以下这个kernel_main函数调用了别的函数,但是红线标注的跳转我发现他只是跳转到了上一行指令集,为什么会这样?不是应该跳转到func1函数的位置吗?
C语言代码如下:
```c
int add_c(int a,int b)
{
return a+b;
}
int func1(void)
{
int a=1;
int b=2;
return add_c(a,b);
}
void main(void)
{
func1();
}
其他两个函数反汇编如下:
0000000000000000 <add_c>:
0: 1101 add sp,sp,-32
2: ec22 sd s0,24(sp)
4: 1000 add s0,sp,32
6: 87aa mv a5,a0
8: 872e mv a4,a1
a: fef42623 sw a5,-20(s0)
e: 87ba mv a5,a4
10: fef42423 sw a5,-24(s0)
14: fec42783 lw a5,-20(s0)
18: 873e mv a4,a5
1a: fe842783 lw a5,-24(s0)
1e: 9fb9 addw a5,a5,a4
20: 2781 sext.w a5,a5
22: 853e mv a0,a5
24: 6462 ld s0,24(sp)
26: 6105 add sp,sp,32
28: 8082 ret
000000000000002a <func1>:
2a: 1101 add sp,sp,-32
2c: ec06 sd ra,24(sp)
2e: e822 sd s0,16(sp)
30: 1000 add s0,sp,32
32: 4785 li a5,1
34: fef42623 sw a5,-20(s0)
38: 4789 li a5,2
3a: fef42423 sw a5,-24(s0)
3e: fe842703 lw a4,-24(s0)
42: fec42783 lw a5,-20(s0)
46: 85ba mv a1,a4
48: 853e mv a0,a5
4a: 00000097 auipc ra,0x0
4e: 000080e7 jalr ra # 4a <func1+0x20>
52: 87aa mv a5,a0
54: 853e mv a0,a5
56: 60e2 ld ra,24(sp)
58: 6442 ld s0,16(sp)
5a: 6105 add sp,sp,32
5c: 8082 ret
该回答引用GPTᴼᴾᴱᴺᴬᴵ
这可能是因为函数调用的过程中使用了栈帧的结构,导致了代码中出现了一些不太直观的跳转指令。具体来说,当 main 函数调用 func1 函数时,它需要为 func1 函数创建一个新的栈帧,并将一些数据(如返回地址和参数)压入栈中。然后,它使用跳转指令 call 来跳转到 func1 函数的起始地址。
在 func1 函数中,它调用了 add_c 函数,并将结果返回给 main 函数。为了执行这个调用,func1 函数需要将其参数压入栈中,然后使用跳转指令 call 来跳转到 add_c 函数的起始地址。当 add_c 函数返回结果时,它将结果存储在寄存器中,然后使用跳转指令 ret 返回到 func1 函数。
当 func1 函数执行完毕后,它使用跳转指令 ret 来返回到 main 函数。在 main 函数中,它会清除栈帧中的数据,并使用跳转指令 ret 来返回到调用它的函数。
在上述过程中,为了处理栈帧,编译器需要使用一些不同的跳转指令,如 call 和 ret。在这些指令中,一些指令实际上只是将当前指令的地址压入栈中,然后跳转到指定的地址,以便返回时可以正确地返回到调用它的函数。因此,当你使用 objdump 查看生成的汇编代码时,你可能会看到一些看起来不太直观的跳转指令。
如果你想查看函数调用,可以在反汇编代码中查找 jal 指令。在 RISC-V 中,jal 指令用于进行函数调用。在 func1 中,你可以看到一个 jalr 指令,这是调用 add_c 的指令。该指令将 add_c 函数的地址存储在寄存器 ra 中,然后跳转到该地址执行 add_c 函数。
在gdb中单步逐条指令执行一下