C Linux汇编和printf
我尝试用printf函数编写简单的汇编程序。我编译它C Linux汇编和printf,c,assembly,printf,nasm,C,Assembly,Printf,Nasm,我尝试用printf函数编写简单的汇编程序。我编译它nasm-f elf 64并使用gcc链接。运行后,我看到分段故障。怎么了 [Bits 32] extern printf global main section .data hello: db "Hello", 0xa, 0 section .text main: push hello call [printf] add esp, 4 mov eax, 1 mov ebx, 0 int 80h ia32上的Linux与a
nasm-f elf 64
并使用gcc
链接。运行后,我看到分段故障
。怎么了
[Bits 32]
extern printf
global main
section .data
hello:
db "Hello", 0xa, 0
section .text
main:
push hello
call [printf]
add esp, 4
mov eax, 1
mov ebx, 0
int 80h
ia32上的Linux与amd64上的调用约定不同。由于您的代码使用前者,您必须将其组装为32位并与32位libc链接。在debian上,您需要libc6-dev-i386包 您还必须将“call[printf]”替换为“call printf”,这是一个错误 还要注意,在使用主界面时,应该从main返回,而不是执行exit系统调用以允许运行C运行时关闭代码 如果您正在使用amd64,则可能需要学习如何编写64位程序集
.如果您真的希望获得代码头显示的32位二进制文件,则只需修复以下行:
call [printf]
将其更改为:
call printf
当您调用[printf]时,您调用的不是printf,而是第一个printf代码字节所指向的地址,该结构(
[address]
)被称为.为什么要汇编一个明显是32位到elf64
的程序?因为当我不这样做时,我看到:/usr/bin/ld:i386输入文件的体系结构。/asemlebr.o与i386:x86-64输出不兼容
您在哪里编写了printf
?如果您正在考虑调用C库中的一个,那么需要做的工作远不止这些-您需要确保调用库的初始化代码,根据您所在平台的ABI设置堆栈框架和参数,并将程序与库链接,至少…@twalberg:事实上这会很好用的。OP正在写入main
,因此CRT启动代码将在调用main之前初始化glibc,即使在静态可执行文件中也是如此。在GLIMC动态链接的二进制中,也可以从<代码> >启动> /代码>安全,因为GLIBC的init函数是由动态链接器调用的,该机制使用在C++库代码中运行静态初始化器的相同机制。相关:了解更多关于静态与动态二进制文件以及是否链接libc的信息。这里的主要危险是sys\u exit
不会刷新标准输出,但如果不是TTY,它将被完全缓冲。