I recently wrote an x86 'bootloader' program that shows the values of the hardware registers after the BIOS jumps to my program. For the purpose of testing, I set the AX
register to a known value to ensure that the program runs correctly.
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
When running from DOSBOX, I correctly see AX:0123
, but when booting from my floppy disk, I get AX:FFFF
. I have no idea what I'm doing wrong. For reference, my PC is a Intel Core 2 Quad
.