You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在x86/32 GNU汇编中调用printf及相关PIE机制疑问

x86/32位汇编调用printf的PLT/GOT相关问题

我编写了一个调用printf的x86/32汇编程序,使用gcc -m32 x.s编译:

.data
format:
    .string "%d\n"
    .text
    .global main
    .type   main, @function
main:
    mov     $56, %eax
    push    %eax
    call    get_pc_eax
    add     $format - ., %eax
    push    %eax
    # call  printf@PLT
    call    get_pc_eax
    add     $_GLOBAL_OFFSET_TABLE_, %eax
    mov     printf@GOT(%eax), %eax
    call    *%eax
    add     $8, %esp
    xor     %eax, %eax
    ret
get_pc_eax:
    mov     (%esp), %eax
    ret
.section .note.GNU-stack,"",@progbits

若启用注释行call printf@PLT替代其后4行代码,程序执行无输出。现提出以下疑问:

  • 调用PLT前是否需要初始化?
  • 这是位置无关代码中调用函数的推荐方式吗?感觉较为繁琐。
  • 求讲解Linux下i386汇编调用libc及位置无关代码的gas/gcc教程内容。

更新:
经讨论后得到main函数的可行代码:

1  push    %ebx
 2  mov     $56, %ebx
 3  push    %ebx
 4  call    get_pc_ebx
 5  add     $format - ., %ebx
 6  push    %ebx
 7  call    get_pc_ebx
 8  add     $_GLOBAL_OFFSET_TABLE_, %ebx
 9  xor     %eax, %eax
10  call    printf@PLT
11  add     $8, %esp
12  pop     %ebx
13  xor     %eax, %eax
14  ret

此代码可正常运行,若注释第7、8行的%ebx初始化则崩溃,推测%ebx需指向全局偏移表(GOT)。求讲解该机制的内容。


问题解答

1. 调用PLT前是否需要初始化?

在32位x86的位置无关代码(PIC)中,调用PLT函数必须先让EBX寄存器指向GOT的基地址。PLT的内部实现依赖GOT来解析函数的实际地址,而EBX是PIC代码中约定用来保存GOT基址的调用保存寄存器(调用者需要维护其值)。你之前直接调用printf@PLT时未设置EBX为GOT基址,导致PLT无法正确定位printf的地址,因此程序无输出。

2. 这是位置无关代码中调用函数的推荐方式吗?

手动通过get_pc_ebx获取GOT基址再调用函数的方式,是32位PIC汇编的标准手动实现逻辑,但确实较为繁琐。如果不需要手写PIC代码,推荐直接用GCC的-fPIC选项编译C代码生成PIC汇编;如果只是编译可执行文件(而非共享库),也可以不用严格遵循PIC规则,直接调用函数符号即可,具体取决于你的需求场景。

3. 相关教程内容推荐

  • GNU汇编器(GAS)官方手册:通过info as命令查看,其中包含i386架构汇编语法、PIC代码编写的详细说明。
  • 《Programming from the Ground Up》:这本书详细讲解了Linux下x86汇编的基础,包括libc函数调用、内存管理等内容,对理解PIC机制也有帮助。
  • GCC官方文档:关于PIC代码生成的章节,能帮助理解编译器如何自动处理GOT/PLT相关逻辑。

更新部分的疑问解析

第7、8行的作用是计算GOT的基址并存入EBX:get_pc_ebx获取当前指令的地址,加上_GLOBAL_OFFSET_TABLE_的偏移后,得到GOT的起始地址。printf@PLT的内部代码会通过EBX访问GOT中的条目来获取printf的实际运行地址,如果EBX未正确设置,访问的内存地址无效,直接导致程序崩溃。


内容的提问来源于stack exchange,提问作者hochl

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 13:55:07