I'm trying to write a small bootloader for x86 using GAS, i.e., 16-bit assembly. This, located at 0x7C00, works perfectly:
 .code16   
 .text
  .globl main
main:
    mov $0xb800, %ax
    mov %ax, %es
    
    mov $0x7c0f, %si
    movb (%si), %al
    mov %al, %es:0
hlt
string:
    .byte 'A'
    .section    .note.GNU-stack,"",@progbits
    .section    .note.gnu.property,"x"
However, as you can see, the address of "string" is hardcoded to be $0x7C0F. As soon as I try to replace that hardcoded line by:
    #mov $0x7c0f, %si
    mov string, %si
compilation fails:
/usr/bin/ld: /tmp/cctVBx2h.o: relocation R_X86_64_16 against `.text' can not be used when making a PIE object; recompile with -fPIE /usr/bin/ld: failed to set dynamic section sizes: bad value
How can I make GAS resolve the addresses automatically, as it would also do in 32-bit or 64-bit mode?
Edit
Yikes, I just found this comment in the Linux source code, arch/x86/realmode/rm/realmode.h where they hardcode the longjump required to enter protected mode:
This must be open-coded since gas will choke on using a relocatable symbol for the segment portion.
Does this mean GAS just is unable to do this properly?
 
     
    