读取硬盘的引导扇区

时间:2013-07-17 07:36:46

标签: assembly x86 real-mode

我正在尝试以实模式学习汇编。我想读取硬盘的启动扇区,所以下面是代码

org 100h

start:
xor ax, ax
mov es, ax    ; ES <- 0
mov cx, 1     ; cylinder 0, sector 1
mov dx, 0080h ; DH = 0 (head), drive = 80h (0th hard disk)
mov bx, buff ; segment offset of the buffer
mov ax, 0201h ; AH = 02 (disk read), AL = 01 (number of sectors to read)
int 13h

jnc .read

 .read:
  mov     ax, cs ; set up segments
  mov     ds, ax
  mov     es, ax
  mov     al, 03h
  mov     ah, 0
  int 10h

 mov     si, buff
 call    print_string

.done:
 jmp     .done


print_string:
lodsb        ; grab a byte from SI

test    al, al  ; logical or AL by itself
jz      .done   ; if the result is zero, get out

mov     ah, 0x0E
int 0x10      ; otherwise, print out the character!
jmp     print_string
.done:
 ret

buff dw 512

我的执行环境是DosBox0.70,exe文件是.COM。 我希望在屏幕上看到512个字节,但是当我运行我的.COM文件时,它只是空白屏幕。我可以在后面看到几个原因

1)给出的代码没有正确地从Bios中断返回(int 13h)。 2)字符串应该以null结束,这不会发生在这里。

但不确定导致它发生的上述原因,如果是,我该如何解决这些问题?

2 个答案:

答案 0 :(得分:3)

磁盘的引导扇区不包含ASCII数据,而是包含代码。概率很高,第一个字节之一将为NULL,并且可能不是可打印代码(例如CR,LF等)。

尝试打印INT 10h打印缓冲区,打印ascii代码,结束0将导致可能根本没有显示任何内容。

您应该将缓冲区的每个字节转换为十六进制字符串,然后将这些字符串打印到显示器。这样,您将获得引导扇区的简单十六进制转储。

答案 1 :(得分:1)

Dos将.com文件加载到它自己选择的某个段中,并将dses设置为该段。您的buff位于该细分受众群中,而不是第0段!你正在读第一个扇区到0,这可能会破坏你的IVT。单独留下es

读取一个扇区后,检查进位标志(表示错误),但是进入.read是否已设置。如果错误,您可能需要重置驱动器并再次尝试读取。你可能想要一个“重试计数器”,所以你不要进入无限循环。

你的buff不会保留512个字节,而是保留两个字节,值为512.因为它位于文件的末尾,这可能不会造成任何伤害,但它不是“正确的”

成功读取扇区后,您可以将其打印为ascii字符,但是要打印所有512个字节,而不是在遇到的前0处停止。十六进制转储可能更具可读性。

如果您的MBR的第一个字节为零,我们处于深水中!有效的bootsector的第一个字节应该是短jmp,后跟nop或近jmp。关于以这种方式启动bootsector我们有点随意,而且大多数BIOS都没有检查,但那就是“应该”在那里。如果将CPU视为第一个字节,CPU会执行什么操作? (提示:这是add

我认为你的两个主要问题是将es设置为零,并在遇到零时停止打印。再试一遍。 FFS,在读取工作可靠之前,不要尝试向驱动器写入任何内容!