Why*_*ing 9 assembly gcc arm gnu-assembler
我一直在阅读 gcc 生成的一些不同的arm汇编代码,并且遇到了一些我在规范中找不到的东西。
movw r0, #39784
movt r0, 1
Run Code Online (Sandbox Code Playgroud)
显然,第一个是将值 39784 移动到底部 16 位或 r0,但 movt 的操作数“1”很奇怪,因为它前面没有哈希,而且我的印象是立即值需要哈希。在某些情况下它是可选的吗?或者我错过了一些神奇的东西?
ARMv7 的GNUgas行为取决于.syntax
两种略有不同的语法是对 ARM 和 THUMB 指令的支持。默认情况下,分开,使用旧样式,其中 ARM 和 THUMB 指令具有自己的独立语法。新的统一语法可以通过 .syntax 指令进行选择,具有以下主要特点:
- 立即操作数不需要 # 前缀。
和https://sourceware.org/binutils/docs-2.26/as/ARM_002dChars.html#ARM_002dChars说:
'#' 或 '$' 均可用于指示立即操作数。
对于 ARMv8#始终是可选的
https://sourceware.org/binutils/docs-2.26/as/AArch64_002dChars.html#AArch64_002dChars文档:
可以选择使用“#”来指示立即操作数。
测试
Ubuntu 16.04、Binutils 2.26.1。
v7.S:
/* These fail */
mov r0, 1
mov r0, 0x1
/* These work */
mov r0, #1
mov r0, #0x1
mov r0, $1
mov r0, $0x1
.syntax unified
mov r0, 1
mov r0, #1
mov r0, 0x1
mov r0, #0x1
mov r0, $1
mov r0, $0x1
Run Code Online (Sandbox Code Playgroud)
v8.S:
mov x0, 1
mov x0, #1
mov x0, 0x1
mov x0, #0x1
Run Code Online (Sandbox Code Playgroud)
集合:
arm-linux-gnueabi-as v7.S
aarch64-linux-gnu-as v8.S
Run Code Online (Sandbox Code Playgroud)
结果:v8 成功,v7 失败,divided没有#:
v7.S:1: Error: immediate expression requires a # prefix -- `mov r0,1'
v7.S:2: Error: immediate expression requires a # prefix -- `mov r0,0x1'
Run Code Online (Sandbox Code Playgroud)
去做
嗯,但是有一些 v7 指令实际上是可选的,例如和#没有错误:movwmovt
movw r0, 1
movt r0, 0x1
Run Code Online (Sandbox Code Playgroud)
但有错误:
movw r0, $1
movt r0, $0x1
Run Code Online (Sandbox Code Playgroud)
ARM 参考手册
ARMv8 -fb 手册本身有汇编/反汇编建议/要求,位于 C1.2“A64 汇编语言的结构”:
A64 汇编语言不需要 # 字符来引入常量立即操作数,但汇编器必须允许使用或不使用 # 字符引入立即值。Arm 建议 A64 反汇编程序在立即操作数之前输出 #。
个人推荐
在 v7 代码中使用.syntax unified,切勿#在 v7 或 v8 上的任何文字上使用。
统一语法更新更好,而那些#和$符号只是更多的代码噪音。
Linux内核同意我的观点:https://github.com/torvalds/linux/blob/v4.19/arch/arm/include/asm/unified.h#L23