2

このコードを Hello world ブートローダーに使用しています。「Hello world\n」を出力する代わりに、「H」を出力してハングします。loadb を使用してメッセージを正常に出力しましたが、同等のように見えるため、このアプローチが機能しない理由がわかりません。

[ORG 0x7c00]
[BITS 16]

    xor ax, ax  ;make it zero
    mov ds, ax

    mov ecx, msg
bios_print:
    mov al, [ecx]
    add ecx,1
    cmp al, 0  ;zero=end of str
    je hang    ;get out
    cmp al,100
    jge hang
    mov ah, 0x0E
    int 0x10
    jmp bios_print


hang:
    jmp hang

msg   db 'Hello World', 13, 10, 0






   times 510-($-$$) db 0
   db 0x55
   db 0xAA

編集: [BITS 64] を [BITS 16] に変更しました

4

1 に答える 1

4

あなたのプログラムは、コーディングしたとおりに正確に動作しています。ASCIIの小文字eは として表され65h、10 進数では 101 に相当します。したがって、cmp al, 100 / jge hangif e(101) is inを実行するalと、ラベル にジャンプしhangます。すべて大丈夫です。:)

あなたの問題の解決策は、単にその行を削除することです。なぜなら、その目的がまったくわからないからです\0

ただし、4 つの追加のヒント:

  • フラグは、(ほぼ) すべての算術演算および論理演算の後に設定されることに注意してください。したがって、特にジャンプの唯一の条件がフラグの 1 つによって表すことができる場合は、実際には a のcmp後にa を実行する必要はありません。addこの場合、add ecx, 1 / cmp al, 0 / je hang非常に単純な に置き換えることができますadd ecx, 1 / jz hang。これにより 2 バイトが節約されるため、これらのブートセクタ条件では非常に価値があります。
  • BIOSルーチンを呼び出すときに、アプリケーションで使用しているレジスタを保持する必要があります。BIOS はさまざまなベンダーから提供されており、一部の BIOS は正常に動作せず、レジスタにあるものを破壊する可能性があります。命令pushaはまさにそれを行います。自分で書いていないコードを呼び出すときは、すべてのランタイム情報を保存するのが一般的な経験則です (ただし、これはより「文明化された」環境では極端に聞こえるかもしれませんが、BIOS および一般的なリアルモード コードはそうではありません)。
  • コンピュータが起動すると、リアル モードになります。このモードでのデフォルトのオペランドとアドレスのサイズは 16 ビットです (アドレスはセグメンテーションによって人為的に 20 ビットに拡張されます)。もちろん、レジスタの 32 ビット部分を使用することもできますが、そのためには命令の前にオペランド サイズのプレフィックスを生成する必要があります。これは別のバイトで、今では 510 個しかありません。:) したがって、mov ecx, msg単純に冗長です。アドレスのオフセット部分が 16 ビットより長くなることはありません。についても同様ですadd ecx, 1。どちらの場合も にecx置き換えるだけです。cx
  • 命令を使用しhltます。それはあなたのCPUの血圧を大幅に低下させます。hltラベルの後hang、ジャンプの前に追加するだけです。
于 2012-04-16T00:51:19.947 に答える