Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/60.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
C 确定程序集中函数的返回类型_C_Assembly_Return Type - Fatal编程技术网

C 确定程序集中函数的返回类型

C 确定程序集中函数的返回类型,c,assembly,return-type,C,Assembly,Return Type,下面的代码是一个家庭作业,我理解实际的汇编命令。但是,我不确定(并且一直在寻找)如何确定函数的返回类型以及函数接受多少参数(如果有的话)。教授真的没有好好复习(单调的终身教职公主) 任务是读取汇编代码,然后根据汇编代码编写c代码。同样,我理解这些指令,只是不知道返回类型是什么,或者代码需要多少参数 .file "hw5.c" .text .p2align 4,,15 .globl p1 .type p1, @function p1: .LFB0:

下面的代码是一个家庭作业,我理解实际的汇编命令。但是,我不确定(并且一直在寻找)如何确定函数的返回类型以及函数接受多少参数(如果有的话)。教授真的没有好好复习(单调的终身教职公主) 任务是读取汇编代码,然后根据汇编代码编写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

这篇文章大部分回答了我的问题。直到我完全重新考虑了我的搜索词选择,我才发现这一点。我仍在试图计算传递到函数中的参数数量。如果我是对的话

addq    %rsi, %rdi
addq    %rdi, %rdx

这两行字告诉我,有两个字母是通过的。一个存储在
&rsi
中,另一个存储在
%rdi
中。您应该查看处理器/平台的调用约定,以了解底层实现

在调用子例程之前,调用方应保存指定为调用方保存的某些寄存器的内容。调用方保存的寄存器为EAX、ECX、EDX[x86]。由于允许被调用的子例程修改这些寄存器,如果调用方在子例程返回后依赖它们的值,则调用方必须将这些寄存器中的值推送到堆栈上(以便在子例程返回后恢复它们)。
若要将参数传递给子例程,请在调用之前将其推送到堆栈上。应按相反顺序推送参数(即,首先推送最后一个参数)。由于堆栈向下生长,第一个参数将存储在最低的地址(这种参数反转在历史上用于允许向函数传递可变数量的参数)。[来自x86调用约定]

有3个参数。它们是rsi、rdi和rdx。返回值以rax表示。函数对这三个参数求和。参数可以是有符号的,也可以是无符号的,因为Addq可以同时使用这两个参数。所有参数和返回值都应被视为具有相同的类型(有符号或无符号64位整数)

这是我在x64上从未见过的调用约定。因此,在转换为C之后,编译器将不会生成相同的程序集,除非您指定自定义调用约定(假设编译器支持该约定)

定义调用约定后,您可以说出参数的顺序。在此之前,您不知道rsi/rdi/rdx是第一个参数、第二个参数还是第三个参数。

有关调用约定文档的链接,请参阅。这看起来像是标准的SysV x86 ABI,除Windows之外的所有设备都使用它

这显然是两次64位加法,从三个输入寄存器生成一个结果,然后将结果放入
%rax

但是,您无法区分结果是有符号的还是无符号的,因为代码是相同的

此外,优化版本将跳过
mov
,使用
lea
作为非破坏性添加,输出不是输入之一:

lea  (%rdi,%rdx), %rax

“单调任期公主”哈哈,请投赞成票:)程序集没有“返回类型”的概念,也没有“参数”。你能进一步解释@immibis吗?如果是这种情况,我发现很难理解如何基于程序集编写有意义的函数。我现在从这个问题知道,用于返回的寄存器可以帮助确定返回类型,我仍在处理参数。汇编语言有一个调用约定h用于确定上面传递的内容。可以看到使用了
rdi
rsi
rdx
。正好如此,64位调用约定使用了前六个整数参数(从左起)这些参数按顺序在RDI、RSI、RDX、RCX、R8和R9中传递。因此,在RDI、RSI和RDX中有3个参数传递给您的函数。@immibis这是我知道的,谢谢您的洞察力。我应该重新编写我的问题。我想说的是如何翻译C返回语句和从程序集传递的参数。我看不到它位于调用约定和返回寄存器中。“addq%rdi,%rdx”将rdi添加到rdx。您认为rdx的初始值来自何处?(提示:您可能错误地认为它只是两个参数).@davmac yep,你说得对,我注意到当我意识到我对第二个add命令很傻的时候已经是三点了。谢谢!@ChristopherJakob查看,它描述了哪个参数是什么寄存器。这是SysV调用约定,除了Windows以外的所有东西都使用它。(Linux、OS X、Solaris等)X86_64有一个已定义的调用约定,所以您知道顺序是什么。@DavidC.Rankin我不知道调用约定(SysV)。没有它,我就不能说args的顺序是什么。顺便说一句,Peter指出,没有一个X86_64调用约定。我理解,这就是为什么您没有因为它而被点名。
:)
第2段与此无关,这是一个叶函数,它只使用保存其参数的寄存器。程序集显然使用的是
x86-64
,它具有完全不同的调用约定。显然,从输出来看,它是Redhat Linux;-)@迈克尔佩奇:你是在取笑我的“显然”吗?这很公平我有时会对“简单”的问题感到恼火,然后低声回答。当我阅读了这个问题,看看它是否真的像它看起来那么简单的时候,我已经有了一个答案。我经常把它作为一个评论开始,然后意识到它已经变成了一个答案,并把它作为一个评论发布。我在结尾放了一张眨眼的笑脸。我只是在开玩笑。你可以说我为什么选择Redhat Linux。从给出的代码中看不出来,但我碰巧注意到了这一点:(最底部显示的输出是Redhat)。我去搜索是因为我觉得这个问题可能遗漏了什么。@MichaelPetch:我知道你在开玩笑,但我不知道这是怎么回事