打印
[ZLG-ARM]

关于ldr指令的问题(2),请求正解!周公,我仔细看书了

[复制链接]
1674|5
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
zlg_arm|  楼主 | 2007-5-4 20:39 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
还是有点疑问 

我看了,汇编代码也找了!
我觉得很奇怪的一点就是,为什么在thumb的指令中,使用ldr加载了一个地址,为什么这个地址的指向是该指令的高地址位,比如该指令是在0x4000001c,0x4000001d这两个地址空间内保存,并且我在这条thumb指令之前加了语句标号FUN,然后使用ldr  r1,=FUN加载这个地址,虽然执行的时候没有任何问题!但是这条指令加载的值确是0x4000001d,这是我觉得很奇怪的地方!我看了我使用的都是小端模式的!

代码如下
        area    example,code,readonly
        entry
        code32
        
    
Start    cmp        r0,        #0
        adr        r7,        FUN+1
        bx        r7
        cmp r0,r1
        cmp r0,r1
        cmp r0,r1
        cmp r0,r1

        
        
        code16
        
FUN        cmp r0,r2
        cmp r0,r2
        cmp r0,r2
        ldr    r1,=FUN
        
        cmp r0,r2
        cmp r0,r2
        cmp r0,r2
        mov    pc,r1

        end        
 
 
反汇编后如下代码
Start    [0xe3500000]   cmp      r0,#0
00000004    [0xe28f7011]   add      r7,pc,#0x11 ; #0x1d
00000008    [0xe12fff17]   bx       r7
0000000c    [0xe1500001]   cmp      r0,r1
00000010    [0xe1500001]   cmp      r0,r1
00000014    [0xe1500001]   cmp      r0,r1
00000018    [0xe1500001]   cmp      r0,r1
FUN        [0x4290]   cmp      r0,r2  <--此处
0000001e        [0x4290]   cmp      r0,r2
00000020        [0x4290]   cmp      r0,r2
00000022        [0x4902]   ldr      r1,0x0000002c ; = #0x0000001d <--此处
00000024        [0x4290]   cmp      r0,r2
00000026        [0x4290]   cmp      r0,r2
00000028        [0x4290]   cmp      r0,r2
0000002a        [0x468f]   mov      pc,r1
0000002c    [0x0000001d]   dcd      0x0000001d  ....

第一个问题的原因也就在这里,就是应为adr取得是的低地址,而ldr取得是高地址?我在书里面没有找到关于这方面的说明阿?

但是在arm状态下adr和ldr的结果是一样的,都是取得4字节指令的低地址!就是在thumb状态下不一样了! 

相关帖子

沙发
zlgARM| | 2007-5-5 17:22 | 只看该作者

zlg_arm

您的程序里用的LDR和ADR是伪指令,不是真正的ARM汇编指令。编译时,编译器会将它们用汇编指令替换,并完成伪指令定义的操作。
此外,这两个伪指令的功能并不是加载指令地址,而是加载指定的一个常量到寄存器。至于这个常量是不是地址,它并不关心——你可以用EQU来定义个常量,再让这两个指令加载它试试。
之所以执行没有问题,是因为会自动忽略地址的低2位(ARM模式)或低1位(Thumb模式)。

建议您把ADR加载的例子也反编译一下看看。

使用特权

评论回复
板凳
zlg_arm|  楼主 | 2007-5-5 19:25 | 只看该作者

周公,还是没有正面回答我的问题啊

周公阿,我两条指令都在上面反汇编了,您没有看到马? 下面我详细标示了     


反汇编后如下代码
Start    [0xe3500000]   cmp      r0,#0
00000004    [0xe28f7011]   add      r7,pc,#0x11 ; #0x1d<--此处使用adr指令在+1的情况下就是0x0000001d,说明adr指令加载地址没有任何问题
00000008    [0xe12fff17]   bx       r7
0000000c    [0xe1500001]   cmp      r0,r1
00000010    [0xe1500001]   cmp      r0,r1
00000014    [0xe1500001]   cmp      r0,r1
00000018    [0xe1500001]   cmp      r0,r1
FUN             [0x4290]   cmp      r0,r2  <--此处FUN的语句标号地址应该是0x0000001c(按照小端对齐方式来说)
0000001e        [0x4290]   cmp      r0,r2
00000020        [0x4290]   cmp      r0,r2
00000022        [0x4902]   ldr      r1,0x0000002c ; = #0x0000001d <--此处,他怎么会是1d而不是1c
00000024        [0x4290]   cmp      r0,r2
00000026        [0x4290]   cmp      r0,r2
00000028        [0x4290]   cmp      r0,r2
0000002a        [0x468f]   mov      pc,r1
0000002c    [0x0000001d]   dcd      0x0000001d  .... 

周公我找了好几本书了,上面都说adr确实是专门用来加载地址的!
但是我看的书上也都写了对于ldr的指令也可以用于32位的常数或者地址的加载,但是这似乎有悖于我的实验程序!!

我只想让您给个解释,到底是不是这样的结果,应该说对于两段程序同在arm状态下或者同时在thumb状态下就可以顺利使用ldr指令取得地址,但是如果两段程序跨了状态,尤其是arm下调用thumb的程序,就不可以使用ldr了??
在周公您实际的工作中有没有这样的问题!?

使用特权

评论回复
地板
zlg_arm|  楼主 | 2007-5-6 14:00 | 只看该作者

周公这是什么道理啊

    area    example,code,readonly
    entry
    code32
Start    cmp r0,    #0
    adr r7,    FUN1+1
    bx  r7
    cmp r0,r1
    cmp r0,r1
    cmp r0,r1
    cmp r0,r1
        
    code16
FUN1    cmp r0,r2
    adr r2,FUN<--此处
    ldr r1,=FUN<--此处
    cmp r0,r2
FUN    cmp r0,r2
    cmp r0,r2
    mov pc,r1
    end

反汇编
Start    [0xe3500000]   cmp      r0,#0
40000004    [0xe28f7011]   add      r7,pc,#0x11 ; #0x4000001d
40000008    [0xe12fff17]   bx       r7
4000000c    [0xe1500001]   cmp      r0,r1
40000010    [0xe1500001]   cmp      r0,r1
40000014    [0xe1500001]   cmp      r0,r1
40000018    [0xe1500001]   cmp      r0,r1
FUN1        [0x4290]   cmp      r0,r2
4000001e        [0xa201]   adr      r2,0x40000024<--此处
40000020        [0x4902]   ldr      r1,0x4000002c ; = #0x40000025<--此处
40000022        [0x4290]   cmp      r0,r2
FUN        [0x4290]   cmp      r0,r2
40000026        [0x4290]   cmp      r0,r2
40000028        [0x468f]   mov      pc,r1
4000002a        [0x0000]   dcw      0x0000        ..
4000002c    [0x40000025]   dcd      0x40000025  %..@

上面的这段代码更加明显的显示了adr和ldr就是渠道的不一样!周公这是什么道理啊???

使用特权

评论回复
5
zlg_arm|  楼主 | 2007-5-6 14:29 | 只看该作者

常量确实没有问题,就是取得地址标号的时候有这个问题

常量确实没有问题,就是取得地址标号的时候有这个问题

使用特权

评论回复
6
zlg_arm|  楼主 | 2007-5-6 23:21 | 只看该作者

得到正解了!!哈哈

 wowow 发表于 2007-5-6 19:14 ARM 论坛 ←返回版面    

10楼: 这个要仔细看资料了 

参考资料:
[1]RVCT 3.0 Developer Guide
http://www.arm.com/pdfs/DUI0203G_rvct_developer_guide.pdf
[2]RVCT 3.0 Assembler Guide
http://www.arm.com/pdfs/DUI0204G_rvct_assembler_guide.pdf

[1]中page 4-10
Exporting symbols
If you export a symbol that references Thumb instructions, the linker automatically adds one to the address of any label in Thumb code.

If you do not export a symbol, you must manually add one to the symbol that references the Thumb instructions. In Example 4-2 on page 4-9 it is ThumbProg+1. This is because all references are resolved by the assembler, and the linker never detects the symbol.

[2]中page 2-29 2.5.3 Loading with LDR Rd, =const

[1]中的第四章都值得一看。

结论:
adr指令中引用的是FUN的地址,而LDR引用的是FUN的地址加1后保存在literal pool中的值。 
 

使用特权

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

本版积分规则

17

主题

72

帖子

0

粉丝