I am attempting to define a constant IDT (Interrupt Descriptor Table) entry in NASM, and to do so, I need to emit into a data table the high word of a double-word address that is not resolved until link time. Is there a way to do it?
Here's the interrupt handler:
;;; Interrupt 3 (breakpoint) handler. For now, just poke the screen and halt.
align 8
int3:
mov [0xb8000],dword '* * '
hlt
And here's the IDT entry that references it. The most-significant and least-significant words of the offset need to be stored separately and non-contiguously:
;; Interrupt 3 - breakpoint
dw int3 ; offset (low) <---- WORKS
dw codesel ; code selector
db 0 ; unused
db 0b10001111 ; present, ring 0, 32-bit trap gate
dw int3 >> 16 ; offset (high) <---- ASSEMBLY ERROR
NASM correctly causes ld to emit the low word of int3's address, but the high word fails at assembly with this error:
pgm.asm:240: error: shift operator may only be applied to scalar values
NASM won't do math with a value that isn't defined until link time. I understand, but I need a way to work around this. I could:
- locate int3 absolutely
- Build the IDT at runtime instead of assembly time
I'll probably end up building the IDT at runtime, but it'd be good to know if there is a way to cause the assembler/linker to emit into a data table the high word of an address that is not resolved until link time.
Particulars:
- NASM 2.20.01
- nasm output format "aout"
- ld version 2.22
- 32-bit mode (nasm "bits 32" directive issued)