打印

在网上看到一段程序的疑问?

[复制链接]
2067|4
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
电子菜鸟435|  楼主 | 2009-10-12 17:14 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 电子菜鸟435 于 2009-10-12 17:22 编辑

昨天在网上看到别人博客里一段程序的注释,把我弄糊涂了:
void test2(int a,int b,int c)
{
int k=a,j=b,m=c;

}
GCC反汇编:
00000064 <test2>:
mov       ip,    sp                         //IP=SP;保存SP
stmdb   sp!, {fp, ip, lr, pc}     //先对SP4,再对fpiplrpc压栈。---------1
sub         fp,   ip, #4                  ; 0x4   //fp=ip-4;此时fp指向栈里面的“fp
sub         sp,   sp, #24               ; 0x18 //分配空间
str          r0,   [fp, #-28]           //
str          r1, [fp, #-32]            //
str          r2, [fp, #-36]             //参数压栈
ldr          r3, [fp, #-28]            //
str          r3, [fp, #-24]            //
ldr          r3, [fp, #-32]            //
str          r3, [fp, #-20]           //
ldr          r3, [fp, #-36]           //
str          r3, [fp, #-16]           //
sub         sp, fp, #12              ; 0xc  //sp=fp-12;此时sp指向栈里面的lr
ldmia     sp, {fp, sp, pc}        //弹栈pc=lrsp=ipfp=fp。然后地址加4---------1


以上是博客原文中的一段,其中下面两个语句把我弄糊涂了
sub        fp, ip, #4                  ; 0x4   //fp=ip-4;此时fp指向栈里面的“fp
sub        sp, fp, #12               ; 0xc    //sp=fp-12;此时sp指向栈里面的lr
我觉得
sub         fp, ip, #4                  ;此时fp指向栈里面的“pc”才对
sub         sp, fp, #12               ; 0xc  //sp=fp-12;此时sp指向栈里面的fp
因为对ARM不是很了解,所以想向前辈们请教一下,我是不是对的。




以下是该博文的全文
void test2(int a,int b,int c)
{
int k=a,j=b,m=c;

}
GCC反汇编:
00000064 <test2>:
mov       ip, sp    //IP=SP;保存SP
stmdb    sp!, {fp, ip, lr, pc}    //先对SP4,再对fpiplrpc压栈。---------1
sub         fp, ip, #4        ; 0x4   //fp=ip-4;此时fp指向栈里面的“fp
sub         sp, sp, #24     ; 0x18 //分配空间
str           r0, [fp, #-28]             //
str           r1, [fp, #-32]            //
str           r2, [fp, #-36]            //参数压栈
ldr           r3, [fp, #-28]            //
str           r3, [fp, #-24]           //
ldr           r3, [fp, #-32]            //
str            r3, [fp, #-20]          //
ldr            r3, [fp, #-36]           //
str            r3, [fp, #-16]            //
sub           sp, fp, #12               ; 0xc //sp=fp-12;此时sp指向栈里面的lr
ldmia       sp, {fp, sp, pc}          //弹栈pc=lrsp=ipfp=fp。然后地址加4---------1

汇编基础:
stmdb
sp!, {fp, ip, lr, pc} //sp=sp-4,sp=pc;
先压PC

//sp=sp-4,sp=lr;
再压lr

//sp=sp-4,sp=ip;
再压ip

//sp=sp-4,sp=fp;
再压fp
ldmia
sp, {fp, sp, pc}
//
stmdb成对使用,


//fp=sp,sp=sp+4;
先弹fp

//sp=sp,sp=sp+4;
先弹sp,此处的弹出不会影响sp,因为ldmia是一个机器周期执行完的。

//pc=sp,sp=sp+4;
先弹pc
LDRH
R0, [R13, #0xC] //
加载无符号半字数据,即低16
LDRB
R0, [R13, #0x4] //
加载一字节数据,即低8位。

注意:R11=fp;R12=ip;R13=SPR14=LRR15=PCR0,R1,R2用于传递参数和存放函数返回值。
注意;低地址的寄存器被压入低地址内存中,也就是说如果向下增长,高地址寄存器先压,向上增长测试低地址先压。
注意:根据“ARM-thumb 过程调用标准”:
1 r0-r3 用作传入函数参数,传出函数返回值。在子程序调用之间,可以将 r0-r3 用于任何用途。被调用函数在返回之前不必恢复 r0-r3---如果调用函数需要再次使用 r0-r3 的内容,则它必须保留这些内容。
2 r4-r11 被用来存放函数的局部变量。如果被调用函数使用了这些寄存器,它在返回之前必须恢复这些寄存器的值。
3 r12 是内部调用暂时寄存器 ip。它在过程链接胶合代码(例如,交互操作胶合代码)中用于此角色。在过程调用之间,可以将它用于任何用途。被调用函数在返回之前不必恢复 r12

相关帖子

沙发
电子菜鸟435|  楼主 | 2009-10-12 17:14 | 只看该作者
续上
4,寄存器 r13 是栈指针 sp。它不能用于任何其它用途。sp 中存放的值在退出被调用函数时必须与进入时的值相同。

5,寄存器 r14 是链接寄存器 lr。如果您保存了返回地址,则可以在调用之间将 r14 用于其它用途,程序返回时要恢复



6,寄存器 r15 是程序计数器 PC。它不能用于任何其它用途。



7,在中断程序中,所有的寄存器都必须保护,编译器会自动保护R4~R11,所以一般你自己只要在程序的开头

sub lr,lr,#4

stmfd sp!,{r0-r3,r12,lr};保护R0~R3,R12,LR就可以了,除非你用汇编人为的去改变R4~R11的值。(具体去看UCOS os_cpu_a.S中的IRQ中断的代码)

使用特权

评论回复
板凳
xinzha| | 2009-10-12 18:12 | 只看该作者
sub        fp, ip, #4                  ; 0x4   //fp=ip-4;此时fp指向栈里面的“fp”
sub        sp, fp, #12               ; 0xc    //sp=fp-12;此时sp指向栈里面的lr

第一句是对的,因为arm的栈是向下生长。
第二句不理解,如果是sp=fp-12;此时sp指向栈里面的lr,那就应该是指向pc,而不是lr,怀疑应该是sub        sp, ip, #12

使用特权

评论回复
地板
电子菜鸟435|  楼主 | 2009-10-13 08:52 | 只看该作者
本帖最后由 电子菜鸟435 于 2009-10-13 09:16 编辑

3# xinzha

注释里也是fp,所以应该不是sub  sp, ip, #12。
mov       ip,    sp               ;假设此时sp的内容是地址A ,则执行这条指令之后ip的内容也是A   
stmdb   sp!, {fp, ip, lr, pc}    ;此时sp的内容是A-16,A-16指向的是fp,A-4是pc。
sub         fp,   ip, #4      ;此时fp的内容是A-4是pc。
难道是我把入栈的顺序搞错了,先是fp入栈吗?               

使用特权

评论回复
5
电子菜鸟435|  楼主 | 2009-10-14 09:19 | 只看该作者
昨晚看了下资料,先入栈的是PC。按常理,弹栈的时候,最后回复的是PC,所以先入栈的也应该是PC,那么肯定是:
    sub         fp,   ip, #4      ;此时fp的内容是A-4是pc。
对于
    sub        sp, fp, #12      ; 0xc    //sp=fp-12;此时sp指向栈里面的fp
我的理解也应该是对的,在执行这条指令之后,sp指向fp,再弹栈,才能正确回复之前保存的内容。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

31

主题

183

帖子

1

粉丝