名字不能取太长 2023-02-27 17:38 采纳率: 78%
浏览 32
已结题

使用objdump查看gcc编译生成的.o文件发现的调用函数的问题

以下这个kernel_main函数调用了别的函数,但是红线标注的跳转我发现他只是跳转到了上一行指令集,为什么会这样?不是应该跳转到func1函数的位置吗?

img

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


  • 写回答

2条回答 默认 最新

  • MarkHan_ 2023-02-28 09:31
    关注

    该回答引用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 查看生成的汇编代码时,你可能会看到一些看起来不太直观的跳转指令。

    根据你提供的反汇编代码,可以看出 kernel_main 调用了 func1,而 func1 又调用了 add_c。关于 kernel_main 中的跳转指令,这并不是函数调用的指令,而是用于结束程序的指令。在 RISC-V 汇编语言中,程序结束的标志是 ebreak 或 ecall 指令,这会使程序停止并返回到操作系统。因此,在 kernel_main 中,跳转指令只是让程序停止,并没有实际的函数调用。

    如果你想查看函数调用,可以在反汇编代码中查找 jal 指令。在 RISC-V 中,jal 指令用于进行函数调用。在 func1 中,你可以看到一个 jalr 指令,这是调用 add_c 的指令。该指令将 add_c 函数的地址存储在寄存器 ra 中,然后跳转到该地址执行 add_c 函数。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论 编辑记录
查看更多回答(1条)

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 3月8日
  • 已采纳回答 3月2日
  • 修改了问题 2月27日
  • 修改了问题 2月27日
  • 展开全部

悬赏问题

  • ¥15 关于#matlab#的问题:在模糊控制器中选出线路信息,在simulink中根据线路信息生成速度时间目标曲线(初速度为20m/s,15秒后减为0的速度时间图像)我想问线路信息是什么
  • ¥15 banner广告展示设置多少时间不怎么会消耗用户价值
  • ¥16 mybatis的代理对象无法通过@Autowired装填
  • ¥15 可见光定位matlab仿真
  • ¥15 arduino 四自由度机械臂
  • ¥15 wordpress 产品图片 GIF 没法显示
  • ¥15 求三国群英传pl国战时间的修改方法
  • ¥15 matlab代码代写,需写出详细代码,代价私
  • ¥15 ROS系统搭建请教(跨境电商用途)
  • ¥15 AIC3204的示例代码有吗,想用AIC3204测量血氧,找不到相关的代码。