为什么我不能将#1001 移动到手臂上的 r5 中? [英] Why can't I move #1001 into r5 on arm?

查看:22
本文介绍了为什么我不能将#1001 移动到手臂上的 r5 中?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 RPi4,我正在尝试在汇编中编写一些代码以循环 1000 次.当我设置较少的循环数时,代码工作正常,但是当我尝试将其设置为 1001 时,gcc 说:

I have an RPi4 and I'm trying to write some code in assembly to loop 1000 times. The code works fine when I set a lower number of loops, but when I try to set it 1001, gcc says:

loop.s: Assembler messages:
loop.s:15: Error: invalid constant (3e9) after fixup

代码如下:

.data
ms3: .asciz "%d\n"
.text
.global main
.extern printf
main:
    push {ip, lr}
    mov r1, #0
    mov r5, #1001

loop1000:
    push {r1}
    ldr r0, =ms3
    bl printf
    pop {r1}
    add r1, #1
    cmp r1, r5
    bne loop1000
    pop {ip, pc}

推荐答案

汇编语言是由工具而非目标定义的,因此解决方案和指令的确切语法各不相同.你提到了 gcc 这意味着 gnu 汇编虽然 gcc 被提供汇编语言是另一种 gnu arm 汇编语言

Assembly languages are defined by the tool not the target, so solutions and exact syntax for instructions varies. You mentioned gcc which implies gnu assembler although gcc being fed assembly language is yet another gnu arm assembly language

使用 gnu 汇编器时,ldr = 伪指令将尝试使用最佳指令,否则它将执行与 pc 相关的加载.如果你想要完全控制,那么只对标签使用 ldr = thing(显然是它的初衷)

With gnu assembler the ldr = pseudo instruction will attempt to use the optimal instruction if it can otherwise it will do a pc-relative load. If you want full control then only use the ldr = thing for labels (clearly its original intent)

.cpu arm7tdmi
ldr r5,=1001
ldr r5,=0x00990000
ldr r5,=0x00990099
ldr r5,=0x90000009


.thumb
.cpu cortex-m0
ldr r5,=1001

.cpu cortex-m3
ldr r5,=1001
movw r5,#1001
ldr r5,=0x00990099
.align

Disassembly of section .text:

00000000 <.text>:
   0:   e59f5018    ldr r5, [pc, #24]   ; 20 <.text+0x20>
   4:   e3a05899    mov r5, #10027008   ; 0x990000
   8:   e59f5014    ldr r5, [pc, #20]   ; 24 <.text+0x24>
   c:   e3a05299    mov r5, #-1879048183    ; 0x90000009
  10:   4d03        ldr r5, [pc, #12]   ; (20 <.text+0x20>)
  12:   f240 35e9   movw    r5, #1001   ; 0x3e9
  16:   f240 35e9   movw    r5, #1001   ; 0x3e9
  1a:   f04f 1599   mov.w   r5, #10027161   ; 0x990099
  1e:   bf00        nop
  20:   000003e9    andeq   r0, r0, r9, ror #7
  24:   00990099    umullseq    r0, r9, r9, r0

从你的问题中间开始.

  10:   4d03        ldr r5, [pc, #12]   ; (20 <.text+0x20>)

1001 (0x3e9) 不适合 mov 立即数拇指指令的 8 位立即数,无旋转.所以使用 ldr = 汇编程序创建了一个相对于 pc 的负载,它有利有弊.

1001 (0x3e9) does not fit within the 8 bit immediate,no rotation, of the mov immediate thumb instruction. so using ldr = the assembler created a pc-relative load, which has pros and cons.

thumb2 扩展仅在某些支持更大立即数的处理器上可用

There is a thumb2 extension only available on some processors that does support larger immediates

  12:   f240 35e9   movw    r5, #1001   ; 0x3e9

它甚至可以做这样奇怪的事情.

It even can do weird things like this.

  1a:   f04f 1599   mov.w   r5, #10027161   ; 0x990099

ldr = 和直接使用 movw 都会产生相同的指令(如预期).

both the ldr = and directly using movw resulted in the same instruction (as expected).

  12:   f240 35e9   movw    r5, #1001   ; 0x3e9
  16:   f240 35e9   movw    r5, #1001   ; 0x3e9

评论中有一些混乱(每个人都需要阅读文档,而不仅仅是 OP)

There was some confusion in the comments (everyone needs to go read the documentation not just the OP)

   0:   e59f5018    ldr r5, [pc, #24]   ; 20 <.text+0x20>
   4:   e3a05899    mov r5, #10027008   ; 0x990000
   8:   e59f5014    ldr r5, [pc, #20]   ; 24 <.text+0x24>
   c:   e3a05299    mov r5, #-1879048183    ; 0x90000009

arm 模式不能做 0x00990099 的事情,但它可以做 8 个非零位在偶数边界 0x00990000 和 0x90000009 上循环,但不能做 0x000001FE、0x102 等.

arm mode cannot do the 0x00990099 thing, but it can do 8 non-zero bits rotated on an even boundary 0x00990000 and 0x90000009, but not 0x000001FE, 0x102, and so on.

arm 使用 32 位指令,像 mips 和其他指令一样,在可能有多少位立即数方面受到限制,同时由于缺乏更好的术语而为操作码留出空间.拇指是 16 位,因此可以立即使用的空间要少得多.thumb2 扩展添加了额外的指令,这些指令需要 2x16 位,但通常不能使用 arm 编码,但由于某种原因没有使用你在 arm 指令中看到的相同的立即方案,所以你有这个反射和移位的东西,而不仅仅是一个移位东西.

arm uses 32 bit instructions and like mips and others is limited in how many bits of immediate are possible while leaving room for the opcode for lack of a better term. thumb is 16 bit so much less room is available for an immediate. thumb2 extensions add additional instructions that take 2x16 bits but couldn't use arm encoding in general but for some reason didn't use the same immediate scheme that you see in arm instructions, so you have this reflect and shift thing rather than just a shift thing.

所有这些都在 arm 文档中,您在编写/学习汇编语言时应该随身携带.

All of this is in the arm documentation which you should have next to you when writing/learning assembly language.

汇编语言是由工具(汇编器)而不是目标定义的,因此 gnu 汇编器和 kiel 以及 ARMasm 和其他语言预计具有不同的汇编语言(主要在非指令领域),他们确实如此.对于任何其他目标(x86、mips 等)也是如此,这是一般规则,通常没有标准化的汇编语言,当然对于主线指令集也没有.

Assembly language is defined by the tool (the assembler) not the target, so gnu assembler and kiel and ARMasm and others are expected to have different assembly languages (mostly in the non-instruction area) and they do. Same for any other target (x86, mips, etc) this is a general rule there aren't standardized assembly languages usually, certainly not for the mainline instruction sets.

说 ldr rx,=label/address 技巧与 gnu 汇编器一起产生了最佳指令,但它伪代码不是真正的指令,因此预计某些汇编器根本不支持它,而有些则不支持支持它可能会真正实现 pc 相对负载而不是优化(在可能有一个命令行选项来启用/禁用优化的可能性范围内).

Saying that the ldr rx,=label/address trick has with gnu assembler resulted in the optimal instruction, but it pseudo code not a real instruction and as such it is not expected to be supported at all on some assemblers and some that support it may literally implement a pc relative load and not optimize (within the realm of possibilities that one might have a command line option to enable/disable the optimization).

您为拇指而构建,并且对于拇指,您仅限于未移位的 8 位立即数.如果您的 CPU 恰好也支持 thumb2,那么您可以在命令行或代码中告诉汇编器,它会生成优化的指令和/或您可以直接指定指令.如果不支持thumb2,那么你可以直接制作一个pc相对负载

You built for thumb and for thumb you are limited to an unshifted 8 bit immediate. If your cpu happens to support thumb2 as well then you can tell the assembler that command line or in the code and it will generate the optimized instruction and/or you can specify the instruction directly. If thumb2 is not supported then you can either directly craft a pc relative load

mov r5,hello
...
hello: .word 1001

或使用 ldr 等于的东西,或使用多条指令 3 左移 8 或 0xE9 之类的东西.

or use the ldr equals thing, or use multiple instructions 3 shifted left 8 orred with 0xE9, that kind of thing.

只为杰克...

.thumb

.cpu cortex-m0
ldr r5,=1001

.cpu cortex-m3
ldr r5,=1001

.align

arm-none-eabi-as --version
GNU assembler (GNU Binutils) 2.34
Copyright (C) 2020 Free Software Foundation, Inc.
This program is free software; you may redistribute it under the terms of
the GNU General Public License version 3 or later.
This program has absolutely no warranty.
This assembler was configured for a target of `arm-none-eabi'.

00000000 <.text>:
   0:   4d01        ldr r5, [pc, #4]    ; (8 <.text+0x8>)
   2:   f240 35e9   movw    r5, #1001   ; 0x3e9
   6:   bf00        nop
   8:   000003e9    andeq   r0, r0, r9, ror #7

对于 armv6m(和 armv4t、armv5t、armv6、当前 armv8ms),您不能使用 movw,这是 OP 错误消息所暗示的.

for armv6m (and armv4t, armv5t, armv6, current armv8ms) you cannot use movw, which is what was implied by the OPs error message.

对于 armv7 和 armv7m,您可以使用 ldr 指令生成它,而不必根据您选择的立即数不断更改代码,如果您使用 gnu 汇编程序,则 ldr equals 是最好的方法.

For armv7, armv7m you can and the ldr instruction generates that, instead of having to keep changing your code based on what immediates you choose, if you use gnu assembler then ldr equals is the best way to go.

arm-none-eabi-gcc --version
arm-none-eabi-gcc (GCC) 9.3.0
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00000000 <.text>:
   0:   4d01        ldr r5, [pc, #4]    ; (8 <.text+0x8>)
   2:   f240 35e9   movw    r5, #1001   ; 0x3e9
   6:   bf00        nop
   8:   000003e9    andeq   r0, r0, r9, ror #7

现在,虽然通过 gcc 提供汇编语言是另一种汇编语言,但当使用 ldr equals 时,它仍然按预期生成理想的指令.movw 在哪些地方可以使用,哪些地方不能使用,但让我们试试这个.

Now while feeding assembly language through gcc is yet another assembly language it still as expected generates the ideal instruction when ldr equals is used. Where you can use movw it does, where you cannot it does not, but let's try this.

.thumb

.cpu cortex-m0
ldr r5,=1001

.cpu cortex-m3
movw r5,#1001

.align

没有抱怨.相同的结果.

No complaints. Same results.

尝试您的建议:

.thumb

.cpu cortex-m0
movw r5,#1001

.cpu cortex-m3
movw r5,#1001

.align

arm-none-eabi-gcc so.s -c -o so.o
so.s: Assembler messages:
so.s:6: Error: selected processor does not support `movw r5,#1001' in Thumb mode

现在您必须重新编写代码.movw 不是一个好的解决方案.

and now you have to go re-write your code. movw is not a good solution.

底线,简短的回答...您收到该消息的原因是您无法生成具有该立即值的拇指 mov 立即指令,因为您将在 arm 文档中看到您没有那么多位.如果你说 rapi 4 是指 raspberry pi 4,它是一个 armv8,它支持 aarch32 (armv7-a),它支持拇指 2 扩展(armv6-m 后包含 movw)

bottom line, short answer... The reason why you got that message is that you cannot generate a thumb mov immediate instruction with that immediate value because you will see in the arm documentation you don't have that many bits. If when you said rapi 4 you meant raspberry pi 4 that is an armv8 which supports aarch32 (armv7-a) which supports thumb2 extensions (which post armv6-m includes movw)

.thumb
ldr r5,=1001
.align

使用ldr等于发现最优指令

Use ldr equals to discover the optimal instruction

arm-none-eabi-as -march=armv7a so.s -o so.o
arm-none-eabi-objdump -D so.o

so.o:     file format elf32-littlearm


Disassembly of section .text:

00000000 <.text>:
   0:   f240 35e9   movw    r5, #1001   ; 0x3e9

如果你愿意,可以直接使用它

and then use that directly if you wish

.thumb
ldr r5,=1001
movw r5,#1001
.align

Disassembly of section .text:

00000000 <.text>:
   0:   f240 35e9   movw    r5, #1001   ; 0x3e9
   4:   f240 35e9   movw    r5, #1001   ; 0x3e9

如果这确实是 raspberry pi 4,那么您需要 armv7-ar 架构参考手册来涵盖 aarch32 的内容和 armv8(不是 8m)架构参考手册来涵盖 aarch64 的内容.还有一个不同的 gnu 工具链,因为它是一个完全不同的指令集(aarch64-whatever-whatever vs arm-whatever-whatever).而且 aarch64 中没有拇指指令(目前).

If this is indeed a raspberry pi 4 then you need the armv7-ar architectural reference manual to cover the aarch32 stuff and the armv8 (not 8m) architectural reference manual to cover the aarch64 stuff. And a different gnu toolchain as it is a completely different instruction set (aarch64-whatever-whatever vs arm-whatever-whatever). And there are no thumb instructions in aarch64 (yet).

这篇关于为什么我不能将#1001 移动到手臂上的 r5 中?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆