4

最近、ブートセクターの書き方を学んでいます。ここに私が学んでいる完全なコードがあります:

org 07c00h
    mov ax, cs
    mov ds, ax
    mov es, ax
    call DispStr
    jmp $

DispStr:
    mov ax, BootMessage
    mov bp, ax
    mov cx, 16
    mov ax, 01301h
    mov bx, 000ch
    mov dl, 0
    int 10h
    ret

BootMessage: db "Hello, OS!"
times 510-($-$$) db 0

dw 0xaa55

システムの起動方法を知っていれば、非常に単純なコードです。結果はHello OS!画面に表示される行です。私が知らないのは最初の行だけです: org 07c00h.

この本は、コード行により、コンパイラーが 7c00h の場所へのアドレスを見つけることができると教えてくれますが、説明は非常にあいまいであり、ここでそれが何に使用されるのか本当にわかりません。ラインorg 07c00hはここで何をしているのですか?

行を削除して、nasm を使用してbinファイルを作成し、bochs を使用して bin ファイルを起動しようとしました。前の「hello OS!」と何も変わりません。画面にも表示されます。

ここで最初の行は何もしていないと言えますか? の用途はorg xxxx何ですか?

4

2 に答える 2

8

アセンブラは、ソースコードの各行をプロセッサ命令に変換し、これらの命令を次々に出力バイナリファイルに生成します。そうすることで、0から上に向かってそのような命令の現在のアドレスをカウントする内部カウンターを維持します。

通常のプログラムをアセンブルしている場合、これらの命令は、アドレス用の空白のスロットがあるオブジェクトファイルのコードセクションに表示されます。このスロットには、後でリンカによって適切なアドレスを入力する必要があるため、問題ありません。

ただし、セクション、再配置、その他のフォーマットを使用せずに、生のマシン命令だけでフラットバイナリファイルをアセンブルする場合、ラベルがどこに表示され、コードとデータのアドレスが何であるかについてのアセンブラの情報はありません。したがって、たとえば、命令があるmov si, someLabel場合、アセンブラは、バイナリファイルの先頭の0から始まるこのラベルのオフセットのみを計算できます。(つまり、デフォルトはORG 0指定しない場合です。)

それが正しくなく、メモリ内のマシン命令+データを他のアドレスから開始する場合、たとえば、プログラムの開始アドレスがソースの先頭に書き込むことによって7C00アセンブラに通知する必要があります。このディレクティブは、アセンブラに、内部アドレスカウンタをからではなくから起動する必要があることを通知します。その結果、そのようなプログラムで使用されるすべてのアドレスが。だけシフトされます。アセンブラは、ラベルごとに計算された各アドレスに単純に追加します。その効果は、ラベルがメモリ内のアドレスに配置されているかのようになります。たとえば、()だけでなく( )7C00org 0x7C007C0007C007C007C487C00 + 4800480000 + 48)、バイナリイメージファイルの先頭から48バイトだけオフセットされているかどうかに関係なく(オフセットでロードした後7C00、適切なアドレスが提供されます)。

これらの「アドレス」は、jmp siまたはのように直接使用される場合、論理アドレス指定mov al, [si]offset一部であり、リアルモードでは、セグメント部分が4だけ左シフトされ、オフセットが追加されるベースを取得します。(したがって、同じ線形アドレスをアドレス指定します。)この部分は、関連するセグメントレジスタに入力したもの、または固定値に設定しなかった場合はBIOSがそこに残したものに由来します。seg:off 07C0:0000000:7C00 7C00segment

、、、および/またはセグメントレジスタが線形アドレス空間のどこにMBRがロードされるか(常に)に一致するように設定されている場合cs、ファイルの最初のバイトは、たとえば、正しく設定されたセグメントベースでそのオフセットを使用すると実際にデータに到達します。 が設定されている場合は、そのラベルにジャンプします。コードがある場所です。つまり、MBRの最初のバイトを参照する場合。 が正しく設定されている場合、そこから2バイトがロードされます。dses7C00es:0jmp sicscs:sics:orgmov ax, [si]ds

あなたの場合、int 10h/ah=13hはをes:bp使用し、絶対アドレス指定の他の使用法はなく、エンコーディングがに依存しない相対ジャンプ/呼び出しのみorgです。使用しているものに一致するように固定値に設定するのではなく、何らかの理由でブートローダーの開始時に設定しesます。これはバグです。ブートローダーは、CS:IP =でMBRにジャンプするBIOSでは機能せず、一致するBIOSのみを使用します。;に置き換えてこれを修正します。DS / ESがCSと異なるかどうかは関係ありません。それだけで、データが実際に存在します。csorg07C0:00000000:7C00orgmov ax,csxor ax,axES: BootMessage-$$ + org


線形アドレスと論理アドレス

あなたの他の質問に関して:7C00ブートローダーの線形物理アドレスです。セグメントがオーバーラップするため、この物理アドレスを論理アドレス(segment:offset)としてさまざまな方法で表すことができます(次のセグメントは10前のセグメントの後に16バイト(16進数)で始まります)。たとえば、最も単純な構成である論理アドレスを使用できます。RAMの先頭から始まる0000:7C00セグメントを使用し、そこからオフセットします。または、 thセグメントである論理アドレスを使用できます。セグメントは互いに16バイト離れて開始することを覚えていますか?したがって、これに(10進数で)を掛けると、次のようになります。07C00007C0:00007C07C010167C00 - 見る?16進アドレスの1つ右にシフトするだけです。:-)ここで、オフセットを追加するだけです。これは0今回なので、7C00物理的にはまだです。メモリ内で始まる0セグメント内のバイト。07C07C00

もちろん、たとえば、のようなより複雑なアドレスを使用することもできます0234:58C0。これは、セグメントがで始まり、それにオフセットを2340追加すると、再び取得されることを意味します:-)しかし、それを行うと混乱する可能性があります。それはすべて、必要な構成によって異なります。物理アドレスをセグメントの開始と見なす場合は、セグメントを使用するだけで、最初の命令がオフセットになるため、ディレクティブを配置する必要はありません。または、配置することができます。ただし、アドレスの下のデータの読み取り/書き込みが必要な場合(たとえば、BIOSデータをのぞいたり、割り込みベクトルをいじったりする場合)、セグメントとオフセットを使用します。58C07C007C0007C00orgorg 07C0007C00これは、最初の命令(バイナリファイルの0番目のバイト)が7C00メモリ内の物理アドレスに配置されることを意味します。org 0x7C00次に、上記の理由からディレクティブを追加する必要があります。


BIOSは、CS:IP = 07C0:0000または0000:7C00のコードにジャンプします。また、DS / ES / SS:SPの値が不明です。xor ax,axを使用している場合は、 /mov ds,axを使用してDSベースをゼロに設定し、どちらの方法でも機能するようにブートローダーを作成する必要がありますorg 0x7c00

すべてのBIOSが主流のソフトウェアで正しく動作する必要がある場合を除いて、BIOSが残した状態についての仮定を回避する堅牢なブートローダーの作成について詳しくは、MichaelPetchのブートローダー開発に関する一般的なヒントを参照してください。(たとえば、線形アドレス0x00007c00で512バイトのMBRをロードし、DLでドライブ番号をロードします)。

ほとんど(?)すべてのBIOSは、CS=0またはCS=07C0のいずれかでMBRを開始しますが、同じ線形アドレスに到達する他のseg:off方法ではありません。しかし、あなたは間違いなくどちらかを想定するべきではありません。

于 2012-06-17T22:15:24.927 に答える
4

これは、アセンブラーとリンカーを1つのステップで実行できる場所です。組織は、リンカ(これらの場合は同じプログラム)に、物理メモリ空間のどこに次のコードを配置するかを指示するアセンブラに指示します。Cコンパイラまたはその他の高級言語コンパイラを使用する場合、多くの場合、コンパイルとリンクの手順が別々になります(ただし、コンパイラはバックグラウンドでリンカーを呼び出すことがよくあります)。ソースは位置に依存しないオブジェクトファイルにコンパイルされ、一部の命令は未実装のままリンクステップで待機します。リンカは、メモリ空間を説明するオブジェクトとリンカスクリプトまたは情報をユーザーから取得し、そこからそのメモリ空間の命令をエンコードします。

User786653はそれを非常にうまく設定し、命令に位置依存のエンコーディングを作成する必要がある場合に備えて、これらの命令が存在するメモリ空間/アドレス自体では理解できないことをアセンブラに伝えます。また、elf、srec、ihexなどのアドレス情報を含むバイナリの場合は、出力バイナリでその情報を使用します。

于 2012-04-24T17:26:37.523 に答える