汇编语言是由工具而不是目标定义的,因此指令的解决方案和确切语法会有所不同。您提到了 gcc,这意味着 gnu 汇编器,尽管 gcc 被输入汇编语言是另一种 gnu arm 汇编语言
使用 gnu 汇编器, ldr = 伪指令将尝试使用最佳指令,否则它将执行相对于 pc 的加载。如果你想要完全控制,那么只使用 ldr = 东西作为标签(显然是它的初衷)
.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 的负载,这有利有弊。
仅在某些支持较大立即数的处理器上才有 thumb2 扩展
12: f240 35e9 movw r5, #1001 ; 0x3e9
它甚至可以做这样奇怪的事情。
1a: f04f 1599 mov.w r5, #10027161 ; 0x990099
ldr = 和直接使用 movw 都会产生相同的指令(如预期的那样)。
12: f240 35e9 movw r5, #1001 ; 0x3e9
16: f240 35e9 movw r5, #1001 ; 0x3e9
评论中有一些混乱(每个人都需要阅读文档,而不仅仅是 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 使用 32 位指令,像 mips 和其他指令一样,在可能的立即数位数方面受到限制,同时为操作码留出了空间,因为没有更好的术语。拇指是 16 位,因此可立即使用的空间要少得多。thumb2 扩展添加了额外的指令,这些指令采用 2x16 位,但通常不能使用 arm 编码,但由于某种原因没有使用您在 arm 指令中看到的相同立即方案,所以您有这个反射和移位的东西,而不仅仅是移位事物。
所有这些都在您编写/学习汇编语言时应该随身携带的 arm 文档中。
汇编语言是由工具(汇编程序)而不是目标定义的,因此 gnu 汇编程序和 kiel 以及 ARMasm 和其他人预计会有不同的汇编语言(主要在非指令区域),他们确实如此。对于任何其他目标(x86、mips 等)也是如此,这是一般规则,通常没有标准化的汇编语言,当然对于主线指令集也没有。
说 ldr rx,=label/address 技巧与 gnu 汇编器一起导致了最佳指令,但它的伪代码不是真正的指令,因此预计某些汇编器根本不支持它,而一些支持它的汇编器可能从字面上实现一个 pc 相对负载而不是优化(在可能有一个命令行选项来启用/禁用优化的可能性范围内)。
您为拇指而构建,而拇指则仅限于未移位的 8 位立即数。如果您的 cpu 恰好也支持 thumb2,那么您可以告诉汇编器该命令行或代码中,它将生成优化指令和/或您可以直接指定指令。如果不支持 thumb2,那么您可以直接制作 pc 相对负载
mov r5,hello
...
hello: .word 1001
或者使用 ldr 等于的东西,或者使用多条指令 3 左移 8 orred 与 0xE9,那种东西。
编辑
只为杰克...
.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,这是 OPs 错误消息所暗示的。
对于 armv7、armv7m,您可以使用 ldr 指令生成它,而不必根据您选择的立即数不断更改您的代码,如果您使用 gnu 汇编程序,那么 ldr equals 是最好的方法。
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 的地方可以使用,不能使用的地方不可以,但让我们试试这个。
.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 不是一个好的解决方案。
编辑 2(对于 OP)
底线,简短的回答...您收到该消息的原因是您无法生成具有该立即值的 thumb mov 立即指令,因为您将在 arm 文档中看到您没有那么多位。如果当您说 rapi 4 时,您的意思是树莓派 4,它是一个 armv8,它支持支持 thumb2 扩展的 aarch32 (armv7-a)(armv6-m 后包含 movw)
.thumb
ldr r5,=1001
.align
使用 ldr equals 发现最优指令
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
如果你愿意,然后直接使用它
.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 中(还没有)没有拇指指令。