【发布时间】:2021-03-16 17:29:10
【问题描述】:
使用此代码:
section .data
msg db "Most basic printf example in NASM", 0xA, 0xD, 0
len equ $-msg
section .bss
section .text
global _start
extern printf
_start:
mov rsi, msg
push rax ;; for stack alignment
call printf
失败并出现错误undefined reference to `printf'
我正在尝试创建从 NASM 调用 printf 的最简单的工作示例。
我已经阅读了将 -lc 添加到 ld 的建议,即:
ld -o worked-example -lc worked-example.o
要么
ld -o worked-example worked-example.o -lc
两者都可以防止错误消息 - 但是文件工作示例 - 无法使用 ./worked-example - even 虽然可以看到 cat 和 ls
file worked-example 表示:
工作示例:ELF 64 位 LSB 可执行文件,x86-64,版本 1 (SYSV),动态链接,解释器 /lib/ld64.so.1,带有 debug_info,未剥离
编辑:基于下面的 cmets,我找到了动态链接器并尝试添加:ld worked-example.o -o worked-example -lc -dynamic-linker /usr/lib64/ld-linux-x86-64.so.2
哪个有效。 [带有段错误并且没有打印任何内容 - 但它可以编译并运行]
【问题讨论】:
-
名称修改适用于 C++,会导致链接器错误。
-
运行时会出现错误,就像找不到文件本身一样,因为您没有指定在加载时运行的动态链接器。在 64 位 Linux 发行版上,通常不能像
ld -o worked-example -lc worked-example.o -dynamic-linker /lib64/ld-linux-x86-64.so.2那样完成。您还必须与-lc链接。如果您使用 GCC 链接,您可以避免这种情况,因为它会为您执行此操作并在 C 库中链接 -
我的第一条评论应该是 在通常无法做到的 64 位 Linux 发行版上。需要注意的是,通过绕过 C 启动代码从 C 库运行代码可能会导致某些类型的 C 函数调用出现问题。如果您使用 MUSL C 库,则可以避免该问题,因为它可以以不需要事先初始化的方式使用。
-
至于它运行不正常是因为第一个参数在 RDI 中,但你把它放在了 RSI 中。由于
printf是一个可变参数函数,您应该指定用于在寄存器 AL 中进行调用的向量寄存器(SIMD 寄存器)的最大数量。在这种情况下,您没有使用向量寄存器,因此您可以将 AL 设置为 0。您的代码也缺少退出程序的内容。call exit -
格式字符串确实进入 RDI,因为它是第一个参数。您的格式字符串是
"Most basic printf example in NASM", 0xA, 0xD, 0。它是一个格式字符串,其中的字符串不包含任何 C 格式说明符。
标签: linux assembly x86-64 nasm glibc