首页 > 解决方案 > 为什么 -marm 选项仍然会生成拇指指令?

问题描述

(我是 ARM 世界的新手。如果这是一个愚蠢的问题,请原谅。)

我正在使用下面的命令行为 C 文件生成汇编代码。

cpu 是arm926ej-s,也就是ARMv5 architecture

arm-none-eabi-gcc -mcpu=arm926ej-s -mthumb -S t.c -o t_thumb.S
arm-none-eabi-gcc -mcpu=arm926ej-s -marm -S t.c -o t_arm.S

我期望-marmand-mthumb选项会产生不同的功能序言。但他们给出了类似的结果:

对于-marm:

@ args = 0, pretend = 0, frame = 72
@ frame_needed = 1, uses_anonymous_args = 0
push    {fp, lr} @<========== push is used instead of stmfd
add fp, sp, #4
sub sp, sp, #72
bl  uart_init

对于-mthumb:

@ args = 0, pretend = 0, frame = 72
@ frame_needed = 1, uses_anonymous_args = 0
push    {r7, lr} @<========== push is used as expected
sub sp, sp, #72
add r7, sp, #0
bl  uart_init

所以他们都使用push指令。但是当我检查了 ARMv5 架构规范时,该push指令属于Thumb指令集。我期待stmfd这个-marm选项。

为什么会push选择呢?

如何生成ARM 指令?

添加 1 - 2019 年 12 月 18 日下午 5:21

下面是.o文件的反汇编:

arm-none-eabi-gcc -mcpu=arm926ej-s -marm -g -c t.c -o build/t_arm.o
arm-none-eabi-objdump.exe -d build/t_arm.o > t_arm.dism

拆解:

000002a0 <main>:
 2a0:   e92d4800    push    {fp, lr} <=============== push is used!
 2a4:   e28db004    add fp, sp, #4
 2a8:   e24dd048    sub sp, sp, #72 ; 0x48
 2ac:   ebfffffe    bl  0 <uart_init>
 2b0:   e59f3168    ldr r3, [pc, #360]  ; 420 <main+0x180>
 2b4:   e50b300c    str r3, [fp, #-12]
 2b8:   e59f1164    ldr r1, [pc, #356]  ; 424 <main+0x184>
 2bc:   e51b000c    ldr r0, [fp, #-12]

添加 2 - 2019 年 12 月 18 日下午 5:34

感谢@Erlkoenig

我只是试图反汇编一个-mthumb二进制文件:

arm-none-eabi-gcc -mcpu=arm926ej-s -mthumb -g -c t.c -o build/t_thumb.o
arm-none-eabi-objdump.exe -d build/t_thumb.o > t_thumb.dism

显示了完全不同的thumb反汇编:

00000170 <main>:
 170:   b580        push    {r7, lr} <====== though still push is shown, but the encoding is different.
 172:   b092        sub sp, #72 ; 0x48
 174:   af00        add r7, sp, #0
 176:   f7ff fffe   bl  0 <uart_init>
 17a:   4b3c        ldr r3, [pc, #240]  ; (26c <main+0xfc>)
 17c:   643b        str r3, [r7, #64]   ; 0x40
 17e:   4a3c        ldr r2, [pc, #240]  ; (270 <main+0x100>)
 180:   6c3b        ldr r3, [r7, #64]   ; 0x40

标签: arm

解决方案


如图所示,原始指令的十六进制编码objdump -d表明这一条 32 位 ARM(“ A32 ”)指令(0xe92d4800)。由标志 to.S生成的文件和输出仅使用 ARM UAL(统一汇编语法),它用作 的别名,而 ARMv5T 架构参考手册使用旧语法,在 A32 上没有。指令编码与 的编码相匹配,这是一个别名。编码显示在 p 上。ARMv5T 参考手册中的 339。-SGCCobjdumppushstmfdpushstmdbstmfd

A32(“ARM”)代码很容易识别,因为所有指令都是 4 字节宽,前 4 位通常是十六进制E(这意味着条件代码是AL,即指令总是无条件执行):

[e]92d4800
[e]28db004
[e]24dd048
[e]bfffffe

在十六进制编辑器中查看原始二进制文件时,这很有帮助。Thumb(“T32”)代码有许多 16 位指令,一些 32 位指令,并且没有 s 的“堆栈” E

b580
b092
af00
f7ff fffe

当然,对于原始二进制文件,不能直接明确哪些 2 字节组和 4 字节组属于一起作为指令。


推荐阅读