在ARM汇编中将32位值加载到寄存器

7

我想使用ARM汇编直接将1个32位十六进制数加载到寄存器中。

mov r1,#0x6c617669

由于这个指令只能加载8位值,因此无法使用。所以我直接从内存中加载32位值。那么我该如何在ARM汇编中将32位值存储到内存中并直接加载到寄存器中呢?

我尝试了以下代码。

    .global main
main:
    sub sp,sp,#4
    str lr,[sp,#0]

    sub sp,sp,#4
    str r0,x
    add sp,sp,#4

    ldr lr,[sp,#0]
    add sp,sp,#4
    mov pc,lr

    .data
x: .word 0x6c617669

但是会出现以下错误。
test1.s: Assembler messages: 
test1.s:45: Error: internal_relocation (type: OFFSET_IMM) not fixed up
3个回答

12

你有两个基本选择。你可以加载它,或者每次构建8个非零位的寄存器。

mov r0,#0x12000000             @ construct from 8-bit rotated immediates
orr r0,r0,#0x00340000
orr r0,r0,#0x00005600
orr r0,r0,#0x00000078
...

ldr r1,=0x12345678             @ let the assembler figure out how
...

ldr r3,myconst                 @ explicitly load from a nearby constant
...
myconst: .word 0x12345678

后两者是相同的,等于技巧只是要求汇编器将该值置于可达范围内并进行相对于程序计数器的加载。


拇指模式下,您应该只使用一个装载。 - old_timer
你的第一个解决方案是错误的,MOV(立即数)最多只能接受8位立即值,你不能将0x12000000加载到r0中。 - Dr. Ehsan Ali
1
@Ehsan 你是否想到拇指而非arm?即使拇指在编码中也有一个旋转方案。mov r0,#0x12000000是完全有效的arm指令,mov,orr等都可以正常工作。1001是四位,可以由移位器在进入寄存器之前旋转任意2的幂次方,因此它是完全有效的,就像0x81和0xFF等一样,但是0x102不是10000001,尽管有8个有效位旋转只有1位,所以那行不通,但0x204是有效的,即8位旋转2的幂次方。然而,0x408等则是无效的... - old_timer
0x12,00010010,因此可以将00010010向右旋转8位或01001000向右旋转10位。00110100,因此可以将00001101向右旋转14位或00110100向右旋转16位或11010000向右旋转18位。 - old_timer
thumb 只能使用 8 位值,不能进行移位操作,而 thumb2 则比较奇特... - old_timer
显示剩余8条评论

3

根据您的处理器型号,您可能可以使用另一组指令(例如movw和movt)。例如,在使用GCC编译时,以下指令将无法在Raspberry Pi 2上运行;但是,它们将在Marvell Armada 370 / XP上工作。如果我没记错的话,这是一款Cortex-A9处理器。

movw r1, #0x6c61
movt r1, #0x7669

...

r1 0x6c617669 1818326633

这也在以下网址提到:https://community.arm.com/processors/b/blog/posts/how-to-load-constants-in-assembly-for-arm-architecture - Ciro Santilli OurBigBook.com

0

你可以用另一种方式,间接地而不是直接地来完成:

.data

.balign 4
value: .word 0x6c617669

.text

.global main
main:
    push {lr}                        /* save lr value on stack */

    ldr r0, address_of_value         /* r0 = &value */
    ldr r0, [r0]                     /* r0 = *r0 = value */

    pop {lr}                         /* load lr (R14) register from stack */
    bx lr                            /* return from main using lr */

address_of_value: .word value

R0寄存器包含32位值,您可以通过调试此代码看到:

(gdb) start
Temporary breakpoint 1 at 0x103ec
Starting program: /home/pi/asm/kk

Temporary breakpoint 1, 0x000103ec in main ()
(gdb) disassemble
Dump of assembler code for function main:
   0x000103e8 <+0>:     push    {lr}            ; (str lr, [sp, #-4]!)
=> 0x000103ec <+4>:     ldr     r0, [pc, #8]    ; 0x103fc <address_of_value>
   0x000103f0 <+8>:     ldr     r0, [r0]
   0x000103f4 <+12>:    pop     {lr}            ; (ldr lr, [sp], #4)
   0x000103f8 <+16>:    bx      lr
End of assembler dump.
(gdb) info registers r0
r0             0x1      1
(gdb) stepi
0x000103f0 in main ()
(gdb) stepi
0x000103f4 in main ()
(gdb) disassemble
Dump of assembler code for function main:
   0x000103e8 <+0>:     push    {lr}            ; (str lr, [sp, #-4]!)
   0x000103ec <+4>:     ldr     r0, [pc, #8]    ; 0x103fc <address_of_value>
   0x000103f0 <+8>:     ldr     r0, [r0]
=> 0x000103f4 <+12>:    pop     {lr}            ; (ldr lr, [sp], #4)
   0x000103f8 <+16>:    bx      lr
End of assembler dump.
(gdb) info registers r0
r0             0x6c617669       1818326633

敬礼。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接