打印

关于ldr指令的问题(2),请求正解

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

我看了,汇编代码也找了!
我觉得很奇怪的一点就是,为什么在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状态下不一样了! 

 

相关帖子

沙发
zlg_arm|  楼主 | 2007-5-5 19:27 | 只看该作者

没有人作答??????

没有人作答??????

使用特权

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

求求高手来解答

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

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

使用特权

评论回复
地板
wowow| | 2007-5-6 10:25 | 只看该作者

这似乎是区分ARM/THUMB指令的一个标志

THUMB中的程序地址都是实际地址加1,也就都是奇数。不记得在哪个Pdf提到过。如果没有这个区别,ARM执行时怎么知道调用的是ARM程序还是thumb呢?

使用特权

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

楼上说的不是很对!!请高手给点答案

    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就是取到的值的不一样!这是什么道理啊???没有发现你说的这个理由啊!!

使用特权

评论回复
6
ferry| | 2007-5-6 15:00 | 只看该作者

re

adr 伪指令取相对当前指令偏移的标号地址,这是个相对地址.
ldr 伪指令取操作数的地址,这是个绝对地址.代码中的操作数是标号的值(=FUN):0x40000025,存放这个值的地址是4000002c.
另外注意标号地址是16位地址(code16).

使用特权

评论回复
7
zlg_arm|  楼主 | 2007-5-6 15:18 | 只看该作者

楼上的有点误解

1、首先adr确实是利用pc来取得FUN标号的地址,但是这只是取得地址手段的不同,不应该会导致值的不同,而且对于使用ldr或者是adr这两种方法取得不同的地址却可以同样的来使用,你可以在最后使用mov pc,r1或者r2来尝试,都可以正确跳转这是我最头痛的!!!
2、对于code16的标示,估计您误解了,他的地址还是32位的,只是代码是16位的,所以只需要两个字节来表示,你可以仔细看到ldr和adr这两个指令,前者把值取在指令高地址位,而adr却取在指令低地址位

使用特权

评论回复
8
ferry| | 2007-5-6 16:20 | 只看该作者

re

1.相对地址绝对地址值是不同的,只有0起点时是相同的.仔细想想.
2.code16地址两字节对齐,code32 4字节对齐.应该是这个意思.

使用特权

评论回复
9
zlg_arm|  楼主 | 2007-5-6 16:38 | 只看该作者

问题依旧,严重哦

我明白楼上的意思!那楼上的认为那种方法取得的地址才是正确的?!我不知道应该以那种方法为准!尤其当这种情况在arm状态下取得thumb的地址的时候,那么两种方法取得的值,其中只有adr的是正确的,而ldr的却不能正确执行。在thumb的情况下,两者都可以正确执行!

使用特权

评论回复
10
wowow| | 2007-5-6 19:14 | 只看该作者

这个要仔细看资料了

参考资料:
[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中的值。

使用特权

评论回复
11
ferry| | 2007-5-6 21:39 | 只看该作者

arm和thumb的切换问题

楼主的问题我想大概是这样,ldr的操作数是4字节的,是code32,而现在处在code16,因此取这个值要做一次code16到code32的切换,应在ldr后加一条bx [r1]切换语句,以保证跳转的地址值是4字节。又这个地址值是指向code16地方的,所以又要做一次code32到code16的切换,这次切换是通过+1实现的,这就是0x40000024+1=0x40000025,汇编程序帮你处理好了。
 

使用特权

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

非常感谢!!牛人!!

非常感谢!!牛人!!得到正解!!!哈哈
看来是要多多看看这些文档了!!

使用特权

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

本版积分规则

17

主题

72

帖子

0

粉丝