若想更好地理解函数的多级调用、线程切换其本质,都需要对栈有更加深入的认识。
一、如何生成反汇编
在上图框中输入
fromelf --text -a -c --output=test.dis xxx.axf
// 把下图中的axf文件(包括路径)替换掉 "xxx.axf"
然后编译即可。可在project目录找到 “test.dis”。
二、解析反汇编代码
以如下示例:
char heap_buf[1024];
int pos = 0;
void *my_malloc(int size)
{
int old_pos = pos;
pos += size;
return &heap_buf[old_pos];
}
void my_free(void *buf)
{
/* err */
}
void c_fun(void)
{
}
void b_fun(void)
{
}
int a_fun(int val)
{
int a = 8;
a += val;
b_fun();
c_fun();
return a;
}
int main(void)
{
char ch = 65; // char ch = 'A';
int i;
char *buf = my_malloc(100);
unsigned char uch = 200;
for (i = 0; i < 26; i++)
buf[i] = 'A' + i;
a_fun(46);
return 0;
}
在反汇编代码中搜索"main",定位到“i.main”:
当执行到0x800018a 时,这里的是一条 BL 指令,跳转到 a_func() 函数去,地址为0x8000154。在跳转之前,下一条指令的地址 0x800018e 已经存入到 LR寄存器里,所以可以看到一进入 a_func(),第一条指令就是先将LR寄存器的值入栈,这样才能在执行完子函数 a_func 之后返回到 main 函数之前跳转位置的下一步。
另外,注意黄色框里的两个变量,将十六进制转换成十进制,其实这是65和100,这是编译器优化的结果(将变量写入寄存器速度更快,而不是写入栈中)。如果不想让编译器优化,在变量定义之前加上 volatile,如下:
volatile char ch = 65; // char ch = 'A';
相应的反汇编为:
可以看到 65 被写入到了栈中,这便是告知编译器不优化的结果。