ARMv6程序集中= label(等号)和[label](括号)之间有什么区别?

时间:2013-06-20 13:30:12

标签: assembly arm

我正在跟随剑桥大学的Baking Pi课程,其中一个简单的操作系统是在ARMv6指令集中构建的,目标是Raspberry Pi。

到目前为止,我们一直使用两种方法通过ldr指令将数据加载到寄存器中,现在我意识到我正在使用它们,我不完全理解它们都做了什么。

所以我使用了像ldr r0,=0x20200000这样的东西,我实际上把它理解为“将存储在存储单元0x20200000的数据读入寄存器r0。

然后我使用了以下内容:

ldr r0,[r1,#4]

我已经理解为“读取存储在r1指向的存储器地址的数据,以4字节的偏移量进入寄存器r0”。

然后我遇到了这个:

ldr r0,=pattern
ldr r0,[r0]

pattern这里是.int部分中的.data(表示LED的开/关状态序列的位图)。我在阅读本文时意识到,我之前对=foo的理解必定是错误的,否则上述两条指令都会做同样的事情。

=x语法基本上更像是C中的指针,而[x]语法就好像实际读取x指向的内存一样?

让我们说下面的C中的ptrint*,我的评论是否考虑等效汇编(概念上,不是字面上的)是否有意义?

r0 = ptr;     /* equivalent to: ldr r0,=ptr     */
r0 = *ptr;    /* equivalent to: ldr r0,[ptr]    */
r0 = *(ptr+4) /* equivalent to: ldr r0,[ptr,#4] */

2 个答案:

答案 0 :(得分:18)

ldr r0,=something
...
something:

表示将标签的地址加载到寄存器r0中。然后汇编程序在ldr指令的某个地方添加一个单词,并用

替换它
ldr r0,[pc,#offset]

指令

所以这个快捷方式

ldr r0,=0x12345678

表示将0x12345678加载到r0。

大多数是固定长度的指令,你不能在一条指令中将一个完整的32位立即加载到一个寄存器中,它可能需要许多指令来完全加载一个32位数的寄存器。很大程度上取决于这个数字。例如

ldr r0,=0x00010000

将被gnu汇编程序替换为单个指令mov r0,如果是ARM指令则为#0x00010000,对于Thumb指令,可能仍然必须是ldr r0,[pc,#offset]

这些ldr rd,=事物是快捷方式,伪指令,不是真实的。

ldr rd,[rm,#offset]
ldr rd,[rm,rn]

是实数指令,意思是从地址rm + offset或rm + rn读取存储器并取值读取并将其放入寄存器rd

=某些东西更像是C中的东西。

unsigned int something;
unsigned int r0;
unsigned int r1;

r0 = &something;
r1 = *(unsigned int *)r0;

和汇编

something:
    .word 0

ldr r0,=something
ldr r1,[r0]

答案 1 :(得分:0)

值得一提的是,对于出于某些原因想要避免伪指令/文字池的那些人,存在以下替代方法:

  • adr r0, label(v7 / v8):单指令,将标签的完整地址存储到r0中。通过相对PC寻址来引用标签,另请参见:What are the semantics of ADRP and ADRL instructions in ARM assembly? | Example with asserts

    但是在ARMv7中,无法使用adr访问不同部分中的标签,例如.data中的.text,显然是因为没有relocation会照顾它。 ldr =可以做到这一点。如果您尝试这样做,则GAS会失败,并显示以下信息:

     Error: symbol .data is in a different section
    

    但是在ARMv8中可以进行跨节访问,并且会生成类型R_AARCH64_ADR_PRE的重定位。 Example

  • movwmovt(v7)+ GNU气体#:lower

    movw r0, #:lower16:myvar
    movt r0, #:upper16:myvar
    

    Example with asserts

    movk +班次(v8)+ GNU GAS

    movz x0, #:abs_g2:label     // bits 32-47, overflow check
    movk x0, #:abs_g1_nc:label  // bits 16-31, no overflow check
    movk x0, #:abs_g0_nc:label  // bits  0-15, no overflow check
    

    Example with asserts