bochs hlp 中的 FASM 引导程序

FASM bootloader in bochs hlp

我试图在 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

disk.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只有打印功能。

我不明白,为什么它不起作用。我尝试了很多解决方案的变体,但没有一个在这个列表中起作用。

求求你帮忙

要成功使用BIOS.ReadSectors函数02h,您需要设置它的所有参数!你没有初始化ES段寄存器,也没有在DH寄存器中指定头号。大概你认为所有的寄存器都是从零开始的,但事实并非如此!您的引导加载程序接收的唯一寄存器是 DL 寄存器,其中包含引导驱动器的编号。这将是您需要提供给此功能的号码。

您正在加载偏移地址 0x7E00 处的附加扇区。因为ES=0(假设),这是分段地址0x0000:0x7E00。您可以通过多种方式 jmp 到此地址,但如果您想使用零偏移量来完成此操作,则段部分必须是 0x07E0。这就是分段的工作原理。

您可以在 () and in Michael Petch's answer at () 的回答中阅读有关引导加载程序的更多信息。

这是一个改进版本:

ORG  0x7C00

xor  ax, ax     ; Setup segment registers in accordance with the `ORG 0x7C00`
mov  ds, ax
mov  es, ax
mov  ss, ax
mov  sp, 0x7C00
cld             ; Once at the top of every program

mov  ax, 0x0003
int  0x10

mov  si, boot_msg
call printf

mov  al, 1      ; Number of sectors to read
mov  bx, 0x7E00 ; ES:BX
mov  cx, 0x0002 ; Cylinder, Sector
mov  dh, 0      ; Head, DL is bootdrive
call disk_read

mov  ax, 0x07E0 ; How segmentation works!
mov  ds, ax
mov  es, ax
jmp  0x07E0:0x0000

include 'disk.asm'
include 'printh.asm'

boot_msg db 'R-OS BOOTLOADER       
              ',\
'KERNEL CHS 0 0 1', 0

times 510-($-$$) db 0
dw 0xAA55
;;;;;;;;; kernel! ;;;;;;;;;;
ORG  0x7E00

mov  bh, 0        ; Don't forget to mention the DisplayPage
mov  ah, 0x0E
mov  al, 'X'
int  0x10

cli
hlt
jmp  $-2

times 4096-512-($-$$) db 0

disk.asm 文件中,您试图实现重试计数,但您忘记在发生错误时实际减少计数器。
此外,如果您在此处显示错误消息,那将是致命的,因此请暂停代码。

再次改进版本:

disk_read:
  pusha
  mov  si, 5     ; Retry count
.top:
  mov  ah, 0x02
  int  0x13
  jnc  .OK
  mov  ah, 0x00
  int  0x13
  dec  si
  jnz  .top      ; More tries
  jmp  .fatal
.OK:
  popa
  ret

.msg db 'disk rw err', 0

.fatal:
  mov  bh, 0        ; Don't forget to mention the DisplayPage
  mov  ah, 0x0E
  mov  si, .msg
  lodsb
.next:
  int  0x10
  lodsb
  cmp  al, 0
  jne  .next

  cli
  hlt
  jmp  $-2

printh.asm just have print functions.

包含尽可能多的信息很重要!在我上面改进的代码中,我假设 printf 不会破坏 DL 寄存器。 请确保它至少保留 DX.
如果您将代码包含在 printh.asm 文件中,我已经为您验证过了...