「Windows を直接起動する」と言うので、物理 PC を使用していると思います。今後の注意事項: 開発には常にエミュレーターを使用してください。それはただ簡単です。私は Bochs for OSDeving が好きです。なぜなら、Bochs には優れたデバッグ機能があるからです。さて、可能な解決策に。
0x7C00 ロード アドレスの IBM PC の非公式仕様を破るバグのある BIOS がたくさんあります。
これにより、アセンブル中はいつでもメモリアドレスなどに多くの問題が発生する可能性があります。したがって、冒頭を次のようにします。
[BITS 16] ;tell the assembler that its a 16 bit code
[ORG 0x7C00] ;this tells the assembler where the code will be loaded at when it runs on your machine. It uses this to compute the absolute addresses of labels and such.
jmp word 0:flush ;#FAR jump so that you set CS to 0. (the first argument is what segment to jump to. The argument(after the `:`) is what offset to jump to)
;# Without the far jmp, CS could be `0x7C0` or something similar, which will means that where the assembler thinks the code is loaded and where your computer loaded the code is different. Which in turn messes up the absolute addresses of labels.
flush: ;#We go to here, but we do it ABSOLUTE. So with this, we can reset the segment and offset of where our code is loaded.
mov BP,0 ;#use BP as a temp register
mov DS,BP ;#can not assign segment registers a literal number. You have to assign to a register first.
mov ES,BP ;#do the same here too
;#without setting DS and ES, they could have been loaded with the old 0x7C0, which would mess up absolute address calculations for data.
参照してください。一部の負荷0x07C0:0000
とほとんどの負荷 (およびその適切と見なされる) を参照してください0x0000:7C00
。これは同じフラット アドレスですが、セグメント設定が異なると、絶対メモリ アドレスが実際に台無しになる可能性があります。それでは、アセンブラの「魔法」を取り除いて、それがどのように見えるか見てみましょう (これでアドレスが完全に正しいことを保証するわけではないことに注意してください。すべてのオペコードのサイズはわかりません)。
jmp word 0:0x7C04 ;# 0x7C04 is the address of the `flush` label
...
したがって、絶対アドレスにジャンプします。
さて。これをしないとどうなりますか?
たとえば、次のプログラムを使用します。
mov ax,[mydata]
hlt
mydata: dw 500 ;#just some data
これは次のようなものに分解されます
mov ax,[0x7C06]
ああ、それは絶対アドレス指定を使用しているので、どうしてうまくいかないのでしょうか? では、DS が実際に0x7C0
. 次に、アセンブラが期待するものを取得する代わりに、同じフラットアドレスではない0:0x7C06
ものを取得します。0x7C0:0x7C06
これが理解に役立つことを願っています。ただし、これは本当に複雑なトピックであり、完全に理解するには低レベルのプログラミングが必要です。