2012-10-22 175 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。您将不得不手动加载任何其他扇区。