下面的代码是家庭作业,我理解的实际装配命令。但是我不确定(并且一直在寻找)如何确定函数的返回类型以及函数采用的参数数量。教授真的没有过这么好(Monotone tenure princess) 赋值是读取汇编代码,然后根据汇编代码编写c代码。我再一次理解了这些指令,只是无法弄清楚返回类型是什么或代码需要多少个参数
.file "hw5.c"
.text
.p2align 4,,15
.globl p1
.type p1, @function
p1:
.LFB0:
.cfi_startproc
addq %rsi, %rdi
addq %rdi, %rdx
movq %rdx, %rax
ret
.cfi_endproc
答案 0 :(得分:2)
有关调用约定文档的链接,请参阅https://stackoverflow.com/tags/x86/info。这看起来像标准的SysV x86 ABI,除了Windows之外的所有东西都使用。
这显然是做了两次添加64位添加以从三个输入寄存器生成结果,然后将结果放在%rax
。
但是,您无法判断结果是有符号还是无符号,因为代码是相同的。
此外,优化版本会跳过mov
,使用lea
作为非破坏性添加,其输出不是其中一个输入:
lea (%rdi,%rdx), %rax
答案 1 :(得分:1)
您应该查看处理器/平台的调用约定,以了解低级实现。
在调用子例程之前,调用者应该保存指定调用者保存的某些寄存器的内容。调用者保存的寄存器是EAX,ECX,EDX [x86]。由于允许被调用子程序修改这些寄存器,如果调用程序在子程序返回后依赖它们的值,则调用程序必须将这些寄存器中的值压入堆栈(这样它们就可以在子程序返回后恢复。 要将参数传递给子例程,请在调用之前将它们推入堆栈。参数应按反转顺序推送(即最后一个参数)。由于堆栈增长,第一个参数将存储在最低地址(参数的这种反转历史上用于允许函数传递可变数量的参数)。 [来自x86调用约定]
答案 2 :(得分:1)
有3个论点。他们是rsi,rdi和rdx。返回值是rax。函数总结了三个参数。参数可以是签名的或无符号的,因为Addq适用于两者。应将所有参数和返回值视为具有相同类型(有符号或无符号64位整数)。
这是我在x64上从未见过的调用约定。因此,在转换为C之后,除非您指定自定义调用约定(假设编译器支持),否则编译器不会生成相同的程序集。
定义调用约定后,您可以说明参数的顺序是什么。在那之前你不知道rsi / rdi / rdx是第一,第二还是第三个arg。
答案 3 :(得分:0)
这篇文章,大部分都回答了我的问题。 Return value of a C function to ASM直到我完全重新考虑我的搜索词选择时,我才看到这一点。我仍在试图弄清楚传递给函数的参数数量。如果我是正确的,但是
addq %rsi, %rdi
addq %rdi, %rdx
这两行显示我已经通过了两个纪录片。一个存储在&rsi
另一个存储在%rdi
中