NASM: emit MSW of non-scalar (link-time) value [duplicate]

一个人想着一个人 提交于 2019-12-20 02:33:09

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!