Here's a boot sector I whipped up that helps me run a dual-boot
FreeBSD/Windows system using NTLDR with much elegance. It is derived from
a boot sector I wrote for a mystery OS, and includes a debug routine that
isn't used but was left in there because I was proud of it. I haven't
looked at this in quite a while, but it works. It is in NASM (not MASM)
syntax.
;;; ===========================================================================
;;; This is the source to a fake boot sector to help the Windows NT bootloader,
;;; ntldr, load other operating systems. All this does is load the "real" boot
;;; sector from a drive and pass control to it. The drive number is hard-coded
;;; by the DRIVE %define below. You need NASM to assemble this file.
;;; ===========================================================================
;; BIOS drive number to load from
%define DRIVE 0x80 ; <---- CHANGE FOR EACH BOOT SECTOR NEEDED
;; I hate "jmp short"
%macro jmps 1
jmp short %1
%endmacro
;; Where we want to be
org 0x7E00
;;; ===========================================================================
;;; CODE
;;; ===========================================================================
;; Setup stack, move code somewhere else, and jump there
cli
xor ax, ax
mov ds, ax
mov es, ax
mov ss, ax
mov sp, 0x7C00
mov si, sp
mov di, 0x7E00
mov cx, 0x0100
cld
rep
movsw
jmp moved + 0x200
moved: sti
;; Reset drive
mov dl, DRIVE
int 0x13
jc error
;; Load real boot sector
mov ax, 0x0201
mov bx, 0x7C00
mov cx, 0x0001
mov dh, ch
mov dl, DRIVE
int 0x13
jc error
;; Jump to real boot sector
mov dl, DRIVE
jmp 0x7C00
;; In case of error, print msg and lock up
error: mov si, errmsg
call print
jmps lockup
;; debug
;; Print the value of the registers and wait for a keystroke
debug: push ax
push cx
push dx
push bp
pusha
push ds
push es
push cs
push ss
mov bp, sp
add bp, 22
mov si, regs
.reg: call print
mov cx, 4 ; print 4 digits
mov dx, [bp] ; load word into dx
.digit: rol dx, 4 ; rotate so that lowest 4 bits are used
mov ax, 0x0E0F ; ah = request, al = mask for nybble
and al, dl
add al, 0x90 ; convert al to hex digits in ASCII
daa
adc al, 0x40
daa
int 0x10
loop .digit
cmp bp, sp
je .done
sub bp, 2
jmps .reg
.done: call print
add sp, 24
xor ax, ax
int 0x16
pop bp
pop dx
pop cx
pop ax
ret
;;; print
;;; prints the zero-terminated string pointed to by SI.
print: push ax
push bx
mov ah, 0x0E
xor bx, bx
.char: lodsb
or al, al
jz .done
int 0x10
jmps .char
.done: pop bx
pop ax
ret
;; lockup
;; Locks the machine way up.
lockup:
hlt
jmps lockup
;;; ===========================================================================
;;; DATA
;;; ===========================================================================
;; Error message
errmsg: db 'Error reading boot sector. System halted.', 0
;; Register names
regs: db 13, 10, "AX=", 0
db 13, 10, "CX=", 0
db 13, 10, "DX=", 0
db 13, 10, "BX=", 0
db 13, 10, "SP=", 0
db 13, 10, "BP=", 0
db 13, 10, "SI=", 0
db 13, 10, "DI=", 0
db 13, 10, "DS=", 0
db 13, 10, "ES=", 0
db 13, 10, "CS=", 0
db 13, 10, "SS=", 0
db 13, 10, 0
;; Zero-padding to 512 bytes
pad: times 510-($-$$) db 0x00
;; Magic boot sector number
magic: dw 0xAA55
--
Jeffrey S. Sharp
jss(a)subatomix.com