2012-04-15 2 views
2

私はこのコードをHello worldブートローダに使用しています。 "Hello world \ n"を印刷する代わりに、単に 'H'を出力してハングします。私はloadsbを使用してメッセージを正常に出力しましたが、なぜこのアプローチが機能しないのか理解できません。Hello Worldのブートローダが最初の文字の後ろにぶら下がっています

[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 16]

+0

コンピュータが起動したときに '[BITS 64] 'を使用して、16ビットモードになっているのはなぜですか? – Earlz

答えて

4

に[BITS 64]を変更しました。 ASCIIの小文字のeは、65h(小数点では101)になります。したがって、e(101)がalにある場合cmp al, 100/jge hangを実行すると、ラベルhangにジャンプします。すべてが大丈夫です。 :)

あなたの問題を解決するには、実際には何の目的も見当たらないので、単にその行を削除するだけです。文字列がどのように得られたのかを見ると、ループは終了時に終了します終わり。

四余分なヒント、しかし:

  • は、フラグが(ほぼ)すべての算術及び論理演算の後に設定されていることに注意してください。したがって、addの後にcmpを実行する必要はありません。特に、ジャンプの唯一の条件をフラグの1つで表すことができます。この場合、add ecx, 1/cmp al, 0/je hangは非常に単純なadd ecx, 1/jz hangで置き換えることができます。これにより、2バイトが節約されるので、ブートセクタの条件にも価値があります。
  • 本当に BIOSルーチンを呼び出すときにアプリケーションで使用しているレジスタを保持したいとしますか? BIOSはさまざまなベンダーから来ていますが、その中のいくつかはうまくプレイできず、レジスタ内にあるものを破壊するかもしれません。指示pushaはそれだけです。一般的には、あなた自身で書かれていないコードを呼び出すときにはすべての実行時情報を保持するのが一般的な経験則です(しかし、これはもっと文明的な環境で極端に聞こえるかもしれませんが、BIOSと一般的なリアルモードのコードはそうではありません)。
  • コンピュータが起動すると、リアルモードになります。このモードでのデフォルトのオペランドとアドレスサイズは16ビットです(アドレスはセグメント化によって20ビットに人為的に拡張されます)。もちろん、レジスタの32ビット部分を使用することもできますが、命令の前にオペランドサイズの接頭辞を生成する必要があります。これは別のバイトで、今はわずか510バイトしか持っていません。 :)したがって、mov ecx, msgは単純に冗長です - アドレスのオフセット部分は決して16ビットより長くなりません。 add ecx, 1も同じです。どちらの場合も、ecxcxに置き換えてください。
  • hlt命令を使用してください。それはあなたのCPUの血圧をはるかに低くし、実際にはどこにもそれを強調するのに使用されていません。 hangラベルの後でジャンプの前に単にhltを追加してください。
+0

これで問題は解決しました。私は今、本当に馬鹿だと感じる。 – user1133383

関連する問題