操作系统笔记(三)函数堆栈
ctime:2020-04-29 22:47:57 +0900|1588168077
标签(空格分隔): 技术 操作系统
练习5 完成函数调用堆栈记录的跟踪函数
函数调用的入栈顺序
主要有几种,__cdecl、__fastcall、__stdcall,都是函数的调用约定,主要决定函数的参数入栈顺序,以及入栈的参数到底是由调用者还是被调用者清除。
其中,cdecl是C语言默认的调用约定。
所有参数从右到左依次入栈,这些参数由调用者清除,称为手动清栈。被调用函数不会要求调用者传递多少参数,调用者传递过多或者过少的参数,甚至完全不同的参数都不会产生编译阶段的错误。
根据入栈顺序:参数4 参数3 参数2 参数1 返回地址 ebp 局部变量,可以写出函数:
void
print_stackframe(void) {
uint32_t ebp=read_ebp();
uint32_t eip=read_eip();
for(int i=0;i<STACKFRAME_DEPTH;++i){
cprintf("ebp:%d eip:%d ",ebp,eip);
cprintf("args: ");
for(int j=0;j<4;++j){
cprintf("%d ",*(uint32_t *)(ebp+8+j*4));
}
cprintf("\n");
print_debuginfo(eip-1);
eip=*(uint32_t *)(ebp+4);
ebp=*(uint32_t *)ebp;
}
}
一开始考虑半天,怎么判断到达栈底了,后来才发现原来要求里直接给了常数STACKFRAME_DEPTH作为栈深度,不需要判断是否到达栈底。
运行结果: