assembly GAS x86 16位汇编程序无法解析地址

xriantvc  于 2023-05-29  发布在  其他
关注(0)|答案(1)|浏览(236)

我正在尝试使用GAS(即16位汇编)为x86编写一个小型 Bootstrap 。位于0x7C00的这个命令工作得很好:

.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"

但是,正如您所看到的,“string”的地址被硬编码为$0x7C0F。只要我尝试将硬编码行替换为:

#mov $0x7c0f, %si
    mov string, %si

编译失败:

/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

如何让GAS自动解析地址,就像它在32位或64位模式下一样?

编辑

Yikes,我刚刚在Linux源代码arch/x86/realmode/rm/realmode.h中找到了这个注解,他们在那里硬编码了进入保护模式所需的longjump:
这必须是开放编码的,因为气体将阻塞,使用可重新定位的符号为段部分。
这是否意味着GAS无法正确地做到这一点?

jobtbby3

jobtbby31#

GCC在大多数现代发行版上的默认值是make a PIE executable,错误消息表明您刚刚使用了gcc -nostdlib foo.s或其他东西来要求GCC将其汇编并链接到普通的64位PIE可执行文件中!这当然行不通; 16位绝对地址在64位虚拟地址空间中不具有重新定位的空间。
通常,您会将ld-Ttext=0x7C00或其他内容链接,以告诉它计算有用的绝对地址来填充,这些地址将适合16位绝对地址。
或者,如果您想使用gcc而不是ld(可能是gcc -m32 -static -no-pie -nostdlib),则可以使用与生成在Linux下运行的静态可执行文件相同的命令。但是你需要objcopy或其他东西来获得一个扁平的二进制MBR。
(Don不要忘记.word 0xaa55 Boot 签名。关于使用GNU汇编器和GNU工具链中的其他工具来制作遗留BIOS MBR Boot 扇区,有各种各样的Q& A,大多数标记为bootloader,并提到GAS或用它标记。
此外,您希望mov $string, %si将该地址用作立即数,而不是从它加载2个字节作为[disp16]寻址模式。出于同样的原因,您使用了$0x7c0f而不是0x7c0f

相关问题