2012-03-13 1 views
43

私はブートローダとシステムSWの新機能ではありませんが、一般的なプログラムが0x8000で始まる理由の原因はわかりません。私はすでに、通常のC/C++プログラムでアドレス0x8000が開始アドレスとして使用されていることを知っています。一般的なプログラムは通常0x8000から始まるのはなぜですか?

一般的なプログラムのブートローダの最小サイズは0x8000ですか?または、ブートローダ32KBに割り当てる必要のあるROMの最小ブロックサイズは?それとも別の理由がありますか?

これは、歴史的にも論理的にも、仮想アドレスの観点からも知りたいと思います。


あなたの時間と助けに感謝します。 質問をより明確にするために、質問は物理アドレスではなく仮想アドレスと関連しています。

私は基本的に物理メモリのアドレスからRの意見に同意します。

linux(アンドロイドでも)、一般的なRTOS(ニュークリアス、その他、特にARMリンカセクション)などの多様なシステムはありませんが、それらはすべてスタートアドレス汎用プログラムとしてアドレス0x8000を使用します。このエリアにはローダー付きの0x0にあるcrt_begin.o、crt.oなどの名前の が存在します。

したがって、一般的なプログラムのブートローダの最小サイズは、ブート時にBootROMに配置されるブロックサイズ(コールドブート)を考慮すると、ブロックサイズを考慮して32KBです。

うーん、しかし、私はわからない...一般的には

+16

あなたはここでどのようなシステムについて話していますか? –

+2

私はこれのための信頼できる情報源を持っていませんが、私は認定を推測することができます。 特に8ビットのプロセッサでは、[ゼロページ](http://en.wikipedia.org/wiki/Zero_page)という機能がありました。これは、アドレス0x00〜0xFFのメモリセルがより速く実行する。私は6800のような古いMCUにメモリマップされたI/Oレジスタを持っていたので、モトローラがこれを導入したと考えています。 - > – Lundin

+2

したがって、この最初のメモリ領域をRAMセルまたは特殊レジスタ。次に、ゼロ・ページの後に来るアドレス空間の部分は、RAMおよび/またはレジスタと同じ性質であることが理にかなっています。これはたくさんのkbをとるでしょう、多分0x6000かそれ以上のものかもしれません。 私は、ROM(プログラムメモリ)を偶数アドレスに置くと便利であると仮定し、0x8000は便利でした。私はこの疑問に対する答えがモトローラの初期のプロセッサー設計で見つけられることはかなり確信しています。 – Lundin

答えて

19

、すべてのが、最小の組み込みシステムでは、プラットフォームABIの設計者は、NULLポインタデリファレンスをすることができるように、使用中の最下位アドレスを持つ、これまで避けたいです閉じ込められた。 nullポインタが配列または構造体メンバのオフセットで逆参照される場合、数KBの決して有効でないアドレスがあると、安全性が向上します(null_ptr->some_member)。

+3

私はこれが理由だとは思わないが、私はアドレス0が有効でアドレス可能なメモリであると同時に、NVMが8000から始まるいくつかの組み込みシステムで働いている。 – Lundin

+5

...特に、アドレス0x8000はC言語とNULLポインタが普及しました。おそらく、Cが発明される前であったでしょうか? – Lundin

+0

私が理解しているように、HWが正常であるシステムでさえ、 "本当の"ポインタを0にすることは望ましくありません。したがって、 'malloc()'が0を返すと、失敗したことがわかります。したがって、アドレス0がトラップしないシステムでは、通常、メモリは割り込みハンドラなどの特定の目的に割り当てられます。 – MSalters

6

これはシステムによって異なり、プログラムは 異なるシステム上の異なるアドレスから開始します。 Unixでは、アドレス0をヌルポインタとして使用し、 仮想メモリの最初のページをマップしないようにするのが普通です(または Posixでも必要です)。ヌルポインタの逆参照によってセグメント違反が発生します。私はNULLポインタとして アドレス0を使用している他のシステムも同様に動作すると考えています(ただし、それらはどれくらい予約されていますか は異なる場合があります)。 (歴史的には、最初のページを読み込み のみにマップし、0で埋めていた場合、空ポインタは のように振る舞います。空の文字列の場合、""へのポインタです。これは約年になります。 、しかし。)

私も今日、いくつかの組み込みシステムは、アドレスから始まる プログラムをロードしないことを期待する
2
私は最初の32Kは、モニター用に予約された例多くの容疑者と思い

コード/ラムの使用。多くの8051評価ボードでは、居住者のモニタに応じてすべてのアプリケーションに対して0x1000または0x2000にデフォルト設定することは珍しくありませんでした(デバッガとしても機能していました)。

32Kはあなたのu-boot/etcローダースペースかもしれません。

3

これはやや恣意的ですが、少なくともLinuxではリンカによって決まります。一般的な考え方は、NULLポインタの例外を捕まえるためのスペースを確保することです。カーネルスペースNULLポインタの逆参照がカーネルモードで任意のユーザコードを実行するのを防ぐために、linuxはメモリの最下位部分をマッピングしないようにします。 /proc/sys/vm/mmap_min_addrは、マップできる最小のアドレスを制御します(0に変更し、必要に応じてページを0にマップできます)。

Linuxでは、/procを見てメモリマッピングを見ることができます。例えば、

genwitt ~> cat /proc/self/maps 
00400000-0040c000 r-xp 00000000 08:01 354804        /bin/cat 
0060b000-0060c000 r--p 0000b000 08:01 354804        /bin/cat 
0060c000-0060d000 rw-p 0000c000 08:01 354804        /bin/cat 
01dda000-01dfb000 rw-p 00000000 00:00 0         [heap] 
7f5b25913000-7f5b25a97000 r-xp 00000000 08:01 435953      /lib64/libc-2.14.1.so 
7f5b25a97000-7f5b25c97000 ---p 00184000 08:01 435953      /lib64/libc-2.14.1.so 
7f5b25c97000-7f5b25c9b000 r--p 00184000 08:01 435953      /lib64/libc-2.14.1.so 
7f5b25c9b000-7f5b25c9c000 rw-p 00188000 08:01 435953      /lib64/libc-2.14.1.so 
7f5b25c9c000-7f5b25ca1000 rw-p 00000000 00:00 0 
7f5b25ca1000-7f5b25cc2000 r-xp 00000000 08:01 436061      /lib64/ld-2.14.1.so 
7f5b25cd2000-7f5b25e97000 r--p 00000000 08:01 126248      /usr/lib64/locale/locale-archive 
7f5b25e97000-7f5b25e9a000 rw-p 00000000 00:00 0 
7f5b25ec0000-7f5b25ec1000 rw-p 00000000 00:00 0 
7f5b25ec1000-7f5b25ec2000 r--p 00020000 08:01 436061      /lib64/ld-2.14.1.so 
7f5b25ec2000-7f5b25ec3000 rw-p 00021000 08:01 436061      /lib64/ld-2.14.1.so 
7f5b25ec3000-7f5b25ec4000 rw-p 00000000 00:00 0 
7fff18c37000-7fff18c58000 rw-p 00000000 00:00 0       [stack] 
7fff18d0c000-7fff18d0d000 r-xp 00000000 00:00 0       [vdso] 
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0     [vsyscall]
2

私は答えが割り込み処理に関連していると考えています。割り込みハンドラのアドレスはハードウェアで設定されます。インテル8086では、割り込みハンドラコードと対応する割り込み処理ルーチンに直接変換テーブルがありました。おそらく、これはいくつかの組み合わせ回路によって行われたものであり、したがって、順互換性を保つために、毎回の変更を防ぐために、最後ではなくメモリの開始時に配置するほうが賢明でした。したがって、実行開始アドレスはメモリのもう一方の端になります。また、メモリセグメントプログラムをロードするのに十分なコードがそのブロックに含まれていて、そのコードアドレスからコードを実行するための切り替え命令が必要であった。

関連する問題