2012-10-22 174 views
1

我目前正在開發我的引導程序,但我遇到了問題。引導程序崩潰

我用Bochs的測試引導程序,我編譯引導程序,使磁盤映像:

rm disk.bin 
rm boot.bin 
rm post.bin 
nasm bootloader.asm -o boot.bin 
nasm postmbr.asm -o post.bin 
cat boot.bin post.bin > disk.bin 

這是bootloader.asm:

[BITS 16]  ;Tells the assembler that its a 16 bit code 
[ORG 0x7C00] ;Origin, tell the assembler that where the code will 

MOV SI, HelloString ;Store string pointer to SI 
MOV AH, 02h   ; read sector command 
MOV AL, 01h 
MOV CX, 0001h 
MOV DH, 00h 
MOV DL, 80h ;disk 
MOV AX, 7E00h 
MOV ES, AX ;buffer 
MOV BX, 00h ;offset 
CALL PrintString 
JMP 0x7E00    ;Infinite loop, hang it here. 


PrintCharacter: ;Procedure to print character on screen 
     ;Assume that ASCII value is in register AL 
MOV AH, 0Eh  ;Tell BIOS that we need to print one charater on screen. 
MOV BH, 00h  ;Page no. 
MOV BL, 07h  ;Text attribute 0x07 is lightgrey font on black background 

INT 10h ;Call video interrupt 
RET    ;Return to calling procedure 



PrintString: ;Procedure to print string on screen 
     ;Assume that string starting pointer is in register SI 

next_character: ;Lable to fetch next character from string 
MOV AL, [SI] ;Get a byte from string and store in AL register 
INC SI   ;Increment SI pointer 
OR AL, AL  ;Check if value in AL is zero (end of string) 
JZ exit_function ;If end then return 
CALL PrintCharacter ;Else print the character which is in AL register 
JMP next_character  ;Fetch next character from string 
exit_function: ;End label 
RET    ;Return from procedure 


;Data 
HelloString db 'Loading OS demo...', 0 ;HelloWorld string ending with 0 

TIMES 510 - ($ - $$) db 0  ;Fill the rest of sector with 0 
DW 0xAA55      ;Add boot signature at the end of bootloader 

而且postmbr.asm:

[BITS 16]  ;Tells the assembler that its a 16 bit code 

MOV SI, HelloString ;Store string pointer to SI 
CALL PrintString  ;Call print string procedure 
JMP $   ;Infinite loop, hang it here. 


PrintCharacter: ;Procedure to print character on screen 
     ;Assume that ASCII value is in register AL 
MOV AH, 0x0E ;Tell BIOS that we need to print one charater on screen. 
MOV BH, 0x00 ;Page no. 
MOV BL, 0x07 ;Text attribute 0x07 is lightgrey font on black background 

INT 0x10  ;Call video interrupt 
RET    ;Return to calling procedure 



PrintString: ;Procedure to print string on screen 
     ;Assume that string starting pointer is in register SI 

next_character: ;Lable to fetch next character from string 
MOV AL, [SI] ;Get a byte from string and store in AL register 
INC SI   ;Increment SI pointer 
OR AL, AL  ;Check if value in AL is zero (end of string) 
JZ exit_function ;If end then return 
CALL PrintCharacter ;Else print the character which is in AL register 
JMP next_character  ;Fetch next character from string 
exit_function: ;End label 
RET    ;Return from procedure 


;Data 
HelloString db 'Hello World', 0 ;HelloWorld string ending with 0 

TIMES 512 - ($ - $$) db 0  ;Fill the rest of sector with 0 

這是來自Bochs的crashlog:

00000004661i[BIOS ] $Revision: 11318 $ $Date: 2012-08-06 19:59:54 +0200 (Mo, 06. Aug 2012) $ 
00000319074i[KBD ] reset-disable command received 
00000321808i[BIOS ] Starting rombios32 
00000322242i[BIOS ] Shutdown flag 0 
00000322837i[BIOS ] ram_size=0x02000000 
00000323258i[BIOS ] ram_end=32MB 
00000363787i[BIOS ] Found 1 cpu(s) 
00000377969i[BIOS ] bios_table_addr: 0x000fa438 end=0x000fcc00 
00000396429i[BIOS ] bios_table_cur_addr: 0x000fa438 
00000524046i[VBIOS] VGABios $Id: vgabios.c,v 1.75 2011/10/15 14:07:21 vruppert Exp $ 
00000524117i[BXVGA] VBE known Display Interface b0c0 
00000524149i[BXVGA] VBE known Display Interface b0c5 
00000527074i[VBIOS] VBE Bios $Id: vbe.c,v 1.64 2011/07/19 18:25:05 vruppert Exp $ 
00000800003i[XGUI ] charmap update. Font Height is 16 
00000866078i[BIOS ] ata0-0: PCHS=1/1/2 translation=none LCHS=1/1/2 
00004743252i[BIOS ] IDE time out 
00016726470i[BIOS ] Booting from 0000:7c00 
00016755553e[CPU0 ] write_virtual_word_32(): segment limit violation 
00016755553e[CPU0 ] write_virtual_word_32(): segment limit violation 
00016755553e[CPU0 ] write_virtual_word_32(): segment limit violation 
00016755553i[CPU0 ] CPU is in real mode (active) 
00016755553i[CPU0 ] CS.mode = 16 bit 
00016755553i[CPU0 ] SS.mode = 16 bit 
00016755553i[CPU0 ] EFER = 0x00000000 
00016755553i[CPU0 ] | EAX=000000aa EBX=00000007 ECX=00090001 EDX=00000080 
00016755553i[CPU0 ] | ESP=00000001 EBP=00000000 ESI=000e7c45 EDI=0000ffac 
00016755553i[CPU0 ] | IOPL=0 id vip vif ac vm RF nt of DF if tf SF zf af PF cf 
00016755553i[CPU0 ] | SEG sltr(index|ti|rpl)  base limit G D 
00016755553i[CPU0 ] | CS:0000(0004| 0| 0) 00000000 0000ffff 0 0 
00016755553i[CPU0 ] | DS:0000(0005| 0| 0) 00000000 0000ffff 0 0 
00016755553i[CPU0 ] | SS:0000(0005| 0| 0) 00000000 0000ffff 0 0 
00016755553i[CPU0 ] | ES:7e00(0005| 0| 0) 0007e000 0000ffff 0 0 
00016755553i[CPU0 ] | FS:0000(0005| 0| 0) 00000000 0000ffff 0 0 
00016755553i[CPU0 ] | GS:0000(0005| 0| 0) 00000000 0000ffff 0 0 
00016755553i[CPU0 ] | EIP=0000fd34 (0000fd34) 
00016755553i[CPU0 ] | CR0=0x60000010 CR2=0x00000000 
00016755553i[CPU0 ] | CR3=0x00000000 CR4=0x00000000 
00016755553i[CPU0 ] 0x0000fd34>> pusha : 60 
00016755553e[CPU0 ] exception(): 3rd (12) exception with no resolution, shutdown status is 00h, resetting 
00016755553i[SYS ] bx_pc_system_c::Reset(HARDWARE) called 
00016755553i[CPU0 ] cpu hardware reset 
00016755553i[APIC0] allocate APIC id=0 (MMIO enabled) to 0x00000000fee00000 
00016755553i[CPU0 ] CPUID[0x00000000]: 00000002 68747541 444d4163 69746e65 
00016755553i[CPU0 ] CPUID[0x00000001]: 00000633 00010800 00000008 17cbfbff 
00016755553i[CPU0 ] CPUID[0x00000002]: 00000000 00000000 00000000 00000000 
00016755553i[CPU0 ] CPUID[0x80000000]: 80000008 68747541 444d4163 69746e65 
00016755553i[CPU0 ] CPUID[0x80000001]: 00000633 00000000 00000000 c1c3f3ff 
00016755553i[CPU0 ] CPUID[0x80000002]: 20444d41 6c687441 74286e6f 7020296d 
00016755553i[CPU0 ] CPUID[0x80000003]: 65636f72 726f7373 00000000 00000000 
00016755553i[CPU0 ] CPUID[0x80000004]: 00000000 00000000 00000000 00000000 
00016755553i[CPU0 ] CPUID[0x80000005]: 01ff01ff 01ff01ff 40020140 40020140 
00016755553i[CPU0 ] CPUID[0x80000006]: 00000000 42004200 02008140 00000000 
00016755553i[CPU0 ] CPUID[0x80000007]: 00000000 00000000 00000000 00000000 
00016755553i[CPU0 ] CPUID[0x80000008]: 00002028 00000000 00000000 00000000 
00016755553i[  ] reset of 'cmos' plugin device by virtual method 
00016755553i[  ] reset of 'dma' plugin device by virtual method 
00016755553i[  ] reset of 'pic' plugin device by virtual method 
00016755553i[  ] reset of 'pit' plugin device by virtual method 
00016755553i[  ] reset of 'floppy' plugin device by virtual method 
00016755553i[  ] reset of 'vga' plugin device by virtual method 
00016755553i[  ] reset of 'ioapic' plugin device by virtual method 
00016755553i[  ] reset of 'keyboard' plugin device by virtual method 
00016755553i[  ] reset of 'harddrv' plugin device by virtual method 
00016755553i[  ] reset of 'unmapped' plugin device by virtual method 
00016755553i[  ] reset of 'biosdev' plugin device by virtual method 
00016755553i[  ] reset of 'speaker' plugin device by virtual method 
00016755553i[  ] reset of 'extfpuirq' plugin device by virtual method 
00016755553i[  ] reset of 'parallel' plugin device by virtual method 
00016755553i[  ] reset of 'serial' plugin device by virtual method 

這是Bochs的配置文件:

# configuration file generated by Bochs 
plugin_ctrl: unmapped=1, biosdev=1, speaker=1, extfpuirq=1, parallel=1, serial=1 
config_interface: textconfig 
display_library: x 
memory: host=32, guest=32 
romimage: file="/usr/share/bochs/BIOS-bochs-latest" 
vgaromimage: file="/usr/share/bochs/VGABIOS-lgpl-latest" 
boot: disk 
floppy_bootsig_check: disabled=0 
# no floppya 
# no floppyb 
ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14 
ata0-master: type=disk, mode=flat, translation=auto, path="disk.bin", cylinders=1, heads=1, spt=2, biosdetect=auto, model="Generic 1234" 
ata1: enabled=1, ioaddr1=0x170, ioaddr2=0x370, irq=15 
ata2: enabled=0 
ata3: enabled=0 
pci: enabled=0 
vga: extension=vbe, update_freq=5 
cpu: count=1, ips=4000000, model=bx_generic, reset_on_triple_fault=1, cpuid_limit_winnt=0, ignore_bad_msrs=1, mwait_is_nop=0 
cpuid: family=6, model=0x03, stepping=3, mmx=1, apic=xapic, sse=sse2, sse4a=0, sep=1, aes=0, xsave=0, xsaveopt=0, movbe=0, adx=0, smep=0, mwait=1 
cpuid: vendor_string="AuthenticAMD" 
cpuid: brand_string="AMD Athlon(tm) processor" 

print_timestamps: enabled=0 
port_e9_hack: enabled=0 
private_colormap: enabled=0 
clock: sync=none, time0=local, rtc_sync=0 
# no cmosimage 
# no loader 
log: - 
logprefix: %t%e%d 
panic: action=ask 
error: action=report 
info: action=report 
debug: action=ignore 
keyboard: type=mf, serial_delay=250, paste_delay=100000, keymap= 
user_shortcut: keys=none 
mouse: enabled=0, type=ps2, toggle=ctrl+mbutton 
parport1: enabled=1, file="" 
parport2: enabled=0 
com1: enabled=1, mode=null, dev="" 
com2: enabled=0 
com3: enabled=0 
com4: enabled=0 

我不知道什麼是錯的,我沒有測試在其他平臺上我的bootloader。

+0

奇怪的是,沒有任何寄存器內容的轉儲。也。除非我錯過了一些東西,似乎沒有任何建議引導扇區加載和執行發生。 –

+0

@AlexeyFrunze我已經用文件(這個來自控制檯輸出) – djmati11

回答

3

好了,崩潰在pusha指令試圖推寄存器到破壞堆棧轉儲unambiguosly點。

相關位:

00016755553e [CPU0] write_virtual_word_32():段限制違反
00016755553e [CPU0] write_virtual_word_32():段限制違反
00016755553e [CPU0] write_virtual_word_32():段違反限制
00016755553i [CPU0] | EAX = 000000aa EBX = 00000007 ECX = 00090001 EDX = 00000080
00016755553i [CPU0] | ESP = 00000001 EBP = 00000000 ESI = 000e7c45 EDI = 0000ffac
00016755553i [CPU0] | SEG sltr(index | ti | rpl)base limit G D
00016755553i [CPU0] | CS:0000(0004 | 0 | 0)00000000 0000ffff 0 0
00016755553i [CPU0] | SS:0000(0005 | 0 | 0)00000000 0000ffff 0 0
00016755553i [CPU0] | EIP = 0000fd34(0000fd34)
00016755553i [CPU0] 0x0000fd34 >> PUSHA:60
00016755553e [CPU0] 例外():第三(12),沒有分辨率例外,關機狀態是00h時,復位

當寫入數據到堆棧時,該指令嘗試跨越偏移量爲0的下段邊界。並導致不可恢復的異常和下面的重置。

最可能的原因是跳轉到錯誤的位置並執行隨機的東西,可能是數據。

看這個指令:CPU執行它

JMP 0x7E00    ;Infinite loop, hang it here. 

後,CS:IP將是0:0x7E00。

現在看看你的postmbr.asm:

[BITS 16]  ;Tells the assembler that its a 16 bit code 

MOV SI, HelloString ;Store string pointer to SI 
... 

那裏面有沒有org,在這種情況下org 0是隱含的。

因此,這部分代碼被編譯與IP當它開始和所有偏移從代碼的這部分開始計數,= 0,從邏輯上講,這意味着假設CS = DS = 0也是錯誤的。但是你會在寄存器中出現錯誤的意外值。

所以這段代碼不會按預期執行。 IOW,它可以做任何事情,我敢打賭,它會導致堆棧破壞和崩潰。

這裏的關鍵是:x86代碼不是位置獨立的。

您應插入適當orgorg 0x7E00)或相應地設置寄存器和做一個遠跳轉到這部分代碼(例如jmp 0x7e0:0使用)。

更新:現在是我的教訓時間...上述問題確實存在。但是,正如@ughoavgfhw所指出的那樣,還有一個幾乎在同一個地方,但稍早出現。第二個512字節永遠不會加載。是的。 BIOS本身只加載第一個扇區。第一個扇區必須通過明確調用BIOS int 13h來加載第二個扇區。

+0

我已將'[ORG 0x7E00]'添加到postmbr.asm,但仍然是相同的錯誤。 – djmati11

+0

你沒看過更新和其他答案/評論嗎?這不是唯一的問題。第二部分沒有加載到內存中。 Jmp 0x7e00跳入垃圾。 –

+0

可能聽起來像個愚蠢的問題,但是:int 13h部分不會將代碼加載到RAM中? – djmati11

-1

當您的引導程序開始運行時,大多數寄存器的值可能是任何值。這包括堆棧指針。您的崩潰報告顯示esp爲1,並且由於pusha指令出現三重故障而發生崩潰,這基本上意味着您嘗試將數據推送到不存在的堆棧上。這是因爲你從不設置堆棧指針,所以你不知道它在哪裏。您需要將堆棧指針設置爲您所做的第一件事情之一。我建議將其設置爲0x7c00,以便將其置於您的代碼下方。將這個近引導程序的開頭:

mov sp, 0x7C00 
+0

-1更新了正確的crashlog的crashlog。這不是問題。如果是這樣,ISR將沒有機會工作。看到我的答案。 –

+0

@AlexeyFrunze ISRs會有一個機會,因爲堆棧沒有*開始*在1.雖然有可能(看起來很可能)你發現了實際問題,但我的答案仍然指出bootloader中存在嚴重缺陷,導致類似的結果。 – ughoavgfhw

+0

'sp = 1'沒有出現。這是位置相關代碼錯誤執行的結果。我同意這個缺陷,但它沒有解決問題中的原始問題。 –

1
JMP 0x7E00 

在這一點上跳到0x7E00會導致意外的行爲。它看起來像你想跳轉到post.bin,你期望在0x7E00加載。不是。 BIOS只裝載了1個扇區,boot.bin,0x7C00。您將不得不手動加載任何其他扇區。