问题
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 time 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.011
- NASM output format
aout
- LD version 2.22
- 32-bit mode (NASM "bits 32" directive issued)
1 This is probably a typo; the latest version in my distro today is 2.12.01. The latest version of nasm available at the time I wrote this question was 2.10.01.
回答1:
Well... as you probably know, Nasm will condescend to do a shift on the difference between two labels. The usual construct is something like:
dw (int3 - $$) >> 16
where $$
refers to the beginning of the section. This calculates the "file offset". This is probably not the value you want to shift.
dw (int3 - $$ + ORIGIN) >> 16
may do what you want... where ORIGIN
is... well, what we told Nasm for org
, if we were using flat binary. I ASSume you're assembling to -f elf32
or -f elf64
, telling ld --oformat=binary
, and telling ld either in a linker script or on the command line where you want .text
to be (?). This seems to work.
I made an interesting discovery: if you tell ld -oformat=binary
(one hyphen) instead of --oformat=binary
(two hyphens), ld silently outputs nothing! Don't do this - you waste a lot of time!
来源:https://stackoverflow.com/questions/16351889/nasm-emit-msw-of-non-scalar-link-time-value