首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >无法用LDR替换MOVW / MOVT

无法用LDR替换MOVW / MOVT
EN

Stack Overflow用户
提问于 2021-11-16 16:05:13
回答 2查看 102关注 0票数 1

我想用一条ldr指令替换这个movw / movt组合:

代码语言:javascript
运行
复制
movw r0, #0x3800
movt r0, #0x4002

      |
      V

ldr r0, =0x40023800

但是,在此更改之后,代码将不再工作。因为这是我更改的唯一部分,所以一定是它有问题。我的印象是这两个代码段是相同的。

代码语言:javascript
运行
复制
.syntax unified
.cpu cortex-m4
.thumb

代码语言:javascript
运行
复制
arm-none-eabi-as -mcpu=cortex-m4 code.s -c -o code.o
arm-none-eabi-gcc -T link.ld -nostartfiles -o result code.o

以防万一,代码的其余部分与托管在this page (底部)的代码完全相同。

为什么这个更改会破坏我的代码?是否有替代的单行方法可以将32位立即值写入寄存器?

在汇编程序上运行objdump的结果显示如下(请注意<main>的开头和<loop>的结尾

代码语言:javascript
运行
复制
Disassembly of section .text:

00000000 <main>:
   0:   4810        ldr r0, [pc, #64]   ; (44 <.loop+0x2a>)
   2:   f240 0101   movw    r1, #1
                 [removed]
  18:   6001        str r1, [r0, #0]

0000001a <.loop>:
  1a:   f240 0100   movw    r1, #0
                 [removed]
  44:   40023800    andmi   r3, r2, r0, lsl #16
EN

回答 2

Stack Overflow用户

发布于 2021-11-18 18:59:00

首先,汇编语言是特定于汇编器的(armasm、gas等),而不是目标程序(Cortex M4),它们可以而且肯定经常是跨工具的不兼容语言。Ldr通常用作伪指令,这意味着汇编程序决定为您使用哪条指令,而不是您请求的指令。

代码语言:javascript
运行
复制
.cpu cortex-m4
.thumb

ldr r0,=0x12345678
ldr r1,=0x00000003
ldr r2,=0xFFFFFFF5
nop
nop
b .

组装和拆卸

代码语言:javascript
运行
复制
00000000 <.text>:
   0:   4803        ldr r0, [pc, #12]   ; (10 <.text+0x10>)
   2:   f04f 0103   mov.w   r1, #3
   6:   f06f 020a   mvn.w   r2, #10
   a:   46c0        nop         ; (mov r8, r8)
   c:   46c0        nop         ; (mov r8, r8)
   e:   e7fe        b.n e <.text+0xe>
  10:   12345678    eorsne  r5, r4, #120, 12    ; 0x7800000

首先使用gnu汇编程序ldr r0,=语法是受支持的,不要期望所有的arm/thumb汇编程序都支持该语法。其次,使用gnu汇编程序(也许还有另一个答案中指出的其他程序),如果该工具可以创建一个实际上不执行ldr的优化,它将会。

我们可以看到,对于第二个和第三个常量,汇编程序使用了非加载指令,并将常量嵌入为立即数。

对于0x12345678值,您不能简单地将32位立即数放入32位(或16位)指令中,您必须进行加载,并且它通过找到一个池来放置常量并对其进行pc相对加载来实现。

汇编语言绝对不适合编译器,只有一些编译器使用汇编语言。如果没有汇编语言,我们就不会有当前的处理器,也不会有新的处理器供人类用于处理器的开发和测试。因此,非人类的asm意味着没有处理器。我们将无法引导高级编程语言,因此将不会有编程语言。不会有编译器,因为您需要精通汇编语言指令集的人员(即使编译器不能编译为asm)才能成功创建编译器,因此不会有编译器,但由于其他原因,目前还没有编译器。如果人类指令集级别的编程消失了,处理器和所有的副作用也就消失了。每一代人都要带着火炬去寻找和教导其他人。

我很幸运(好吧,这是计划好的),工作不是在这里完成的,这样如何:

代码语言:javascript
运行
复制
.cpu cortex-m4
.thumb

ldr r0,=0x12345678
ldr r1,=0x00000003
ldr r2,=0xFFFFFFF5
nop
b .

Disassembly of section .text:

00000000 <.text>:
   0:   4803        ldr r0, [pc, #12]   ; (10 <.text+0x10>)
   2:   f04f 0103   mov.w   r1, #3
   6:   f06f 020a   mvn.w   r2, #10
   a:   46c0        nop         ; (mov r8, r8)
   c:   e7fe        b.n c <.text+0xc>
   e:   56780000    ldrbtpl r0, [r8], -r0
  12:   Address 0x0000000000000012 is out of bounds.

常量被放置在非单词对齐的边界上。它可能已经成功组装,但ldr是一个未对齐的传输,这可能会导致异常,代码将无法工作。

快速解决方案:

代码语言:javascript
运行
复制
.cpu cortex-m4
.thumb

ldr r0,=0x12345678
ldr r1,=0x00000003
ldr r2,=0xFFFFFFF5
nop
b .
.align


Disassembly of section .text:

00000000 <.text>:
   0:   4803        ldr r0, [pc, #12]   ; (10 <.text+0x10>)
   2:   f04f 0103   mov.w   r1, #3
   6:   f06f 020a   mvn.w   r2, #10
   a:   46c0        nop         ; (mov r8, r8)
   c:   e7fe        b.n c <.text+0xc>
   e:   bf00        nop
  10:   12345678    eorsne  r5, r4, #120, 12    ; 0x7800000

这招很管用。我们仍在假设池将去往何处,我们可以尝试强制它。

代码语言:javascript
运行
复制
.cpu cortex-m4
.thumb

one:
ldr r0,=0x12345678
ldr r1,=0x00000003
ldr r2,=0xFFFFFFF5
b .
.align

two:
ldr r0,=0x11223344
b .
.align

Disassembly of section .text:

00000000 <one>:
   0:   4803        ldr r0, [pc, #12]   ; (10 <two+0x4>)
   2:   f04f 0103   mov.w   r1, #3
   6:   f06f 020a   mvn.w   r2, #10
   a:   e7fe        b.n a <one+0xa>

0000000c <two>:
   c:   4801        ldr r0, [pc, #4]    ; (14 <two+0x8>)
   e:   e7fe        b.n e <two+0x2>
  10:   12345678    eorsne  r5, r4, #120, 12    ; 0x7800000
  14:   11223344            ; <UNDEFINED> instruction: 0x11223344


.cpu cortex-m4
.thumb

one:
ldr r0,=0x12345678
ldr r1,=0x00000003
ldr r2,=0xFFFFFFF5
b .
.align
.ltorg

two:
ldr r0,=0x11223344
b .
.align

00000000 <one>:
   0:   4802        ldr r0, [pc, #8]    ; (c <one+0xc>)
   2:   f04f 0103   mov.w   r1, #3
   6:   f06f 020a   mvn.w   r2, #10
   a:   e7fe        b.n a <one+0xa>
   c:   12345678    eorsne  r5, r4, #120, 12    ; 0x7800000

00000010 <two>:
  10:   4800        ldr r0, [pc, #0]    ; (14 <two+0x4>)
  12:   e7fe        b.n 12 <two+0x2>
  14:   11223344            ; <UNDEFINED> instruction: 0x11223344

pc的相对负载是正的,所以我们没有完全控制:

代码语言:javascript
运行
复制
.cpu cortex-m4
.thumb

one:
ldr r0,=0x12345678
ldr r1,=0x00000003
ldr r2,=0xFFFFFFF5
nop
b .

two:
ldr r0,=0x11223344
b .
.align
.ltorg


00000000 <one>:
   0:   4804        ldr r0, [pc, #16]   ; (14 <two+0x6>)
   2:   f04f 0103   mov.w   r1, #3
   6:   f06f 020a   mvn.w   r2, #10
   a:   46c0        nop         ; (mov r8, r8)
   c:   e7fe        b.n c <one+0xc>

0000000e <two>:
   e:   4802        ldr r0, [pc, #8]    ; (18 <two+0xa>)
  10:   e7fe        b.n 10 <two+0x2>
  12:   bf00        nop
  14:   12345678    eorsne  r5, r4, #120, 12    ; 0x7800000
  18:   11223344            ; <UNDEFINED> instruction: 0x11223344

我们不需要在两个之前对齐,两个可以在非32位边界上着陆,所以我们有时会在那里保存半字。.align (汇编语言是特定于汇编器的,而不是目标,这是gnu汇编器支持的语言,并为这个目标做了特定的事情)允许它在4字节边界上对齐,这样ldr就不会出错,而.ltorg实际上并没有改变这里的事情,只是表明这是我们想要的地方。您还必须了解与pc相关的负载可以工作多远,每个指令集(arm、mips、x86等)的范围各不相同,因此您不能在大型项目结束时只使用一个池。

为什么这对你来说不一定有效呢?我们需要看到和理解--你只是简单地改变了汇编语言并重新汇编,还是你在二进制文件中修改了一些指令?后者有很多问题,包括指令大小以及如何将项目填充到池中。如果它只是代码,并且你组装了它,那么它很可能是未对齐的,你可能会得到一个未对齐的访问错误。

但是ldr rd,=可以覆盖所有可能的位模式,并且movw/movt也可以。但是ldr rd,= on gnu汇编程序会在可能的情况下进行优化,否则它需要池,并且池需要为它做好准备。如果你手工创建movw/movt,你所需要的就是这两条指令,没有池。

您需要创建一个更完整的示例,并定义“不再有效”的含义。

票数 0
EN

Stack Overflow用户

发布于 2021-11-16 17:26:43

ldr是一条伪指令,可转换为从池中加载。

LDR Rd,=const伪指令生成加载任意32位数的最有效的单指令。您可以使用此伪指令生成超出MOV与MVN指令范围的常量。LDR伪指令为指定的立即值生成最有效的单指令:

如果可以使用单个MOV或MVN指令构造立即值,则汇编程序会生成相应的指令。如果不能使用单个MOV或MVN指令构造立即值,则汇编程序:将该值放入文字池(嵌入在代码中以保存常量值的内存的一部分)中。生成具有PC相对地址的LDR指令,该指令从文字池中读取常量。例如:

LDR rn,pc,#偏移量到文字池;用一个字加载寄存器n;从地址pc + offset

您必须确保在汇编程序生成的LDR指令的范围内有一个文字池。

https://www.keil.com/support/man/docs/armasm/armasm_dom1359731147386.htm

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69992454

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档