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

查看:71
本文介绍了为什么我不能将#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 =用作标签(显然是其原始意图)

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.

说gdr汇编器具有ldr rx,= label/address技巧导致了最佳指令,但是伪代码不是真正的指令,因此,某些汇编器和某些汇编器根本不支持该伪代码.支持它可能从字面上实现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,在不能使用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

没有投诉.结果相同.

尝试您的建议:

.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.

底行,简短的答案...之所以收到该消息,是因为您无法生成具有该立即值的thumb mov立即指令,因为您会在arm文档中看到没有那么多位.如果说rapi 4的意思是树莓pi 4,它是一个支持aarch32(armv7-a)的armv8,它支持thumb2扩展(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

如果这确实是树莓派4,则需要armv7-ar体系结构参考手册来介绍aarch32内容,而armv8(而非8m)体系结构参考手册来介绍aarch64内容.还有一个不同的gnu工具链,因为它是完全不同的指令集(aarch64-随便什么与arm随便什么).而且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天全站免登陆