- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
test.c(裸机)
#include <stdio.h>
int add1(int a, int b)
{
int c;
c = a + b;
return c;
}
int main()
{
int x, y, z;
x = 3;
y = 4;
z = add1(x,y);
printf("z = %d\n", z);
}
我愿意
aarch64-none-elf-gcc test.c -specs=rdimon.specs
并得到a.out。我愿意
aarch64-none-elf-objdump -d a.out
并得到了汇编代码。这里是主要功能。
00000000004002e0 <add1>:
4002e0: d10083ff sub sp, sp, #0x20 <-- reduce sp by 0x20 (just above it are saved fp and lr of main)
4002e4: b9000fe0 str w0, [sp, #12] <-- save first param x at sp + 12
4002e8: b9000be1 str w1, [sp, #8] <-- save second param y at sp + 8
4002ec: b9400fe1 ldr w1, [sp, #12] <-- load w1 with x
4002f0: b9400be0 ldr w0, [sp, #8] <-- load w0 with y
4002f4: 0b000020 add w0, w1, w0 <-- w0 = w1 + w0
4002f8: b9001fe0 str w0, [sp, #28] <-- store x0 to sp+28
4002fc: b9401fe0 ldr w0, [sp, #28] <-- load w0 with the result (seems redundant)
400300: 910083ff add sp, sp, #0x20 <-- increment sp by 0x20
400304: d65f03c0 ret
0000000000400308 <main>:
400308: a9be7bfd stp x29, x30, [sp, #-32]! <-- save x29(fp) and x30(lr) at sp - 0x20
40030c: 910003fd mov x29, sp <-- set fp to new sp, the base of stack growth(down)
400310: 52800060 mov w0, #0x3 // #3
400314: b9001fe0 str w0, [sp, #28] <-- x is assigned in sp + #28
400318: 52800080 mov w0, #0x4 // #4
40031c: b9001be0 str w0, [sp, #24] <-- y is assiged in sp + #24
400320: b9401be1 ldr w1, [sp, #24] <-- load func param for y
400324: b9401fe0 ldr w0, [sp, #28] <-- load func param for x
400328: 97ffffee bl 4002e0 <add1> <-- call main1 (args are in w0, w1)
40032c: b90017e0 str w0, [sp, #20] <-- store x0(result z) to sp+20
400330: b94017e1 ldr w1, [sp, #20] <-- load w1 with the result (why? seems redundant. it's already in w0)
400334: d0000060 adrp x0, 40e000 <__sfp_handle_exceptions+0x28>
400338: 91028000 add x0, x0, #0xa0 <-- looks like loading param x0 for printf
40033c: 940000e7 bl 4006d8 <printf>
400340: 52800000 mov w0, #0x0 // #0 <-- for main's return value..
400344: a8c27bfd ldp x29, x30, [sp], #32 <-- recover x29 and x30 (look's like values in x29, x30 was used in the fuction who called main)
400348: d65f03c0 ret
40034c: d503201f nop
我用
<--
添加了我的理解标记。有人可以看到代码并给我一些更正吗?任何小的评论将不胜感激。 (请见
<main>
)
最佳答案
在为 main
布置堆栈时,编译器必须满足以下约束:
x29
和 x30
需要保存在堆栈中。它们每个占用 8 个字节。x,y,z
需要堆栈空间,每个 4 个字节。 (如果您正在优化,您会看到它们被保存在寄存器中,或者完全不存在优化。)这使我们总共得到了 8+8+4+4+4=28
字节。sp
必须始终保持与 16 字节对齐;这是架构和 ABI 约束(操作系统可以选择放宽此要求,但通常不会)。所以我们不能从 sp
中减去 28 ;我们必须四舍五入到 16 的下一个倍数,即 32。0x20
你提到的来自。请注意,它完全用于
main
使用的堆栈内存。本身。它不是一个普遍的常数;如果您从
main
中添加或删除了足够多的局部变量,您会看到它发生了变化。 .
printf
需要。如
printf
自己的局部变量需要栈空间,那么
printf
内的代码将不得不照顾相应地调整堆栈指针。编译时的编译器
main
不知道那会有多少空间,也不在乎。
x29, x30, x, y, z
在它将为自己创建的 32 字节堆栈空间内。除了以下几点之外,选择放在哪里几乎是完全任意的。
x29, x30
在分配的空间内的某个地方。这一切都可以在使用预索引存储对指令
stp x29, x30, [sp, #-32]!
的单个指令中完成。 .它减去
32
来自
sp
,然后存储
x29
和
x30
在地址开始的 16 个字节中
sp
现在点。所以为了使用这个指令,我们必须接受放置
x29
和
x30
在分配空间的底部,偏移量
[sp+0]
和
[sp+8]
相对于
sp
的新值.将它们放在其他任何地方需要额外的说明并且效率较低。
x29, x30
在堆栈上按该顺序连续,当它们被使用时(5.2. 3))
[sp+16]
开始一起玩,其中
x,y,z
必须放置。编译器选择将它们放在地址
[sp+28], [sp+24], [sp+20]
分别。
[sp+16]
处的 4 个字节保持未使用,但请记住,我们必须在某处浪费 4 个字节才能实现正确的堆栈对齐。安排这些对象的选择,以及哪个插槽不使用,完全是任意的,任何其他安排也一样有效。
关于assembly - 理解aarch64汇编函数调用,栈是如何操作的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66098678/
C语言sscanf()函数:从字符串中读取指定格式的数据 头文件: ?
最近,我有一个关于工作预评估的问题,即使查询了每个功能的工作原理,我也不知道如何解决。这是一个伪代码。 下面是一个名为foo()的函数,该函数将被传递一个值并返回一个值。如果将以下值传递给foo函数,
CStr 函数 返回表达式,该表达式已被转换为 String 子类型的 Variant。 CStr(expression) expression 参数是任意有效的表达式。 说明 通常,可以
CSng 函数 返回表达式,该表达式已被转换为 Single 子类型的 Variant。 CSng(expression) expression 参数是任意有效的表达式。 说明 通常,可
CreateObject 函数 创建并返回对 Automation 对象的引用。 CreateObject(servername.typename [, location]) 参数 serv
Cos 函数 返回某个角的余弦值。 Cos(number) number 参数可以是任何将某个角表示为弧度的有效数值表达式。 说明 Cos 函数取某个角并返回直角三角形两边的比值。此比值是
CLng 函数 返回表达式,此表达式已被转换为 Long 子类型的 Variant。 CLng(expression) expression 参数是任意有效的表达式。 说明 通常,您可以使
CInt 函数 返回表达式,此表达式已被转换为 Integer 子类型的 Variant。 CInt(expression) expression 参数是任意有效的表达式。 说明 通常,可
Chr 函数 返回与指定的 ANSI 字符代码相对应的字符。 Chr(charcode) charcode 参数是可以标识字符的数字。 说明 从 0 到 31 的数字表示标准的不可打印的
CDbl 函数 返回表达式,此表达式已被转换为 Double 子类型的 Variant。 CDbl(expression) expression 参数是任意有效的表达式。 说明 通常,您可
CDate 函数 返回表达式,此表达式已被转换为 Date 子类型的 Variant。 CDate(date) date 参数是任意有效的日期表达式。 说明 IsDate 函数用于判断 d
CCur 函数 返回表达式,此表达式已被转换为 Currency 子类型的 Variant。 CCur(expression) expression 参数是任意有效的表达式。 说明 通常,
CByte 函数 返回表达式,此表达式已被转换为 Byte 子类型的 Variant。 CByte(expression) expression 参数是任意有效的表达式。 说明 通常,可以
CBool 函数 返回表达式,此表达式已转换为 Boolean 子类型的 Variant。 CBool(expression) expression 是任意有效的表达式。 说明 如果 ex
Atn 函数 返回数值的反正切值。 Atn(number) number 参数可以是任意有效的数值表达式。 说明 Atn 函数计算直角三角形两个边的比值 (number) 并返回对应角的弧
Asc 函数 返回与字符串的第一个字母对应的 ANSI 字符代码。 Asc(string) string 参数是任意有效的字符串表达式。如果 string 参数未包含字符,则将发生运行时错误。
Array 函数 返回包含数组的 Variant。 Array(arglist) arglist 参数是赋给包含在 Variant 中的数组元素的值的列表(用逗号分隔)。如果没有指定此参数,则
Abs 函数 返回数字的绝对值。 Abs(number) number 参数可以是任意有效的数值表达式。如果 number 包含 Null,则返回 Null;如果是未初始化变量,则返回 0。
FormatPercent 函数 返回表达式,此表达式已被格式化为尾随有 % 符号的百分比(乘以 100 )。 FormatPercent(expression[,NumDigitsAfterD
FormatNumber 函数 返回表达式,此表达式已被格式化为数值。 FormatNumber( expression [,NumDigitsAfterDecimal [,Inc
我是一名优秀的程序员,十分优秀!