Page 1 of 1

Manipulating symbol addresses in GNU Assember

Posted: Fri Feb 13, 2015 4:17 pm
by ivtMasMidt
Hi OSDev.org community,
I'm using GNU-Assembler in intel syntax to write my x86 initialization routines and want to set up an IDT. The IDT requires the target address to be split into two 16-bit parts.

Now my question is, is there a possibility to let the assembler do this? I would like to have the (absolute) addresses already stored in the binary, without the need to manually set up the individual IDT entries.

In practice I would like to be able to write the following code:

Code: Select all

.macro IGATE SEL FN TP
.word (\FN & 0xffff)
.word \SEL
.byte 0
.byte \TP
.word ((\FN & 0xffff0000) >> 16)
.endm

.align 16
idt:
IGATE 0x08 gate_1 0x8f
idt_end:

gate_1:
    call C_function
    iret
Running this code through as yields the assembler complaining about argument mismatch for the bitwise and operator, as the symbol reference is section relative.

Is there a way around this? Or is it a limitation of the relocation mechanism of stitching together different object files, so that as cannot emit a request for the upper/lower part of the symbol location to be stored at this place?

Re: Manipulating symbol addresses in GNU Assember

Posted: Sat Feb 14, 2015 12:45 am
by xenos
As far as I know, there are no relocations that can take something like the upper or lower 16 bit of an address.

An alternative way is to write the IDT and do these calculations at runtime. Instead of an assembler macro, you would write a short function that takes the same arguments and writes the IDT entry to the place where it should be. The arguments to this function can then be relocations / function addresses.

Re: Manipulating symbol addresses in GNU Assember

Posted: Sat Feb 14, 2015 5:00 am
by ivtMasMidt
Thanks for the suggestion, that's similar to what I ended up with yesterday. In order to save space my solution looks like

Code: Select all

.macro IGI NUM
    mov edx, \NUM
    shl edx, 3
    add edx, 2
    mov ax, word ptr [edx+idt]
    add edx, 4
    mov bx, word ptr [edx+idt]
    mov word ptr [edx+idt], ax
    sub edx, 4
    mov word ptr [edx+idt], bx
.endm

.macro IGATE SEL FN TP
    .int \FN
    .byte 0
    .byte \TP
    .word \SEL
.endm

idt:
IGATE 0x08 gate_0 0x8f
idt_end:

gate_0:
    ...
    iret

idt_init:
    mov ecx, ((idt_end-idt)/8)
    dec ecx
    IGI ecx
    test ecx, ecx
    jnz idt_init
    ret
Which swaps the second half of the address with the segment selector at startup.
I suppose linker support for such a fringe case is not to be expected.