【发布时间】:2020-09-25 18:40:40
【问题描述】:
我最近编写了一个 x86 'bootloader' 程序,它在 BIOS 跳转到我的程序后显示硬件寄存器的值。出于测试的目的,我将AX寄存器设置为一个已知值,以确保程序正确运行。
BITS 16
%macro pad 1-2 0
times %1 - ($ - $$) db %2
%endmacro
[org 0x7C00]
CLD ; clear direction flag (forward direction)
CLI ; clear interrupt flag (disable interrupts, opposite of 65xx)
MOV [0x8000], AX ; display all registers,
MOV [0x8004], BX ; including stack,
MOV [0x8008], CX ; segment, & extra
MOV [0x800C], DX ; registers
MOV [0x8010], SP
MOV [0x8014], BP
MOV [0x8018], SI
MOV [0x801C], DI
MOV [0x8020], CS
MOV [0x8024], SS ; we also display DS register,
MOV [0x8028], ES ; so we can't modify it or
MOV [0x802C], DS ; we'll loose our data
MOV [0x8030], FS
MOV [0x8034], GS
MOV AX, 0x0123 ; write 0x0123 to [0x8000]
MOV [0x8000], AX ; for debugging
MOV DI, 0x804C ; DI is pointer to address 0x804C
; (temporary data)
MOV AH, 0x02
MOV BH, 0x00 ; video page 0?
MOV DX, 0x0401
INT 0x10 ; move cursor to XY:($01, $04)
; display register data
MOV AL, 'A'
CALL printXl ; print 'AX:'
MOV DX, [0x8000] ; recall value of AX register
; (set to 0x0123 for test)
CALL printascii ; print 16-bit value @ [0x8000]
;... ; omitted code: display other registers
MOV AH, 0x00 ; wait for keyboard press
INT 0x16
INT 0x18 ; boot Windows
printXl:
MOV AH, 0x0E
XOR BX, BX
INT 0x10 ; display character in 'AL'
MOV AL, 'X'
; falls through
prnt: ; referenced in omitted code
MOV AH, 0x0E
INT 0x10 ; display character 'X'/'S'
MOV AL, ':'
INT 0x10 ; display character ':'
RET
printascii:
MOV [DI], DX ; store value for later recall
MOV AH, 0x0E ; INT 10,E
MOV SI, hexascii ; load address of 'hexascii'
AND DX, 0xF000
SHR DX, 0x0C ; shift high nibble to lowest 4 bits
ADD SI, DX
CS LODSB ; AL = CS:[0x1EE + DX >> 12];
INT 0x10 ; display high nibble of character value
MOV SI, hexascii
MOV DX, [DI]
AND DX, 0x0F00
SHR DX, 0x08
ADD SI, DX
CS LODSB
INT 0x10 ; display low nibble of character value
MOV SI, hexascii
MOV DX, [DI]
AND DX, 0x00F0
SHR DX, 0x04
ADD SI, DX
CS LODSB
INT 0x10 ; display high nibble of character value
MOV SI, hexascii ;
MOV DX, [DI]
AND DX, 0x000F
ADD SI, DX
CS LODSB
INT 0x10 ; display low nibble of character value
RET
pad 0x01EE
hexascii:
db "0123456789ABCDEF" ;
pad 0x01FE ; pad to end of bootsector
dw 0xAA55 ; bootsector signature
从 DOSBOX 运行时,我正确地看到了 AX:0123,但是从我的软盘启动时,我看到了 AX:FFFF。我不知道我做错了什么。作为参考,我的电脑是Intel Core 2 Quad。
【问题讨论】:
-
您使用了
[org 0x7C00],但从未初始化DS0。某些 BIOS 可能会以 CS=7c0、IP=0 进入您的 MBR,而谁知道 DS 是什么。 -
int 20h不是 ROM-BIOS 中断服务。 -
您也没有向我们展示“pad”宏。 (或者它可能是您的汇编程序内置的?这条
lea行似乎不是有效的 NASM 语法,因此它取决于您使用的汇编程序。)无论如何填充都是错误的,应该填充到 510 (1FEh)。 -
一个可能的问题:由 ROM-BIOS 加载程序初始化的堆栈可能与您的寄存器存储区域重叠。
-
Boot loader doesn't jump to kernel code 的可能副本,Michael Petch 对引导加载程序的一般提示。回复:内存布局和使用
0x8000地址;如果 DS = 0,可能是安全的。Understanding of boot loader assembly code and memory locations 显示来自 MikeOS 的引导加载程序的内存映射。
标签: assembly x86-16 bootloader dosbox real-mode