MIT 6.S081 栈的理解

在lab4中,我们要做一个backtrace的函数,来打印出函数调用的过程。 

这是xv6 栈的布局,fp为栈帧指针,sp为栈底指针。栈是从高地址向低地址扩张,整个调用过程的第一个函数在高地址,最近的函数在低地址。如A()->B()->C(),则A在高地址,C在低地址。

注意:每一个栈帧的大小是不固定的,和具体调用函数有关(局部变量不同)。但是每一个栈帧中往下0x8是返回地址,往下0x10是上一个函数对应的栈帧指针,这是固定的。

注意:分清楚栈和栈帧的概念,栈中有多个栈帧

(借用一下知乎大佬的图)

backtrace代码:

 

 关于这两行代码,实则是为了解引用取出返回值和上一个栈帧的地址。(curr_fp本来就是一个地址,所以我们通过偏移加解引用)

将整数值转换为指针并解引用也就是取该地址的值

uint64 ret = *(pte_t *)(curr_fp - 0x8);
uint64 prev_fp = *(pte_t *)(curr_fp - 0x10);

 打印一下fp看看是不是从低地址往高地址走。(因为入栈是从高地址开始向低地址扩张,现在进行返回则是相反的)

 可以看出当前fp在低地址,它的前一个fp在高地址

那么我们返回地址都是些什么呢,这实际上就是ecall调用的过程,以公开课的write函数为例

 在进入内核后,调用过程为uservec->usertrap->syscall->sys_write,我们打印返回地址一看究竟:

可以看到是符合我们预期的,栈底是sys_sleep,往上依次是syscall、usertrap 

终于搞懂了函数调用的过程了,开心!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值