当前位置: 首页 > news >正文

Thumb 汇编指令集,Thumb 指令编码方式,编译 Thumb 汇编代码

版权归作者所有,如有转发,请注明文章出处:https://cyrus-studio.github.io/blog/

Thumb指令集

ARM 指令集:最早在 1985 年随第一代 ARM 处理器问世。ARM 指令集一开始是 32 位固定长度的指令,用于各种计算任务。

Thumb 指令集:在 1994 年的 ARM7TDMI 处理器中首次引入。这是在 ARM 指令集基础上开发的一个 16 位指令集,旨在优化嵌入式系统中代码密度和内存效率。

寄存器 Thumb 跟 ARM 是一样的。

随着 ARM 架构的演进,后来加入了 32 位的 Thumb 指令,称为 Thumb-2 指令集。

以简单的加载立即数到寄存器为例,解释一下 16 位和 32 位的 Thumb 指令的区别

16 位 Thumb 指令

MOVS R0, #1   // 将立即数 1 加载到 R0,指令长度为 16 位

32 位 Thumb 指令

MOV.W R0, #65535  // 将较大的立即数 65535 加载到 R0,指令长度为 32 位

由于 16 位 Thumb 指令长度有限,无法直接处理大立即数,而 32 位 Thumb 指令支持更大的立即数范围。32 位指令格式可以容纳更多位的立即数、更复杂的操作码。

在 ARM64 架构(也称为 AArch64)中,不再支持 Thumb 指令集,因此也没有 16 位和 32 位的 Thumb 指令。

ARM64 仅支持 32 位的固定长度指令,取消了 Thumb 指令集以及 ARM 和 Thumb 模式的切换,从而简化了指令解码和执行流程。

Thumb指令集文档

google 搜索 armv7 site:arm.com

截图.png

找到arm指令参考手册并下载pdf到本地:https://developer.arm.com/documentation/ddi0406/latest/

在文档书签目录可以看到有16位和32位 Thumb 指令集文档,也可以找 thumb 指令的编码方式说明

截图.png

Thumb 指令的编码方式

以下面的 16 位 Thumb 指令为例

MOVS R0, #1   // 将立即数 1 加载到 R0,指令长度为 16 位

在 16 位 Thumb 指令集中,MOVS Rd, #imm8 指令的编码格式如下

1514131211109876543210
含义00100Rd(3 位)Imm(8 位)

其中:

  • 位 15-11:00100 是 MOVS 指令的操作码。

  • 位 10-8:寄存器 Rd,即目标寄存器的编码,这里 R0 的编码为 000。

  • 位 7-0:立即数 imm8,8 位长度的立即数。

对于 MOVS R0, #1:

  • 操作码:00100(固定)。

  • 寄存器 Rd:目标寄存器为 R0,编码为 000。

  • 立即数 imm8:#1 的二进制为 0000 0001。

将这些字段组合在一起

0010 0000 0000 0001

十六进制值为 0x2001
image.png
转为为小端模式后为 0x0120

在 ARM 架构(包括 Thumb 指令集)中,机器码在存储时通常使用 小端模式。小端模式下,低字节先存储,所以存储在内存中的顺序会变为 01 20。

打开 https://armconverter.com/?disasm,验证一下是否正确
image.png

编译 Thumb 汇编指令

编写一个C程序 hello_thumb.c 源码如下

#include <stdio.h>int main() {int result = 1 + 1;printf("1 + 1 = %d\n", result);return 0;
}

执行下面命令把 hello_thumb.c 编译成 thumb 汇编代码文件 hello_thumb.s

armv7a-linux-androideabi35-clang -S -mthumb hello_thumb.c -o hello_thumb.s

-mthumb 表示使用 thumb 汇编

关于ARM程序生成过程可以参考这篇文章【详解ARM64可执行程序的生成过程】

打开 hello_thumb.s 可以看到,结构上和 ARM 汇编是差不多的,多了一些 thumb 标记,如:.code 16、.thumb_func 标记为 16 位 thumb,还有使用到 thumb 指令。

    .text                                // 指令区段开始.syntax unified                      // 统一汇编语法.eabi_attribute 67, "2.09"           // EABI 属性,符合 ARM EABI 2.09.eabi_attribute 6, 10                // EABI 属性,CPU 架构为 ARMv7.eabi_attribute 7, 65                // EABI 属性,CPU 为 Application Profile (A-profile).eabi_attribute 8, 1                 // EABI 属性,使用 ARM 指令集.eabi_attribute 9, 2                 // EABI 属性,使用 Thumb-2 指令集.fpu neon                            // 指定 NEON 浮点单元 (FPU) 支持.eabi_attribute 34, 1                // EABI 属性,支持未对齐的内存访问.eabi_attribute 15, 1                // EABI 属性,RW 数据符合 PCS.eabi_attribute 16, 1                // EABI 属性,RO 数据符合 PCS.eabi_attribute 17, 2                // EABI 属性,GOT 符合 PCS.eabi_attribute 20, 1                // EABI 属性,FP 支持非正规数.eabi_attribute 21, 0                // EABI 属性,不支持 FP 异常.eabi_attribute 23, 3                // EABI 属性,IEEE 754 浮点模型.eabi_attribute 24, 1                // EABI 属性,内存对齐需求.eabi_attribute 25, 1                // EABI 属性,内存对齐保留.eabi_attribute 38, 1                // EABI 属性,支持 16 位浮点格式.eabi_attribute 18, 4                // EABI 属性,wchar_t 为 4 字节.eabi_attribute 26, 2                // EABI 属性,enum 类型大小为 32 位.eabi_attribute 14, 0                // EABI 属性,不使用 R9 寄存器作为特殊用途.file "hello_thumb.c"                // 文件名 "hello_thumb.c".globl main                          // 声明全局符号 main.p2align 2                           // 代码段对齐到 4 字节.type main,%function                 // 声明 main 函数.code 16                             // 使用 Thumb 指令集.thumb_func                          // 标记为 Thumb 函数
main:.fnstart                             // 函数开始标记
@ %bb.0:.save {r7, lr}                       // 保存 r7 和 lr 到栈中push {r7, lr}                        // 压栈保存 r7 和 lr.setfp r7, sp                        // 设置帧指针 r7 指向当前栈指针 spmov r7, sp                           // 将 sp 值复制到 r7.pad #16                             // 保留 16 字节栈空间sub sp, #16                          // sp 减 16,分配栈空间movs r0, #0                          // 将 0 存入 r0str r0, [sp, #4]                     // 将 r0 (0) 存入栈的偏移量 4 处str r0, [sp, #12]                    // 将 r0 (0) 存入栈的偏移量 12 处movs r0, #2                          // 将 2 存入 r0str r0, [sp, #8]                     // 将 r0 (2) 存入栈的偏移量 8 处ldr r1, [sp, #8]                     // 将偏移量 8 的值 (2) 加载到 r1 中ldr r0, .LCPI0_0                     // 加载 .LCPI0_0 到 r0 中
.LPC0_0:add r0, pc                           // 计算字符串地址并将其加到 r0bl printf                            // 调用 printf 函数// printf 执行完成后,返回主函数ldr r0, [sp, #4]                     // 从栈的偏移量 4 处加载 r0 (0)add sp, #16                          // 恢复栈指针,释放 16 字节的栈空间pop {r7, pc}                         // 恢复 r7 并从栈中弹出返回地址到 pc.p2align 2                           // 代码对齐
@ %bb.1:
.LCPI0_0:.long .L.str-(.LPC0_0+4)             // 存储字符串 .L.str 的偏移量
.Lfunc_end0:.size main, .Lfunc_end0-main         // 指定 main 函数的大小.cantunwind                          // 标记不能展开.fnend                               // 函数结束标记// main 函数定义结束.type .L.str,%object                 // 声明字符串常量.section .rodata.str1.1,"aMS",%progbits,1  // 只读数据段,存储字符串
.L.str:.asciz "1 + 1 = %d\n"                // 字符串 "1 + 1 = %d\n".size .L.str, 12                     // 指定字符串的大小为 12 字节.ident "Android ... clang version ..."  // 编译器标识符.section ".note.GNU-stack","",%progbits   // 栈保护

执行下面命令把 thumb 汇编文件编译成可执行程序 hello_thumb。

armv7a-linux-androideabi35-clang hello_thumb.s -o hello_thumb

把 hello_thumb 推送到 android 设备并执行

adb push .\hello_thumb /data/local/tmp
adb shell chmod +x /data/local/tmp/hello_thumb
adb shell /data/local/tmp/hello_thumb

输出如下
image.png


http://www.mrgr.cn/news/65125.html

相关文章:

  • Matlab实现鲸鱼优化算法优化随机森林算法模型 (WOA-RF)(附源码)
  • Rust的enum枚举的强大用法
  • 实景三维赋能森林防灭火指挥调度智慧化
  • #【YashanDB认证】#YCA的学习过程总结-之崖山数据库初体验
  • MDA模型驱动开发
  • Mac下载 安装MIMIC-IV 3.0数据集
  • 软件平台系统稳定性规范
  • PHP JSON 教程
  • 国产操作系统重新安装软件商店
  • CSS 计数器:深入解析与高级应用
  • 21.网工入门篇--------介绍下SDN与NFV的概述
  • Spring 函数式端点详解
  • 【Linux 26】应用层协议 - HTTP
  • 工作:三菱IQ-R PLC的SFC程序编写方式及代码模拟仿真
  • 项目开发管理之开发、测试到上线
  • 英语四六级/考研英语资料迅雷网盘免费分享
  • 嵌入式实验1-软件配置+STM32最小系统+LED灯交替闪烁
  • koa + sequelize做距离计算(MySql篇)
  • MyBatis-Plus条件构造器:构建安全、高效的数据库查询
  • 深入了解 Flutter 中的泛型:让代码更灵活更安全的关键
  • 6-4 重新加载GDT(1)
  • 2025四川省考职位表+新增考点15页。完整备考资料集!!!免费领取!
  • 嵌入式开发之刷新流
  • 51c大模型~合集10
  • Python毕业设计选题:基于Hadoop的租房数据分析系统的设计与实现
  • HTML5+css3(伪类,动态伪类,结构伪类,否定伪类,UI伪类,语言伪类,link,hover,active,visited,focus)