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

x86_64 AT&T汇编调用printf执行报错:required file not found

64位ELF汇编调用printf报错排查与修正

问题描述

开发编译器时生成x86_64 AT&T汇编代码,试图调用libc的printf函数,目标架构为64位ELF。使用以下命令编译链接生成可执行文件:

as --64 examples/out/test.S -o examples/out/test.o && ld -lc examples/out/test.o -o examples/out/test

运行./examples/out/test时出现错误:

bash: examples/out/test: cannot execute: required file not found

原汇编代码test.S内容如下:

;#; This file was generated by the MZ compiler.
    .section .data
        b: .space 8
        a: .space 8
        fmt: .asciz "%lld"

    .global _start

    .section .text

_start: 
    push %rbp
    mov %rsp, %rbp

    lea a(%rip), %rax
    movq $420, (%rax)
    lea b(%rip), %rax
    movq $42, (%rax)

    movq $42069, %rdx
    lea  fmt(%rip), %rcx
    call printf

    pop %rbp
    movl $0, %ebx
    movl $1, %eax
    int $0x80

报错原因分析

  • 动态链接器路径缺失:直接用ld -lc链接时,未指定64位系统的动态链接器路径,导致系统无法找到运行时所需的动态链接器,进而无法加载依赖的libc库。
  • 调用约定违反规范:x86_64 System V ABI调用约定中,printf的第一个参数(格式串)应放入%rdi寄存器,第二个参数(输出数值)应放入%rsi寄存器。原代码错误地将格式串放入%rcx、数值放入%rdx,完全违反调用约定,会导致函数调用行为异常。
  • 栈未对齐:x86_64架构要求函数调用前栈保持16字节对齐。原代码中push %rbp后栈指针偏移8字节,调用printf前未调整栈对齐,会触发运行时错误。
  • 退出方式错误:int $0x80是32位Linux系统调用接口,在64位程序中使用会导致系统调用参数传递错误,无法正常退出程序。

修正方案

1. 修正后的汇编代码

;#; This file was generated by the MZ compiler.
    .section .data
        b: .space 8
        a: .space 8
        fmt: .asciz "%lld\n"  # 添加换行符,让输出更规范

    .global _start

    .section .text

_start: 
    push %rbp
    mov %rsp, %rbp

    # 示例数据赋值(保留原逻辑)
    lea a(%rip), %rax
    movq $420, (%rax)
    lea b(%rip), %rax
    movq $42, (%rax)

    # 调整栈对齐:push %rbp后栈偏移8字节,sub $8凑16字节对齐
    sub $8, %rsp

    # 按照x86_64 System V ABI传递printf参数
    movq $42069, %rsi        # 第二个参数:要输出的数值
    lea fmt(%rip), %rdi      # 第一个参数:格式串
    call printf

    # 恢复栈
    add $8, %rsp
    pop %rbp

    # 使用64位系统调用退出程序
    mov $60, %rax            # exit系统调用号(64位)
    mov $0, %rdi             # 退出码
    syscall

2. 正确的编译链接命令

方式一:用gcc自动处理链接细节(推荐)

gcc会自动处理动态链接器、libc依赖和栈对齐等问题:

as --64 examples/out/test.S -o examples/out/test.o && gcc -no-pie examples/out/test.o -o examples/out/test

或直接用gcc编译汇编文件:

gcc -no-pie examples/out/test.S -o examples/out/test

方式二:手动用ld指定动态链接器

若必须用ld,需明确指定64位动态链接器路径(WSL Kali中通常为/lib64/ld-linux-x86-64.so.2):

as --64 examples/out/test.S -o examples/out/test.o && ld -dynamic-linker /lib64/ld-linux-x86-64.so.2 -lc examples/out/test.o -o examples/out/test

验证

运行修正后的可执行文件,会输出42069,程序正常退出,无报错。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 02:36:00