gpt4 book ai didi

c - RISC-V汇编-堆栈布局-函数调用

转载 作者:太空宇宙 更新时间:2023-11-04 03:33:41 27 4
gpt4 key购买 nike

目前我正在使用 RISC-V 处理器实现。我需要运行部分手工制作的汇编代码。 (最后会有动态代码注入(inject)。)为此,我必须了解 RISC-V 汇编中函数调用的基础知识。

我发现这个主题非常有帮助:confusion about function call stack

但我仍在为函数调用的堆栈布局而苦苦挣扎。请考虑以下 C 代码:

void some_func(int a, int b, int* c){
int cnt = a;
for(;cnt > 0;cnt--){
*c += b;
}
}

void main(){
int a = 5;
int b = 6;
int c = 0;

some_func(a,b,&c);
}

该程序通过一系列加法实现基本乘法。派生的汇编代码 (riscv64-unknown-elf-gcc -nostartfiles mul.c -o mul && riscv64-unknown-elf-objdump -D mul) 如下所示:

0000000000010000 <some_func>:
10000: fd010113 addi sp,sp,-48
10004: 02813423 sd s0,40(sp)
10008: 03010413 addi s0,sp,48
1000c: fca42e23 sw a0,-36(s0)
10010: fcb42c23 sw a1,-40(s0)
10014: fcc43823 sd a2,-48(s0)
10018: fdc42783 lw a5,-36(s0)
1001c: fef42623 sw a5,-20(s0)
10020: 0280006f j 10048 <some_func+0x48>
10024: fd043783 ld a5,-48(s0)
10028: 0007a703 lw a4,0(a5)
1002c: fd842783 lw a5,-40(s0)
10030: 00f7073b addw a4,a4,a5
10034: fd043783 ld a5,-48(s0)
10038: 00e7a023 sw a4,0(a5)
1003c: fec42783 lw a5,-20(s0)
10040: fff7879b addiw a5,a5,-1
10044: fef42623 sw a5,-20(s0)
10048: fec42783 lw a5,-20(s0)
1004c: fcf04ce3 bgtz a5,10024 <some_func+0x24>
10050: 00000013 nop
10054: 02813403 ld s0,40(sp)
10058: 03010113 addi sp,sp,48
1005c: 00008067 ret

0000000000010060 <main>:
10060: fe010113 addi sp,sp,-32
10064: 00113c23 sd ra,24(sp)
10068: 00813823 sd s0,16(sp)
1006c: 02010413 addi s0,sp,32
10070: 00500793 li a5,5
10074: fef42623 sw a5,-20(s0)
10078: 00600793 li a5,6
1007c: fef42423 sw a5,-24(s0)
10080: fe042223 sw zero,-28(s0)
10084: fe440793 addi a5,s0,-28
10088: 00078613 mv a2,a5
1008c: fe842583 lw a1,-24(s0)
10090: fec42503 lw a0,-20(s0)
10094: f6dff0ef jal 10000 <some_func>
10098: 00000013 nop
1009c: 01813083 ld ra,24(sp)
100a0: 01013403 ld s0,16(sp)
100a4: 02010113 addi sp,sp,32
100a8: 00008067 ret

需要说明的重要步骤是:(some_func(int,int,int))

   10060:   fe010113            addi    sp,sp,-32
10064: 00113c23 sd ra,24(sp)
10068: 00813823 sd s0,16(sp)
1006c: 02010413 addi s0,sp,32

和: (main())

   10000:   fd010113            addi    sp,sp,-48
10004: 02813423 sd s0,40(sp)
10008: 03010413 addi s0,sp,48

根据我的理解:堆栈指针被移动以为返回地址和参数腾出空间。 (main 可能是这里的特例。)传递的参数位于堆栈时如何处理?他们如何取回?总的来说,方法论对我来说很清楚,但我要如何手动编写这个片段才能工作。

关于相关主题,堆栈应该有点像

| ???                            |
| params for some_func() <???> |
| ra of some_func() |
| locals of main() <int c> |
| locals of main() <int b> |
| locals of main() <int a> |
| params for main() <None> |

但仅此而已。谁能指出这是如何安排的,以及这两个 list (函数调用)如何相互关联?

最佳答案

你想知道的由 RISC-V calling conventions 指定.

要点:

函数参数通常在 a0a7 寄存器中传递,而不是在堆栈中传递。如果 a* 寄存器中没有剩余空间,则仅通过堆栈传递参数。

一些寄存器是调用者保存的,而另一些是被调用者保存的(参见表 26.1,第 26 章 RISC-V 汇编程序员手册,在 RISC-V base specification 中,2019-06-08 批准)。这意味着在调用函数之前,调用者必须将所有调用者保存的寄存器保存到堆栈中,如果它想保留它们的内容。同样,如果被调用函数想要将它们用于自己的目的,则必须将所有被调用者保存的寄存器保存到堆栈中。

关于c - RISC-V汇编-堆栈布局-函数调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34182330/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com