NASM: emit an MSW of a non-scalar (link-time) value

I'm trying to define a permanent IDT record (interrupt descriptor table) in NASM , and for this I need to transfer the high word of the double word address to the data table, which is not allowed until the link time. Is there any way to do this?

Here is the interrupt handler:

;;; Interrupt 3 (breakpoint) handler. For now, just poke the screen and halt. align 8 int3: mov [0xb8000],dword '* * ' hlt 

And here is the IDT record that refers to it. The most significant and least significant offset words should 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 forces LD to issue the low word of the int3 address, but the high word is not executed during build with this error:

pgm.asm: 240: error: the shift operator can only be applied to scalar values

NASM will not do math with a value that is not defined before the reference time. I understand, but I need a way around this. I could:

  • find int3 absolutely
  • Build IDT at runtime, not at build time

I will probably end up building an IDT at runtime, but it would be nice to know if there is a way to get the assembler / linker to output a high address word into the data table that is not resolved before the link time.


Features:

  • NASM 2.20.01 1
  • NASM aout output format
  • LD version 2.22
  • 32-bit mode (NASM "bits 32" directive issued)

1 This is probably a typo; the latest version in my distribution today is 2.12.01. The latest version of nasm, available at the time of this writing, was 2.10.01.

+3
source share
1 answer

Well ... as you probably know, Nasm will come down to offset the difference between the two shortcuts. A regular construct is something like:

dw (int3 - $$) >> 16

where $$ refers to the beginning of the section. This computes the "file offset". This is probably not the value you want to shift.

dw (int3 - $$ + ORIGIN) >> 16

can do what you want ... where is ORIGIN ... well, what did we say to Nasm for org if we used a flat binary. I assume that you are going to -f elf32 or -f elf64 by specifying ld --oformat=binary and specifying ld either in the script builder or on the command line where you want the .text be (?). It seems to work. I made an interesting discovery: if you say ld -oformat=binary (one hyphen) instead of --oformat=binary (two hyphens), ld silently prints nothing! Do not do this - you spend a lot of time!

+3
source

All Articles