【发布时间】:2020-08-01 19:38:41
【问题描述】:
我编写了以下基本程序来添加两个数字,1+2,如下:
.globl main
main:
# put 1 (1 byte int/char) into accumulator register
mov $1, %eax
# add 2 (1 byte int/char), storing result in accumulator
add $2, %eax
# move the result of the accumulator into Data register (input/output)
mov %eax, %edx
ret
编译后,它会返回预期的输出:
$ gcc d.s -o d2.out && ./d2.out; echo $?
3
我有几个关于这个程序的问题:
- 这或多或少是一个 OK 程序,还是我误用了任何操作等?
- 程序集文件是否总是必须有一个
globl函数,例如main,或者它是否可以,例如,删除main/.globl main部分,然后“逐行运行代码”行”? - 最后,查找操作码的最佳资源是什么?我倾向于用谷歌搜索这些,它会返回不同的结果:如果有像
Python docs这样的标准资源会很好,我可以在其中添加一个页面的书签并在那里查看所有内容。
【问题讨论】:
-
1.) 干得好,但
mov %eax,%edx至少在这种情况下是不必要的。 2.) 您可以将其编译为平面二进制文件(不是目标文件),将其加载到 C 代码中,使其可执行并从那里运行。或者您可以使用调试器逐行运行代码。 3.) 我没有找到资源 -
返回值进入 eax,而不是 edx。在这里设置任何值的 edx 是没有意义的。
-
@JCWasmx86 -- 我明白了。我一定把eax和edx搞混了。
%eax是程序返回控制后OS读取的寄存器和程序的返回码? -
EAX 由
main返回给 C 运行时。 C 运行时将值传递给 OS_exit函数,可以在 EDI 中或在堆栈中,具体取决于您的系统。 shell 调用wait来检索值,以便打印它。 (可能比你想知道的更多。) -
@prl: nitpicks - 32 位 Linux 的系统调用 ABI 按 EBX、ECX、EDX 等顺序传递参数。 C 运行时实际上使用
exit_group(2)系统调用(x86-64 上的 EAX=231/syscall),而不是_exit(EAX=60/系统调用)。 (名为_exit(2)actually usesexit_group的 libc 包装函数)。并且这仅在进行清理(如刷新 stdio 缓冲区)之后,与exit(3)库函数相同。 (glibc 的_exit在错误(包括 ENOSYS)来自exit_group时有趣地回退到exit)
标签: assembly x86 gnu-assembler att