28

単純なブートローダーがどのように機能するかを理解するのに苦労しています。私が話しているブートローダーは、MITのコース「オペレーティングシステムエンジニアリング」からのものです。

まず、BIOSが実行するアセンブリコードの一部を示します。

[f000:fec3]    0xffec3: lidtw  %cs:0x7908
[f000:fec9]    0xffec9: lgdtw  %cs:0x7948
[f000:fecf]    0xffecf: mov    %cr0,%eax
[f000:fed2]    0xffed2: or     $0x1,%eax
[f000:fed6]    0xffed6: mov    %eax,%cr0
[f000:fed9]    0xffed9: ljmpl  $0x8,$0xffee1

このコードは、見た目から、割り込みテーブルと記述子テーブルを設定してから、プロテクトモードをオンにします。

  1. BIOSでプロテクトモードに入るのはなぜですか?ブートローダーをリアルモードで実行するべきではありません(ところで、なぜリアルモードで実行する必要があるのですか?)
  2. 私は検索しましたが、ljmpl命令がどのように機能するかを正確にどこにも見つけられませんでした。これは、ljmpおよび通常のjmpとの違いです。誰かが正しい方向を指し示していただければ幸いです。
  3. なぜジャンプを実行するのですか?この指導の目的は何ですか?

ブートローダーコードに移ります-

# Switch from real to protected mode, using a bootstrap GDT
# and segment translation that makes virtual addresses
# identical to their physical addresses, so that the
# effective memory map does not change during the switch.
lgdt    gdtdesc
movl    %cr0, %eax
orl     $CR0_PE_ON, %eax
movl    %eax, %cr0

# Jump to next instruction, but in 32-bit code segment.
# Switches processor into 32-bit mode.
ljmp    $PROT_MODE_CSEG, $protcseg
  1. プロセッサがリアルモードになっていると表示されますが、BIOSがプロテクトモードに切り替わるのを見たばかりです...混乱しています-どうすればこれが可能になるのでしょうか。
  2. 32ビットモードに切り替えるにはどうすればよいですか?ljmp命令が原因で、プロセッサが魔法のように32ビットモードになる原因は何ですか?

そして、私が理解していないもう1つのことは、gdbを使用してブートローダーの実行を追跡すると、次の命令が実行されていることを確認します(これは、ブートローダーコードのljmp命令です)。

ljmp   $0x8,$0x7c32

しかし、.asmファイルを見ると、次のことがわかりました。

ljmp   $0xb866,$0x87c32

ここで完全に失われました-.asmファイルに書き込まれた命令と実行された命令がどうして違うのですか?私はこれがプロテクトモードとそれがアドレスをどのように変換するかに関係しているという予感がありますが、私は実際にはそれを理解していません。

助けていただければ幸いです!

4

2 に答える 2

30
  1. 一部のBIOS実装は、ブートローダーに入る前に保護モードになります。ほとんどはしません。BIOSが短期間プロテクトモードに切り替わり、ブートローダーに進む前に元に戻る可能性があります。これにより、プロテクトモードの利点の一部(デフォルトのアドレスサイズが32ビットなど)を使用できるようになります。ブートローダーをリアルモードにする必要がある理由は、ほとんどのBIOS機能がリアルモードでのみ機能するため、それらを使用するにはリアルモードである必要があります。

  2. ljmpは、ジャンプ先のアドレスに加えて、切り替え先のコードセグメントを指定します。それらは非常に似ているため、(少なくともGASでは)アセンブラは2つのオペランドを持つjmpをljmpに切り替えます。

  3. ljmpは、csレジスタを変更する唯一の方法の1つです。csレジスタにはGDTのコードセグメントのセレクタが含まれている必要があるため、これはプロテクトモードをアクティブにするために実行する必要があります。(知りたい場合は、csを変更する他の方法は、far call、far return、およびinterrupt returnです)

  4. 項目1を参照してください。BIOSがリアルモードに戻るか、このブートローダーはこのBIOSで動作しません。

  5. 項目3を参照してください。csを変更して32ビットコードセグメントを指定するため、プロセッサは32ビットモードになります。

  6. .asmファイルを見ると、命令はアドレスサイズが32ビットであるかのように解釈されましたが、GDBはアドレスサイズが16ビットであるかのように解釈しました。命令のアドレスのデータは0xEA327C 08 0066B8になります。EAは走り幅跳びのオペコードです。32ビットアドレス空間では、アドレスは0x87C32のアドレスに対して次の4バイトを使用して指定されますが、16ビットアドレス空間では、0x7C32のアドレスに対して2バイトのみが使用されます。アドレスの後の2バイトは、要求されたコードセグメントを指定します。これは、32ビットモードでは0xB866、16ビットモードでは0x0008になります。0x66 B8は次の命令の開始であり、16ビットのイミディエート値をaxレジスタに移動します。これは、おそらくプロテクトモードのデータセグメントを設定するためです。

于 2011-03-06T22:30:38.867 に答える
2

BIOSでプロテクトモードに入るのはなぜですか?ブートローダーをリアルモードで実行するべきではありません(ところで、なぜリアルモードで実行する必要があるのですか?)

プロテクトモードは、リアルモードよりもはるかに多くの機能を提供します。基本的に、Intel CPUの保護リング特権メカニズム(http://en.wikipedia.org/wiki/Ring_(computer_security)、32ビットモードの実行など)です。

私は検索しましたが、ljmpl命令がどのように機能するかを正確にどこにも見つけられませんでした。これは、ljmpおよび通常のjmpとの違いです。誰かが正しい方向を指し示していただければ幸いです。

ljmplとljmpは、ここでは文脈上同じです。

なぜジャンプを実行するのですか?この指導の目的は何ですか?

これは、Intelマニュアルに記載されているように必要であり、以下に示すコードにもインラインで記載されています。

実在から保護への移行については、次のステージ2ブートローダーに実装されています。

http://src.illumos.org/source/xref/illumos-gate/usr/src/grub/grub-0.97/stage2/asm.S#real_to_prot

974   /* load the GDT register */
975   DATA32  ADDR32  lgdt    gdtdesc
976 
977   /* turn on protected mode */
978   movl    %cr0, %eax
979   orl $CR0_PE_ON, %eax
980   movl    %eax, %cr0
981 
982   /* jump to relocation, flush prefetch queue, and reload %cs */
983   DATA32  ljmp    $PROT_MODE_CSEG, $protcseg
984

ご覧のとおり、コードの各部分には機能があり、ljmpは基本的に、Intelのマニュアルで要求されているように、プリフェッチキューをフラッシュするためのものです。どこにあるのか思い出せません。

于 2012-02-18T13:57:54.353 に答える