web-dev-qa-db-ja.com

一般的なプログラムが通常0x8000から始まるのはなぜですか?

ブートローダーとシステムソフトウェアは初めてではありませんが、一般的なプログラムが0x8000で始まる理由の原因はわかりません。アドレス0x8000が通常のC/C++プログラムの開始アドレスとして使用されていることはすでに知っています。

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

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


お時間をいただきありがとうございました。質問をより明確にするために、質問は物理アドレスではなく仮想アドレスに関連しています。

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

Linuxなどの多様な特定のシステムは言うまでもなく(Androidでも)、一般的なRTOS(中核など)、特にARMリンカーセクション) 、それらはすべて、アドレス0x8000を開始アドレス一般プログラムとして使用します。この領域には、ローダーを使用して0x0にあるcrt_begin.o、crt.oなどの名前が付けられています。

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

うーん、でもわからないけど...

43
OfusJK

一般に、最小の組み込みシステムを除くすべてにおいて、プラットフォームABI設計者は、ヌルポインター逆参照がトラップされるように、使用中の最小アドレスを使用しないようにしたいと考えています。無効なアドレスが数KBあると、null_ptr->some_memberのように、配列または構造体のメンバーオフセットを使用してnullポインターが逆参照される場合に、安全性が向上します。

これはシステムに依存し、プログラムは異なるシステムの異なるアドレスで開始します。 Unixでは、アドレス0をnullポインタとして使用し、仮想メモリの最初のページをマップしないのが通常(またはPosixでも必要になる場合があります)なので、nullポインタを逆参照するとセグメント違反が発生します。私は、アドレス0をnullポインターとして使用している他のシステムも同様に動作すると思います(ただし、予約する量は異なる場合があります)。 (歴史的には、最初のページを読み取り専用としてマップし、ゼロで埋めることが一般的でした。ヌルポインターは、空の文字列(""へのポインター)のように動作します。25ほど戻ります。年、ただし。)

今日でも、一部の組み込みシステムはアドレス0からプログラムをロードすることを期待しています。

6
James Kanze

これはいくぶん恣意的で、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 [ヒープ] 
 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]
3
Kenneth Waters

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

2
user796530

多くの場合、最初の32Kはモニターのコード/ RAMの使用のために予約されていたと思います。 8051評価ボードの多くでは、常駐モニターに応じてすべてのアプリのデフォルトを0x1000または0x2000にすることはそれほど珍しくありませんでした(一部はデバッガーとしても機能しました)。

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

2
Tom St Denis