arm - 为什么 -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
我期望-marm
and-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
解决方案
如图所示,原始指令的十六进制编码objdump -d
表明这是一条 32 位 ARM(“ A32 ”)指令(0xe92d4800)。由标志 to.S
生成的文件和输出仅使用 ARM UAL(统一汇编语法),它用作 的别名,而 ARMv5T 架构参考手册使用旧语法,在 A32 上没有。指令编码与 的编码相匹配,这是一个别名。编码显示在 p 上。ARMv5T 参考手册中的 339。-S
GCC
objdump
push
stmfd
push
stmdb
stmfd
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 字节组属于一起作为指令。
推荐阅读
- mule - 缺少 Mule 文档名称
- java - 尝试获取空数组 Kotlin 的长度
- sql-server - SAP B1:如何检查 OIVL 表中是否插入了新数据
- laravel - Laravel 6.0 输入::value"old(' ')"
- visual-studio-code - 如何在vscode中设置匹配的括号颜色?
- kivy - Kivy ScreenManager 根本不做任何事情
- javascript - Javascript文本更改未在HTML“for”中修复
- java - 来自 JavaFX 桌面客户端应用程序的 RESTful API 身份验证
- node.js - 从以下 Firestore 列表中获取最新帖子
- python - Colab/Jupyter/Python:如何读取上传的文件