Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Gcc 在Linux中链接32/64位程序集时出错_Gcc_Assembly_X86_Linker Errors_Ld - Fatal编程技术网

Gcc 在Linux中链接32/64位程序集时出错

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/

我是汇编语言编程新手。我试图按照概述的步骤来更好地理解组装和优化。我的操作系统是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/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