assemble、link 和 运行 如何在 linux 中生成 .s 文件?
How do you assemble, link and run a .s file in linux?
我在尝试使用 AT&T 英特尔语法 assemble 和 运行 .s 文件时收到奇怪的错误消息。不确定我是否一开始就使用了正确的架构,或者我是否有语法错误,如果我没有使用正确的命令 assemble 和 link,等等。完全丢失我不知道从哪里开始。
所以基本上,我有一个名为 yea.s 的文件,其中包含一些简单的 assembler 说明。然后我尝试使用命令 as yea.s -o yea.o
编译它,然后 link 使用 ld yea.o -o yea
。当 运行ning ld 时,我收到这条奇怪的消息:ld: warning: cannot find entry symbol _start; defaulting to 000000440000
。
这是我正在尝试 运行 的程序,非常简单,实际上什么都不做。
resMsg: .asciz "xxxxxxxx"
.text
.global main
main:
pushq [=14=]
ret
我只是不知道发生了什么。显然,这是学校作业。显然,我不是在寻找家庭作业的答案,但这是我可以真正开始编码的起点。而且我只是不知道如何简化 运行 程序,它在作业中没有说明。无论如何,提前谢谢大家!
在所有当前支持的 Ubuntu 版本中打开终端并输入:
sudo apt install as31 nasm
as31:英特尔 8031/8051 assembler
这是一款快速、简单、易于使用的 Intel 8031/8051 assembler.
nasm:通用 x86 assembler
全网汇编程序。 NASM 当前将输出平面形式的二进制文件、a.out、COFF 和 ELF Unix 目标文件,以及 Microsoft 16 位 DOS 和 Win32 目标文件。
如果您在 Ubuntu 18.04 中使用 NASM,编译命令和 运行 名为 example.asm 的 .asm 文件是:
nasm -f elf64 example.asm # assemble 程序
ld -s -o example example.o # link 目标文件 nasm 产生为可执行文件
./example # example 是一个可执行文件
Linux 可执行文件需要指定入口点。入口点是程序中要执行的第一条指令的地址。如果没有另外指定,link 编辑器会查找名为 _start
的符号作为入口点。您的程序不包含这样的符号,因此 linker 抱怨并选择 .text
部分的开头作为入口点。要解决此问题,请将 main
重命名为 _start
.
进一步注意,与 DOS 不同,return 与 _start
没有任何关系。因此,您对 return 的尝试将导致崩溃。相反,调用系统调用 sys_exit
退出程序:
mov [=10=], %edi # exit status
mov , %eax # system call number
syscall # perform exit call
或者,如果您想使用 C 运行时环境并调用 C 库中的函数,请保持程序不变,而不是 assemble 和 link 使用 C 编译器驱动程序 cc
:
cc -o yea yea.s
如果您这样做,C 运行时环境会为您提供入口点,并最终尝试调用一个函数 main
,这就是您的代码所在的位置。如果您想调用函数,则需要这种方法来自 C 库。如果您这样做,请确保 main
遵循 SysV ABI(调用约定)。
请注意,即使这样您的代码也不正确。函数的 return 值在 eax
(相应的 rax
)寄存器中给出,而不是压入堆栈。从 main
到 return 零,写入
mov [=12=], %eax # exit status
ret # return from function
我在尝试使用 AT&T 英特尔语法 assemble 和 运行 .s 文件时收到奇怪的错误消息。不确定我是否一开始就使用了正确的架构,或者我是否有语法错误,如果我没有使用正确的命令 assemble 和 link,等等。完全丢失我不知道从哪里开始。
所以基本上,我有一个名为 yea.s 的文件,其中包含一些简单的 assembler 说明。然后我尝试使用命令 as yea.s -o yea.o
编译它,然后 link 使用 ld yea.o -o yea
。当 运行ning ld 时,我收到这条奇怪的消息:ld: warning: cannot find entry symbol _start; defaulting to 000000440000
。
这是我正在尝试 运行 的程序,非常简单,实际上什么都不做。
resMsg: .asciz "xxxxxxxx"
.text
.global main
main:
pushq [=14=]
ret
我只是不知道发生了什么。显然,这是学校作业。显然,我不是在寻找家庭作业的答案,但这是我可以真正开始编码的起点。而且我只是不知道如何简化 运行 程序,它在作业中没有说明。无论如何,提前谢谢大家!
在所有当前支持的 Ubuntu 版本中打开终端并输入:
sudo apt install as31 nasm
as31:英特尔 8031/8051 assembler
这是一款快速、简单、易于使用的 Intel 8031/8051 assembler.
nasm:通用 x86 assembler 全网汇编程序。 NASM 当前将输出平面形式的二进制文件、a.out、COFF 和 ELF Unix 目标文件,以及 Microsoft 16 位 DOS 和 Win32 目标文件。
如果您在 Ubuntu 18.04 中使用 NASM,编译命令和 运行 名为 example.asm 的 .asm 文件是:
nasm -f elf64 example.asm # assemble 程序
ld -s -o example example.o # link 目标文件 nasm 产生为可执行文件
./example # example 是一个可执行文件
Linux 可执行文件需要指定入口点。入口点是程序中要执行的第一条指令的地址。如果没有另外指定,link 编辑器会查找名为 _start
的符号作为入口点。您的程序不包含这样的符号,因此 linker 抱怨并选择 .text
部分的开头作为入口点。要解决此问题,请将 main
重命名为 _start
.
进一步注意,与 DOS 不同,return 与 _start
没有任何关系。因此,您对 return 的尝试将导致崩溃。相反,调用系统调用 sys_exit
退出程序:
mov [=10=], %edi # exit status
mov , %eax # system call number
syscall # perform exit call
或者,如果您想使用 C 运行时环境并调用 C 库中的函数,请保持程序不变,而不是 assemble 和 link 使用 C 编译器驱动程序 cc
:
cc -o yea yea.s
如果您这样做,C 运行时环境会为您提供入口点,并最终尝试调用一个函数 main
,这就是您的代码所在的位置。如果您想调用函数,则需要这种方法来自 C 库。如果您这样做,请确保 main
遵循 SysV ABI(调用约定)。
请注意,即使这样您的代码也不正确。函数的 return 值在 eax
(相应的 rax
)寄存器中给出,而不是压入堆栈。从 main
到 return 零,写入
mov [=12=], %eax # exit status
ret # return from function