【发布时间】:2021-11-20 16:29:25
【问题描述】:
我试图在 fasm 程序集上编写自己的引导加载程序,但没有成功。
结果: 预取:EIP 00010000 > CS.limit 0000ffff
代码:
org 0x7C00
mov ax, 0x02
int 0x10
mov si, boot_msg
call printf
mov al, 0x01 ; secror to read
mov bx, 0x7E00 ; dest
mov cx, 0x0002 ; cylinder:sector
mov dl, 0x01 ; floppy
call disk_read
mov ax, 0x7E00
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
jmp 0x7E00:0x0000
include 'disk.asm'
include 'printh.asm'
boot_msg db 'R-OS BOOTLOADER
',\
'KERNEL CHS 0 0 1', 0x00
times 510-$+$$ db 0x00
dw 0xAA55
;;;;;;;;; kernel! ;;;;;;;;;;
org 0x7E00
mov ah, 0x0E
mov al, 'X'
int 0x10
cli hlt
times 4096-512-$+$$ db 0x00
磁盘.asm:
disk_read:
pusha
mov si, 0x02
.top:
mov ah, 0x02
int 0x13
jnc .end
xor ah, ah
int 0x13
jnc .top
jc .err
.end:
popa
ret
.msg db 'disk rw err', 0x00
.err:
popa
pusha
mov ah, 0x0E
mov si, .msg
jmp .l
.l:
lodsb
cmp al, 0x00
je .end
int 0x10
printh.asm 只有打印功能。
我不明白,为什么它不起作用。我尝试了很多解决方案的变体,但没有一个在这个列表中工作。
请帮忙
【问题讨论】:
-
7E00h:0不是线性地址 07E00h,并且你没有在磁盘读取之前初始化es。 -
jmp .l在这里没用。int 0x10作为disk_read.err中的最后一条指令意味着执行将失败。popa然后pusha这里不需要。jnc后跟jc使第二个无条件。大概您打算使用si作为重试计数,因为它没用。如果您的磁盘读取错误处理有效,则该函数将在出错时返回给调用者,而不向调用者指示任何错误。 -
cli\hlt应该在两行(也许 FASM 是宽容的),然后是无条件的jmp回到hlt,以保持稳健性。dl= 1 从第二个软盘驱动器读取,如果要从第一个驱动器读取,请使用零。 (或者将dl保留为由ROM-BIOS 加载程序初始化,以使用您从中加载的相同单元。)设置ss之后的下一条指令应该是设置sp的指令。建议在从磁盘读取之前初始化ss:sp,因为之前的堆栈设置可能会与您的扇区读取缓冲区发生冲突。
标签: assembly bootloader boot fasm