assembly 在这种情况下,为什么它加载值而不是地址?

xienkqul  于 2022-11-13  发布在  其他
关注(0)|答案(1)|浏览(182)

我从一篇课文中举了这样一个例子:

MOV R1, #7
LDR R2, = ioadr
STR R1, [R2]
ioadr .word 0x20001000

它说它会将值7存储到内存地址0x20001000。但是我想知道行LDR R2, = ioadr。为什么我们不把ioadr的地址加载到R2?而是把值if ioadr加载到R2?汇编程序知道ioadr是常量而不是变量吗?难道不存在加载地址的情况吗?
PS:这个例子是用DCD,但据我所知,这相当于. word。
原始代码:

MOV R1, #7
LDR R2, = ioadr
STR R1, [R2]
ioadr DCD 0x20001000

来源:第九章https://booksite.elsevier.com/9780128000564/

eagi6jfj

eagi6jfj1#

使用gnu汇编器进行arm。

MOV R1, #7
LDR R2, = ioadr
STR R1, [R2]
ioadr .word 0x20001000

这将失败,因为ioadr后面没有冒号

so.s: Assembler messages:
so.s:5: Error: bad instruction `ioadr .word 0x20001000'

所以

MOV R1, #7
LDR R2, = ioadr
STR R1, [R2]
ioadr: .word 0x20001000

这其中

LDR R2, = ioadr

是伪代码,1)不是所有的arm工具都支持,2)不是以同样的方式支持。它说你想把ioadr的地址加载到r2中。作为伪代码,你应该看到工具对它做了什么
未链接:

Disassembly of section .text:

00000000 <ioadr-0xc>:
   0:   e3a01007    mov r1, #7
   4:   e59f2004    ldr r2, [pc, #4]    ; 10 <ioadr+0x4>
   8:   e5821000    str r1, [r2]

0000000c <ioadr>:
   c:   20001000    .word   0x20001000
  10:   0000000c    .word   0x0000000c

链接的

Disassembly of section .text:

00008000 <ioadr-0xc>:
    8000:   e3a01007    mov r1, #7
    8004:   e59f2004    ldr r2, [pc, #4]    ; 8010 <ioadr+0x4>
    8008:   e5821000    str r1, [r2]

0000800c <ioadr>:
    800c:   20001000    andcs   r1, r0, r0
    8010:   0000800c    andeq   r8, r0, ip

现在,您可以对照架构参考手册使用此函数,并轻松地看到它将ioadr的ADDRESS加载到r2中,而不是0x20001000
因此,当发生存储时,它会存储,并覆盖0x20001000,而不是写入0x20001000
将其更改为不同的伪代码,删除等号

MOV R1, #7
LDR R2, ioadr
STR R1, [R2]
ioadr: .word 0x20001000

现在它做了书中似乎在描述的事情。

Disassembly of section .text:

00008000 <ioadr-0xc>:
    8000:   e3a01007    mov r1, #7
    8004:   e59f2000    ldr r2, [pc]    ; 800c <ioadr>
    8008:   e5821000    str r1, [r2]

0000800c <ioadr>:
    800c:   20001000    andcs   r1, r0, r0

加载操作将值0x20001000加载到r2中,以便存储操作实际上写入到0x20001000。
DCD和.word并不是您需要考虑的唯一汇编语言问题。正如您现在所看到的。如果您有任何问题,然后组装和拆卸,并先自己查找说明,然后如果仍然感到困惑,请将其与源代码沿着发布。
我怀疑这本书是错误的,这是另一个人生教训。文档是有缺陷的,假设它是,包括手臂文档。如果你有机会获得与书中汇编语言相匹配的手臂工具(如果这本书是半生不熟的,它会指定确切的工具和版本,我没有看),然后组装和拆卸。
正如您在本网站上看到的许多与ARM的等号伪代码相关的答案,例如

ldr r0,=0x12345678
ldr r1,=0x00000007

你会发现gnu会选择最佳的指令。(s)。但是其他工具,如果他们支持它的话,可能会照字面理解它,并使用一个字面池生成一个ldr。上面的第一个可能是来自一个字面池的pc相对负载,如上面基于您的代码的例子所示。后面的,使用gnu,将生成一个mov r1,#7而不是pc的相对负载。所以当使用这些东西的时候,小心使用。最重要的是要理解汇编语言是特定于工具的,而不是目标。有时候是工具的版本。同样,将c程序转换为java或python也需要工作,将汇编语言转换为arms工具也需要工作。(请注意,arm已经有了一系列的工具,重写或购买的小公司),以gnu binutils和回来。这是字面上的转换,从一个编程语言到另一个,只是没有那么苛刻的C到python。

相关问题