簡體   English   中英

JMP無法正常工作

[英]JMP not working

好的,所以我一直試圖在Assembly / C中制作一個兩步引導程序,但是我無法使JMP正常工作。 起初我以為讀取失敗,但是在進行以下測試后,我排除了這一點:

__asm__ __volatile__(
    "xorw %ax, %ax;"
    "movw %ax, %ds;"
    "movw %ax, %es;"
    "movb $0x02, %ah;"
    "movb $0x01, %al;"
    "movw $0x7E00, %bx;"
    "movw $0x0003, %cx;"
    "xorb %dh, %dh;"
    "int $0x13;"
    "movb 0x7E00, %al;"
    "movb $0x0e, %ah;"
    "int $0x10;"
    //"jmp 0x7E00"
);

如預期的那樣打印此“ f”(扇區的第一個字節為0x66,這是“ f”的ASCII碼),證明讀取成功並且jmp成為問題。 這是我的代碼:

__asm__(".code16\n");
__asm__(".code16gcc\n");
__asm__("jmpl $0x0000, $main\n");
void main(){
    __asm__ __volatile__(
        "xorw %ax, %ax;"
        "movw %ax, %ds;"
        "movw %ax, %es;"
        "movb $0x02, %ah;"
        "movb $0x01, %al;"
        "movw $0x7E00, %bx;"
        "movw $0x0003, %cx;"
        "xorb %dh, %dh;"
        "int $0x13;"
        "jmp $0x200;"
    );
}

運行時,我的程序只是掛起,這意味着該程序可能正在跳轉到內存中的錯誤位置。 順便說一句,我顯然是在VMWare播放器下以實模式運行它。 我正在使用以下命令對此進行編譯:

gcc -c -0s -march=i686 -ffreestanding -Wall -Werror boot.c -o boot.o
ld -static -Ttest.ld -nostdlib --nmagic -o boot.elf boot.o --no-check-sections
objcopy -0 binary boot.elf boot.bin

這是test.ld

ENTRY(main);
SECTIONS
{
    . = 0x7C00;
    .text : AT(0x7C00)
    {
        *(.test);
    }
    .sig : AT(0x7DFE)
    {
        SHORT(0xAA55);
    }
}

注意:我已經確認這不是內聯匯編程序的問題-我也嘗試了具有相同結果的純匯編實現-我使用C的唯一原因是因為我計划對此進行一點擴展並且我感到更舒服具有C循環和函數...

編輯:我已經上傳了我的軟盤驅動器的前三個行業的在這里

編輯2:我無法使用任何建議使引導加載程序正常工作,並且根據來自@RossRidge的建議,我編寫了同一程序的匯編版本和一個簡單的匯編程序以回顯輸入。 可悲的是這些都不起作用。

引導程序:

org 0x7c00
xor ax, ax
mov ds, ax
mov es, ax
mov ah, 0x02
mov al, 0x01
mov bx, 0x7E00
mov cx, 0x0003
xor dh, dh
int 0x13
jmp 0x7E00

部門3中的計划:

xor ax, ax
int 0x16
mov ah, 0xe
int 0x10

它們都使用nasm Linux/boot.S -o Linux/asm.bin ,其行為與C副本相同。

我很確定您的匯編器生成的跳轉偏移量錯誤,它可能會將0x7e00解釋為當前文本部分中的相對偏移,但是0x7e00描述文件將其映射為0x7c00 ,因此您的跳轉可能轉到0x7c00+0x7e00=0xfa00 作為丑陋的解決方法,您可以嘗試使用jmp 0x200或使用間接跳轉將其隱藏在諸如mov $0x7e00, %ax; jmp *%ax mov $0x7e00, %ax; jmp *%ax 另外, jmp .text+0x200也可以工作。

還要注意的是,在32位C編譯器中寫入16位asm會生成錯誤代碼,加載扇區的第一個字節為0x66也暗示了此錯誤,這是操作數大小覆蓋前綴。 由於編譯器采用32位模式,因此它將生成帶有前綴的16位代碼,當以16位模式運行時,它將切換回32位。 通常,出於這種目的濫用內聯匯編不是一個好主意,您應該使用一個單獨的匯編文件,並確保您告訴匯編程序該代碼適用於16位實模式。

PS:學習使用調試器。


更新:使用nasm boot.asm -o boot.bin組裝時,以下代碼在qemubochs可以正常工作:

org 0x7c00
xor ax, ax
mov ds, ax
mov es, ax
mov ah, 0x02
mov al, 0x01
mov bx, 0x7E00
mov cx, 0x0003
xor dh, dh
int 0x13
jmp 0x7E00

times 510-($-$$) db 0
dw 0xaa55
; second sector
times 512 db 0
; Program in sector 3:
xor ax, ax
int 0x16
mov ah, 0xe
int 0x10
jmp $
times 1536-($-$$) db 0

您可以在此處下載圖片 (數量有限;)。

我寫了很多引導加載程序。

必須有兩(2)個獨立的可執行文件,

1) the boot loader
2) the main code

因此可以在不對引導加載程序進行任何操作的情況下更新已加載的代碼(主程序)。

引導加載程序完成后需要跳轉到已知位置。

主程序需要在已知位置放置一條跳轉指令,該指令跳轉到librt庫中的函數。 (通常是start())

start()將設置I / O,堆等並調用main()

引導加載程序的鏈接器命令文件和主程序的鏈接器命令文件都必須在已知位置的地址上達成一致

通常,兩個鏈接器命令文件的唯一部分中只有已知位置。

引導加載程序必須足夠聰明,才能將主程序的所有部分放置在內存中的正確區域。

最好是主程序采用Motorola S1(或類似格式)而不是原始的.elf或.coff格式。 否則引導加載程序會很快變得很大。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM