NASM Forum > Programming with NASM
Changing entry of Interrupt Vector Table
patdes20:
Hi everyone, I am trying to change the entry at 0x000:0x0020 (Timer Interrupt) of the Interrupt Vector Table and replace it with an own interrupt handler that jumps to the old interrupt handler after it finishes. My method needs to be executed every 55ms. The program is in real mode and works without OS. Could anybody help me and give me some code examples? Thank you. :)
With best regards, Patrick
fredericopissarra:
--- Code: ---; 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
--- End code ---
--- Code: ---$ nasm -f bin boot.asm -o boot.bin
$ qemu-system-i386 -drive file=boot.bin,index=0,media=disk,format=raw
--- End code ---
debs3759:
My boot sector was written with the assumption that CS can be either 0000 or 07C0. I believe both are possible, so I use org 0, copy the boot sector and do a far jump to the copy, setting CS up how I want it. I'm pretty sure I did that based on research that showed you can't guarantee the values of CS:IP when the boot sector is first loaded.
debs3759:
It's also important to set up the stack at the start of a boot sector, to be safe on all systems.
The start of my boot sector has the following code:
--- Code: ---org 0
BootSector:
jmp short start ; There should always be 3 bytes of code
nop ; followed by the start of the data.
<insert BPD data here>
start:
push WORD stackseg ; set up the stack
pop SS
mov SP,stacksize ;
push WORD 07C0h
pop DS
push WORD moveseg ; where I move my boot sector to
pop ES
xor SI,SI ; Starting from bottom of each segment
xor DI,DI
mov CX,100h ; 256 words to be transferred
cld
rep movsw ; Move the code
;-----------------------------------------------------------------------+
; Now we jump to the next instruction in the copy of the code +
;-----------------------------------------------------------------------+
jmp moveseg:next ; CS is now set to moveseg
next:
--- End code ---
That way I make no assumptions about the initial values of any segment register, and I don't do anything (other than a short jump over the BPD) before executing any other code.
debs3759:
See https://wiki.osdev.org/Boot_Sequence for confirmation that the boot sector could be loaded at either 0:07C00 or 07C0:0000
Navigation
[0] Message Index
[#] Next page
Go to full version