【发布时间】:2019-09-05 18:30:19
【问题描述】:
我想编写一个简单的引导加载程序。但是,从磁盘读取 2 个扇区后,我的引导扇区无法打印 int 10h 的字符串,ah=0Eh
在我调用 int 13h, ah=02h 之前它可以工作
我的代码:
;-------------------------------------------------------------------------------
; boot.asm - First boot sector
;-------------------------------------------------------------------------------
org 0x7c00
bits 16
jmp word _start
;-------------------------------------------------------------------------------
; BIOS Parameter Block (FAT32)
;-------------------------------------------------------------------------------
BS_OEMName: db "TestOS "
BPB_BytesPerSector: dw 512
BPB_SectorsPerCluster: db 1
BPB_ReservedSectors: dw 4
BPB_FATCount: db 2
BPB_RootEntryCount: dw 0
BPB_TotalSectors16: dw 0
BPB_Media: db 0xf0
BPB_FATSize16: dw 0
BPB_SectorsPerTrack: dw 18
BPB_HeadCount: dw 2
BPB_HiddenSectors: dd 0
BPB_TotalSectors32: dd 2880
BPB_FATSize32: dd 23
BPB_ExtendedFlags: dw 0x0000
BPB_FileSystemVersion: dw 0
BPB_RootCluster: dd 2
BPB_FSInfo: dw 3
BPB_BackupBootSector: dw 0
BPB_Reserved: times 12 db 0
BS_DriveNum: db 0x00
BS_Reserved1: db 0x0
BS_BootSignature: db 0x29
BS_VolumeID: dd 0x12345678
BS_VolumeLabel: db "TestOS "
BS_FileSystemType: db "FAT32 "
;-------------------------------------------------------------------------------
_start:
; Initialize segment registers and set up stack at 0x7c00 (grows downwards)
cli
xor ax, ax
mov ds, ax
mov es, ax
mov ss, ax
mov sp, 0x7a00
sti
; Save drive number in DL
mov [BS_DriveNum], dl
; Copy this boot sector from 0x7c00 to 0x7a00
mov si, 0x7c00
mov di, 0x7a00
mov cx, 512
cld
rep movsb
; Jump to the new location
jmp 0x0000:(_continue - 0x200)
_continue:
; Reset boot disk (try it 3 times before error message is printed)
mov cx, 4
_reset:
sub cx, 1
cmp cx, 0
je _error
mov ah, 0
mov dl, [BS_DriveNum]
int 0x13
jc _reset
; Load second boot sector into memory at 0x7c00 (try it 3 times before error message is printed)
mov cx, 4
_load:
sub cx, 1
cmp cx, 0
je _error
mov ah, 0x02
mov al, 2
mov ch, 0
mov cl, 3
mov dh, 0
mov dl, [BS_DriveNum]
mov bx, 0x7c00
; IT STILL WORKS HERE <--------
int 0x13
; IT DOESN'T WORK ANYMORE <--------
jc _load
mov si, error_msg
call print
; Jump to the second boot sector
; End of program
_end:
hlt
jmp _end
_error:
mov si, error_msg
call print
jmp _end
;-------------------------------------------------------------------------------
; Prints a zero-terminated string onto the screen
; SI = string to write
;-------------------------------------------------------------------------------
print:
pusha
.print_lbl:
lodsb
cmp al, 0
je .finished
mov ah, 0x0e
mov bl, 0
int 0x10
jmp .print_lbl
.finished:
popa
ret
;-------------------------------------------------------------------------------
error_msg: db "Operating system not found", 0xa, 0xd, "Press Ctrl+Alt+Del to reboot", 0x0
; Fill the rest of the 512 bytes with 0, byte 510 and 511
; contains 0xaa55 (boot signature for BIOS)
times 510 - ($ - $$) db 0
dw 0xaa55
我搜索了谷歌来解决这个问题,但之前没有其他人遇到过这个问题。
我用bochs调试了一下,发现...
我可以通过将字符写入 b800:0000 来在屏幕上打印一些东西
正确读取了 2 个扇区。我用 bochs 在 0x7c00 处转储了内存,它显示了正确的值
我的引导加载程序没有处于无限循环中,因为使用 bochs 进行调试表明它在读取 2 个扇区后执行指令
我不知道如何解决这个问题。谁能帮帮我?
【问题讨论】:
-
您使用了
org 7c00h,但随后将代码复制到其他地方并用加载的扇区覆盖了原始代码。当然,除了复制的代码仍然引用原始代码,因此它不会工作。 -
以后有没有可能在代码中重新定义org指令?如果我尝试它,nasm 会说错误
-
如果在读取第二个扇区时出现错误,您的代码将陷入无限循环,因为您用于计算重试次数 (CX) 的寄存器被覆盖。您可能最好使用 0x7a00 的 org 并在跳转到重新定位的引导扇区后保存 DL。
-
您可以使用
org 0并更改分段。 -
我会试试这个
标签: assembly x86 nasm bootloader bios