gpt4 book ai didi

assembly - GNU ARM 汇编程序将 mov 更改为 add?

转载 作者:行者123 更新时间:2023-12-04 02:33:42 25 4
gpt4 key购买 nike

社区!
我有以下单行源文件,名为 first.S

mov R1, R2
我生成一个目标文件如下:
$ arm-none-eabi-as -mcpu=cortex-m3 -march=armv7 -mthumb -c -o first.o first.S 
那我拆开看看
$ arm-none-eabi-objdump -d first.o

first.o: file format elf32-littlearm


Disassembly of section .text:

00000000 <.text>:
0: 1c11 adds r1, r2, #0
显然,在这种情况下,两条指令( movadd )具有相同的所需效果。
不过,问题是:为什么?
根据 ARMv7-M 体系结构引用手册,mov 寄存器指令存在多种编码,但是汇编程序选择将其编码为 add。操作说明。
在任何文件中是否有描述此类决定的地方?
谢谢!

最佳答案

从开始时间为拇指指令集,编码

0001110xxxnnnddd 
是一个
adds rd,rn,#xxx
这是更有效的编码 IF 标志的修改对您来说是可以的。
伪指令 mov rd,rn 意味着标志可以改变(显然是文档中的每个武器汇编和气体)。所以原始编码没问题。
现在由反汇编程序选择 if immed == 0 然后打印 mov rd,rn vs added rd,rn,#0,两者都是正确的反汇编。
现在,一个寄存器高一个低的 mov 说:
Unlike the low register MOV instruction described in MOV (2) on page A7-73, this instruction does not change the flags.
现在它进入了完全由汇编程序而不是目标(非 ARM)定义的汇编语言,以及可怕的统一语法等等。所以现在它变成了一个工具特定的东西。例如,用于拇指的 Gnu 汇编器不喜欢添加(非统一语法,我发现它更容易用于拇指)您执行添加并获得添加。
.thumb
add r0,r1,#0
mov r0,r1
adds r0,r1,#0
movs r0,r1

arm-none-eabi-as so.s -o so.o
so.s: Assembler messages:
so.s:5: Error: instruction not supported in Thumb16 mode -- `adds r0,r1,#0'

.thumb
add r0,r1,#0
mov r0,r1
movs r0,r1

00000000 <.text>:
0: 1c08 adds r0, r1, #0
2: 1c08 adds r0, r1, #0
4: 1c08 adds r0, r1, #0
然而,它对 movs 很好。
0x1c08 = 0x0001110000001000,这是一个添加拇指指令,当这一切开始时返回到 armv4t。
.syntax unified
.thumb
add r0,r1,#0
mov r0,r1
adds r0,r1,#0
movs r0,r1


0: f101 0000 add.w r0, r1, #0
4: 4608 mov r0, r1
6: 1c08 adds r0, r1, #0
8: 0008 movs r0, r1
所以现在在这种情况下,它是一种不同的汇编语言(相同的工具不同的汇编语言)
所以这个汇编语言尊重 add vs add 和 mov vs movs。
为了在没有闪光的情况下进行添加,您需要thumb2 编码。没有标志的 mov 是高位寄存器 mov 0x4608 0100011000001000 0x46xx
add 和往常一样,movs 现在被编码为左移,但不是反汇编 lsl r0,r1,#0,而是反汇编为 mov r0,r1,更多的是让您咀嚼,而不仅仅是将 mov 反汇编为添加。他们为什么不使用添加?这是另一个问题,如果您至少在旧的 arm arm 中查看 mov low registers 指令,它会描述显示添加编码的标志会发生什么。但是,如果您查看 lsl 描述,标志是不同的,那么 lsl 并不能替代具有标志的 mov,至少如生命周期最长的 ARM ARM(用拇指)中所述。
好吧,这是有道理的,他们对较老的 ARM 有帮助。如果立即数为零,则没有进位,因此将其描述为与有符号溢出标志一起设置为零。
Lsl 将一个文档中的进位显示为未更改而不是零。因此,也许随着时间的推移在指令的实现中发生了一些变化,或者 ARM ARMS 之一是错误的(这种情况经常发生)。

简短的回答, mov rd,rn 一直是作为添加记录的伪指令,反汇编程序可以选择将其打印出来,这取决于反汇编程序。
汇编语言由工具而不是目标定义,因此工具确定在其语法中使用哪种标志解决方案,并可以在添加、mov 高位寄存器、thumb2 编码或其他一些编码之间进行选择。
我们不知道为什么的问题,为什么选择一种编码而不是另一种编码,其中可能有相同的编码,通常选择较短的编码(thumb 与 thumb2 扩展)(x86 中的 xor 与 mov 立即数,零作为立即数)。但是 lsl vs add vs sub vs ...
您可以在 arm 文档中找到其他伪指令(记录当时其工具的汇编语言),以及汇编程序添加到其汇编语言中的伪指令,如 nop。
.thumb
nop
mov r8,r8
mov r4,r4

00000000 <.text>:
0: 46c0 nop ; (mov r8, r8)
2: 46c0 nop ; (mov r8, r8)
4: 1c24 adds r4, r4, #0
现在的问题是他们为什么不直接打印出来:
   0:   1c08        mov r0,r1  ; (adds r0, r1, #0)
我也喜欢反汇编器如何将分号作为注释边界,而汇编语言奇怪地不支持它(就像地球上的所有其他汇编器(以及大多数)一样)。
当然,反汇编程序不知道创建该机器代码的汇编程序是什么,因此对于有伪指令显示两者的情况会很好。

关于assembly - GNU ARM 汇编程序将 mov 更改为 add?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62838438/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com