; boot.asm - Legacy boot sector.
bits 16
cpu 386
org 0x7c00
_start:
; Since CS is always zero at this point, just copy
; CS to DS and ES.
mov ax,cs
mov ds,ax
mov es,ax
; Disable interrupts.
cli
; Change int 0x1c to new handler.
; if there is an old handler, store it.
;
; int 0x1c is called by irq8, which is adjusted to
; occur 18.2 times/sec (timer 0 is 18.2 Hz rate generator
; by default - roughly 55 ms).
mov eax,es:[0x1c*4]
test eax,eax
jz .no_old_handler
mov dword es:[oldint],eax
.no_old_handler:
mov word es:[0x1c*4],newint
mov word es:[0x1c*4+2],cs
; Re-enable interrupts
sti
.loop:
hlt
jmp .loop
; --- Our interrupt handler.
align 2
newint:
pushf
push ds
push ax
push bx
push si
mov ax,cs
mov ds,ax
; We'll print 'tick' on string each second (roughly).
inc byte [cnt]
cmp byte [cnt],18
jne .not_time_yet
cld
mov byte [cnt],0
mov ax,cs
mov ds,ax
lea si,[msg]
call puts
.not_time_yet:
pop si
pop bx
pop ax
pop ds
; if there is an old handler, jump to it.
; Otherwise iret.
cmp dword cs:[oldint],0
je .retfromint
popf
jmp far [cs:oldint]
.retfromint:
popf
iret
align 2
puts:
lodsb
test al,al
je .exit
mov bx,7
mov ah,0x0e
int 0x10
jmp puts
.exit:
ret
align 4
oldint:
dd 0
cnt:
db 0
msg:
db `tick\r\n`,0
times 510-($-$$) db 0
dw 0xaa55
$ nasm -f bin boot.asm -o boot.bin
$ qemu-system-i386 -drive file=boot.bin,index=0,media=disk,format=raw