首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >GNU ARM汇编程序将mov改为adds?

GNU ARM汇编程序将mov改为adds?
EN

Stack Overflow用户
提问于 2020-07-10 16:21:29
回答 2查看 691关注 0票数 5

社区!

我有以下一行源文件,名为first.S

代码语言:javascript
运行
复制
mov R1, R2

我生成一个对象文件如下:

代码语言:javascript
运行
复制
$ arm-none-eabi-as -mcpu=cortex-m3 -march=armv7 -mthumb -c -o first.o first.S 

然后,我把它拆开。

代码语言:javascript
运行
复制
$ 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指令。

在任何文件中是否有关于这样一项决定的地方?

谢谢!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-07-10 18:33:53

从一开始对拇指指令集,编码

代码语言:javascript
运行
复制
0001110xxxnnnddd 

是一个

代码语言:javascript
运行
复制
adds rd,rn,#xxx

如果对标志的修改对您来说是可以的,这将是更有效的编码。

伪指令mov,rn意味着标志可以改变(文档中的每个臂asm和明显的gas )。所以原始编码没问题。

现在由反汇编程序来选择一个if immed == 0,然后打印mov,rn vs adds,rn,#0,两者都是正确的反汇编。

现在,只有一个寄存器高和一个低的mov说:

代码语言:javascript
运行
复制
Unlike the low register MOV instruction described in MOV (2) on page A7-73, this instruction does not change the flags.

现在它进入了汇编语言,汇编语言完全是由汇编程序而不是目标(非ARM)定义的,以及可怕的统一语法。所以现在它变成了特定于工具的东西。例如,用于拇指的Gnu汇编程序不喜欢add (非统一语法,我发现它很容易用于拇指)--您可以做一个add并得到一个add。

代码语言:javascript
运行
复制
.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

然而,对摩佛来说,这是好的。

0x1c08 = 0x0001110000001000,这是一个添加拇指指令,当这一切开始时返回到armv4t。

代码语言:javascript
运行
复制
.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

因此,在这种情况下,它是一种不同的汇编语言(相同的工具,不同的汇编语言)。

因此,这个汇编语言尊重添加vs添加和mov vs mov。

为了进行添加而不使用thumb2编码,您需要使用编码。没有标志的mov是高寄存器mov 0x4608 0100011000001000 0x46xx。

add是过去的样子,mov现在被编码为左移,但它们不是分解lsl r0、r1、#0,而是作为mov r0、r1反汇编,更多的是供您咀嚼,而不是仅仅将mov分解为一个添加。他们为什么不使用adds?这里还有另一个问题,如果你看一下mov低寄存器指令--至少在旧的手臂上--它描述了它所显示的添加编码的标志发生了什么。但是,如果您查看lsl描述--标志是不同的-- lsl并不是带有标志的mov的替代品--至少像在最长的活臂(用拇指)中描述的那样。

好吧,这是有道理的,他们在老手臂上很有帮助。如果即时是零,那么就没有执行,因此它被描述为被设置为零以及签名的溢出标志。

Lsl显示在一个文档与另一个文档中的进位不变而不是零。因此,也许随着时间的推移,在执行指令时发生了一些变化,或者手臂中的一个是错误的(这种情况经常发生)。

简而言之,mov,rn一直是一个伪指令,作为一个补充,反汇编程序可以选择打印出来,它是由反汇编程序的任何方式。

汇编语言是由工具而不是目标定义的,因此该工具决定在其语法中使用哪种标记解决方案,并可以在添加、mov高寄存器、thumb2编码或其他编码之间进行选择。

我们将不知道为什么问题,为什么选择一种编码而另一种编码是可能的,通常选择较短的编码(拇指对thumb2扩展)( x86中的xor对以零作为直接的mov直接)。但lsl vs增加vs sub vs ..。

您可以在arm文档中找到其他伪指令(文档是其工具的汇编语言),以及汇编程序添加到其汇编语言中的伪指令(如nop )。

代码语言:javascript
运行
复制
.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

现在的问题是他们为什么不把这个打印出来:

代码语言:javascript
运行
复制
   0:   1c08        mov r0,r1  ; (adds r0, r1, #0)

我还喜欢反汇编程序是如何将分号作为注释边界的,其中汇编语言奇怪地不支持这个(就像地球上的所有其他汇编程序一样(好吧,大多数))。

假设反汇编程序不知道是什么汇编程序创建了机器代码,所以对于存在伪指令的情况,两者都显示最好。

票数 5
EN

Stack Overflow用户

发布于 2020-07-10 16:54:26

https://static.docs.arm.com/ddi0403/eb/DDI0403E_B_armv7m_arm.pdf#G11.5007716中,移动指令的操作码也是2字节,因此使用这两种操作都没有好处。https://developer.arm.com/documentation/ddi0337/e/instruction-timing/processor-instruction-timings声明,这两个指令使用一个CPU周期来完成.

然而,编码T2 https://static.docs.arm.com/ddi0403/eb/DDI0403E_B_armv7m_arm.pdf#G11.5007716会有一个空字节,这在某些情况下是不好的(利用漏洞)。

然而,我可以想象,构建一个汇编程序越容易,它产生的不同操作代码就越少。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62838438

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档