首页
社区
课程
招聘
[旧帖] 程序调用时的堆栈链表时如何处理的 0.00雪花
发表于: 2011-2-5 15:29 3350

[旧帖] 程序调用时的堆栈链表时如何处理的 0.00雪花

2011-2-5 15:29
3350
在书 <LINUX POWERPC详解:核心篇> 31页讲到: 本节内容对于程序员深入理解powerpc体系结构十分重要,
指令集,寄存器,及于编译器有关的ABI是处理器体系结构的精华所在。由于篇幅所限,本书不能详述。
看到最后语句傻眼了,还是不明白如何进行堆栈操作,如何单向链表,本地变量地址如何计算寻址,带入
参数如何传递, 既然是精华所在为何此处略去一千字...

shows the stack frame organization including all optional areas:
        ------------------------------------------------
        | FPR Save Area                           |
        | (optional, size varies)                   |
        ------------------------------------------------
        | GPR Save Area                           |
        | (optional, size varies)                   |
        ------------------------------------------------
        | CR Save Word                           |
        | (optional)                           |
        ------------------------------------------------
        | Local Variables Area                   |
        | (optional, size varies)                   |
        ------------------------------------------------
        | Function Parameters Area           |
        | (optional, size varies)                   |
        ------------------------------------------------
        | Padding to adjust size to multiple of 8 bytes |
        | (optional, size varies 1-7 bytes)           |
        ------------------------------------------------
        | LR Save Word                           |
        | Back Chain Word                   |
        ------------------------------------------------

       . 调用前的堆栈   .               . 调用后的堆栈   .
       .                .               .                .
       |                |               |                |
       +----------------+-              +----------------+-
       | Parameter area | |             | Parameter area | |
       +----------------+ +-调用函数    +----------------+ +-调用函数
       | Linkage area   | |             | Linkage area   | |
SP --->+----------------+-              +----------------+-
       |  堆栈增长方向  |               | Saved registers| |
       .        |       .               +----------------+ |
       .        v       .               | Local variables| |
                                        +----------------+ +-被调函数
                                        | Parameter area | |
                                        +----------------+ |
                                        | Linkage area   | |
                                 SP --->+----------------+-
                                        |  堆栈增长方向  |
                                        .        |       .

下面是简单的反汇编,似乎看的明白又不明白 :(
int average(int a, int b)
{
    return (a + b) / 2;
}

int main(void)
{
        int val = 0;
        val =  average(0xaa, 0x55);
        return val;
}

10000480 <average>:
10000480:        7c 64 1a 14         add     r3,r4,r3
10000484:        7c 63 0e 70         srawi   r3,r3,1
10000488:        7c 63 01 94         addze   r3,r3
1000048c:        4e 80 00 20         blr

10000490 <main>:
10000490:        94 21 ff f0         stwu    r1,-16(r1)                # -16(r1) = r1, r1 = -16(r1)
10000494:        7c 08 02 a6         mflr    r0                        # r0 = lr
10000498:        90 01 00 14         stw     r0,20(r1)                # 20(r1) = lr
1000049c:        38 60 00 aa         li      r3,170                         # r3 = 0xaa
100004a0:        38 80 00 55         li      r4,85                          # r4 = 0xbb
100004a4:        4b ff ff dd         bl      10000480 <average>
100004a8:        80 01 00 14         lwz     r0,20(r1)                # r0 = 20(r1)
100004ac:        7c 08 03 a6         mtlr    r0                        # lr = r0  恢复返回地址
100004b0:        38 21 00 10         addi    r1,r1,16                # r1 += 16 恢复sp
100004b4:        4e 80 00 20         blr

问题:
1. 20(r1) = lr 其中 20 这个值始终不明白,在稍微长一点的函数里这个值会有所变化,如何计算它(在遵循EABI标准情况下)
2. r1(sp) 和 lr 什么时候需要保存以及恢复。
3. 在gdb里是否可以看到到整个链表。
3. 总结就是堆栈处理的单向链表如何看。

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 0
支持
分享
最新回复 (2)
雪    币: 354
活跃值: (65)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
没人回复:(
2011-2-7 05:15
0
雪    币: 84
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
1. 20(r1) = lr 其中 20 这个值始终不明白,在稍微长一点的函数里这个值会有所变化,如何计算它(在遵循EABI标准情况下)
re: 这是根据之前的栈指针处理情况来的。
main第一句,栈指针-16,就是为调用average预留了16字节的空间,也就是你前边示意图中的【调用后的堆栈】比【调用前的堆栈】增加的部分:Saved registers、Local variables、Parameter area、Linkage area。
注意这16字节是为被调用者,也就是average预留的,因此main函数的Saved registers、Local variables、Parameter area、Linkage area,不能放在这个空间,也就是r1+4、r1+8、r1+12、r1+16这4个位置都不能用,所以main能用的堆栈最小地址就是r1+20。
由于这个函数比较简单,所以只预留了16字节,如果average函数中有非常多的Saved registers、Local variables、Parameter area、Linkage area,这个值就会变大,相应的后边的20也会变大。

2. r1(sp) 和 lr 什么时候需要保存以及恢复。
re: 在ABI规范里应该有,函数调用前保存,调用后恢复。
从你贴出的反汇编看,是由调用者(你这里就是main)负责做这个工作的,也有些硬件环境是由被调用者(你这里就是average)负责做这个工作。
还有些环境,调用规则是可以配置的,由编译器统一配置,或者是在代码中加编译伪指令控制部分函数的调用规则。

3. 在gdb里是否可以看到到整个链表。
3. 总结就是堆栈处理的单向链表如何看。
re: gdb有ltrace,具体你去查gdb帮助。
2011-2-25 22:16
0
游客
登录 | 注册 方可回帖
返回
//