2012-04-15 26 views
2

我正在使用此代碼來處理Hello world引導程序。它不是打印出「Hello world \ n」,而是打印出「H」並掛起。我已經使用loadb成功地打印出消息,但我不明白爲什麼這種方法不起作用,因爲它看起來相當。第一個字符後掛起的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 64]到[位16]

+0

爲什麼在計算機啓動時使用'[BITS 64]'生成64位彙編代碼,它處於16位模式 – Earlz 2012-04-15 23:53:12

回答

4

你的程序在你編碼它的方式工作完全吻合。 ASCII中的小寫e表示爲65h,其等於101十進制。因此,如果e(101)在al中,則執行cmp al, 100/jge hang會導致跳轉到標籤hang。一切安好。 :)

您的問題的解決方案將簡單地刪除該行,因爲我沒有真正看到它的任何目的 - 看到你如何讓你的字符串終止於\0,循環將達到時,結束。

四個額外的提示,但:

  • 記住標誌後(幾乎)所有的算術和邏輯操作設置。因此,在add之後確實不需要執行cmp,特別是如果跳轉的唯一條件可以由其中一個標誌表示。在這種情況下,add ecx, 1/cmp al, 0/je hang可以用一個非常簡單的add ecx, 1/jz hang來代替。這爲您節省了兩個字節,在引導區條件中非常有用。
  • 確實確實想要在調用BIOS例程時保留您在應用程序中使用的寄存器。 BIOS來自不同的供應商,其中一些可能不會很好地發揮作用並破壞你的註冊表。指令pusha就是這樣做的。在調用任何你自己沒有寫過的代碼時,保存所有的運行時信息通常是一條經驗法則(雖然在更「文明」的環境中這可能聽起來極端 - 但BIOS和一般實模式代碼不是一個)。
  • 計算機啓動時,它處於實模式。此模式下的默認操作數和地址大小爲16位(地址通過分段20位人工擴展)。當然,您可以使用寄存器的32位部分,但必須在指令發生之前生成操作數大小前綴。這是另一個字節,現在你只有510個字節。 :)因此,mov ecx, msg只是多餘的 - 地址的偏移部分永遠不會超過16位。 add ecx, 1也一樣。在這兩種情況下,只需將ecx替換爲cx即可。使用指令hlt。它使得你的CPU血壓低得多,而且在整個過程中都沒有用處。只需在hang標籤後跳轉前添加hlt即可。
+0

謝謝你這樣做解決了我的問題。我現在覺得很蠢。 – user1133383 2012-04-16 01:13:20