Gcc 在Linux中链接32/64位程序集时出错
我是汇编语言编程新手。我试图按照概述的步骤来更好地理解组装和优化。我的操作系统是LinuxMint,我正在尝试使用NASM汇编程序,尽管没有成功 与演练中一样,代码是:Gcc 在Linux中链接32/64位程序集时出错,gcc,assembly,x86,linker-errors,ld,Gcc,Assembly,X86,Linker Errors,Ld,我是汇编语言编程新手。我试图按照概述的步骤来更好地理解组装和优化。我的操作系统是LinuxMint,我正在尝试使用NASM汇编程序,尽管没有成功 与演练中一样,代码是: BITS 32 GLOBAL main SECTION .text main: mov eax, 42 ret 它使用以下命令使用nasm成功编译:nasm-f elf tiny.asm 但是如果我尝试使用gcc链接命令:gcc-Wall-s tiny.o 我得到以下错误: /输入文件'tiny.o'的usr/
BITS 32
GLOBAL main
SECTION .text
main:
mov eax, 42
ret
它使用以下命令使用nasm成功编译:nasm-f elf tiny.asm
但是如果我尝试使用gcc链接命令:gcc-Wall-s tiny.o
我得到以下错误:
/输入文件'tiny.o'的usr/bin/ld:i386体系结构与i386:x86-64输出不兼容
快速搜索告诉我应该使用以下ld命令进行链接:ld-melf_i386-s-o tiny.o
但是,这样做给了我以下警告:
ld:警告:找不到输入符号\u start;默认为000000000 8048060
如果我/tiny
,我会得到一个分段错误。和/tiny;echo$?
还返回数字“139”,即。。。出乎意料
浏览一下,我发现有些问题已经解决了,方法是将1传递给eax寄存器,将0传递给ebx,然后使用我不熟悉的int命令结束程序。。。但是考虑到我的目标是使程序尽可能小,我宁愿不添加额外的代码行
我应该补充一点,编译和链接类似的代码(GAS):
使用gcc编译器似乎可以完美地运行。我在这里不知所措。如果方向正确,我们将不胜感激 程序的默认入口点是
\u start
符号。使用gcc编译时,编译器会创建一个名为\u start
的函数,在调用main
之前先进行一些设置。我相信它实际上是C库的一部分。因为您使用的是更低级的工具,所以您没有链接到C库,因此您必须自己完成这项工作
因此,只要将您的main
更改为\u start
,ld就不会再抱怨了。现在,您最好使用libc的\u start
,因为您当前的实现仍然会出错:您需要使用退出
系统调用停止程序,而不是使用返回
Michael的评论告诉您如何使用gcc从汇编代码编译(因此您有了libc的\u start
)。如果您仍想自己完成,您的程序需要如下所示:
BITS 32
GLOBAL _start
SECTION .text
_start:
mov ebx, 42
mov eax, 1
int 0x80
您将退出的系统调用号放入eax,返回码放入ebx,并触发0x80中断。这适用于Linux Mint、Ubuntu、Xubuntu和其他基于Ubuntu的现代发行版。对于其他Debian系统,信息相同,但您可以从安装命令中删除
sudo
命令,并以root
用户身份运行该命令
默认情况下,GCC创建32位程序所需的文件不安装在64位Linux Mint上。此命令将安装所需的文件:
sudo apt-get install gcc-multilib g++-multilib
要组装32位对象,然后链接到32位可执行文件,可以执行以下操作:
nasm -f elf32 tiny.asm -o tiny.o
gcc -m32 -Wall -s tiny.o -o tiny
由于在汇编文件的顶部有位32
,因此您希望将其编译为32位ELF对象,这就是NASM命令行上的-f elf32
选项所做的
GCC用于将对象链接到最终可执行文件。添加-m32
告诉GCC将对象链接到32位可执行文件。-m32
选项覆盖在64位Linux发行版上生成64位可执行文件的正常默认行为
通过使用GCC链接可执行文件,生成的程序实际上提供了一个执行C运行时初始化的
\u start
,然后调用名为main
的标签,就好像它是一个C函数一样
当您在main
函数中执行ret
时,它会返回到C运行时代码,并为您干净地退出程序
对于新的汇编语言开发人员来说,使用GCC是更简单、更安全的方法。它还允许您添加调用C运行时函数的代码,如
printf
,scanf
,atoi
,以及大多数其他标准C库函数。如果您使用64位Linux Mint并试图创建32位应用程序(使用GCC链接)尝试安装gcc multilib g++-multilib然后尝试nasm-f elf32 tiny.asm
和gcc-m32-Wall-s tiny.o-o tiny
非常感谢!这为我解决了所有问题,你介意再解释一下附加选项的作用吗?他们只是让32位代码在64位环境中运行吗?默认情况下,GCC创建32位程序所需的文件不安装在64位Linux上<代码>sudo apt get…行只需下载并安装64位Linux Mint上32位GCC开发所需的GCC文件。由于在汇编程序的顶部有位32
,所以您希望将其编译为32位ELF对象,这就是nasm-f elf32 tiny.asm所做的)(默认情况下,它会输出一个名为tiny.o
的文件。对象文件需要链接到一个可执行文件gcc-m32-Wall-s tiny.o-o tiny
。我添加的-m32
选项表示我们希望从32位对象生成一个32位可执行文件。通过使用gcc链接可执行文件,生成的程序实际上会执行一些C运行时初始化,然后调用名为main
的标签,就像调用C函数一样。当您在main
中执行ret
时,它会返回到C运行时代码,并为您干净地退出程序。谢谢,此解决方案可以阻止链接器抱怨。但是,在运行时,仍然存在“分段”错误错误,返回值不是42而是139。很抱歉,我有一个坏习惯,在尝试添加更多信息时,会先发布我的答案并对其进行编辑。现在应该完成了。感谢
nasm -f elf32 tiny.asm -o tiny.o
gcc -m32 -Wall -s tiny.o -o tiny