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.rhkb.cn/news/463535.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Clikhouse 探秘】ClickHouse 物化视图:加速大数据分析的新利器

&#x1f449;博主介绍&#xff1a; 博主从事应用安全和大数据领域&#xff0c;有8年研发经验&#xff0c;5年面试官经验&#xff0c;Java技术专家&#xff0c;WEB架构师&#xff0c;阿里云专家博主&#xff0c;华为云云享专家&#xff0c;51CTO 专家博主 ⛪️ 个人社区&#x…

【HarmonyOS NEXT】在 HarmonyOS NEXT 中实现优雅的加载动画

【HarmonyOS NEXT】在 HarmonyOS NEXT 中实现优雅的加载动画 在移动应用开发中&#xff0c;加载动画是提升用户体验的重要工具。在应用程序处理数据或加载页面时&#xff0c;为用户提供视觉反馈尤为关键。在这篇博客中&#xff0c;我们将探讨如何在 HarmonyOS NEXT 中使用 Sta…

Redis高级篇之缓存一致性详细教程

文章目录 0 前言1.缓存双写一致性的理解1.1 缓存按照操作来分 2. 数据库和缓存一致性的几种更新策略2.1 可以停机的情况2.2 我们讨论4种更新策略2.3 解决方案 总结 0 前言 缓存一致性问题在工作中绝对没办法回避的问题&#xff0c;比如&#xff1a;在实际开发过程中&#xff0c…

C++_day2

目录 1. 引用 reference&#xff08;重点&#xff09; 1.1 基础使用 1.2 特性 1.3 引用参数 2. C窄化&#xff08;了解&#xff09; 3. 输入&#xff08;熟悉&#xff09; 4. string 字符串类&#xff08;掌握&#xff09; 4.1 基础使用 4.2 取出元素 4.3 字符串与数字转换 5. …

Vuex的基本使用

文章目录 一、Vuex概述1.是什么2.使用场景3.优势4.注意二、如何构建vuex多组件共享数据环境1.创建项目2.创建三个组件3.源代码三、vuex 的使用 - 创建仓库1.安装 vuex2.新建 `store/index.js` 专门存放 vuex3.创建仓库 `store/index.js`4 在 main.js 中导入挂载到 Vue 实例上5.…

WPF+MVVM案例实战(二十一)- 制作一个侧边弹窗栏(CD类)

文章目录 1、案例效果1、侧边栏分类2、CD类侧边弹窗实现1、样式代码实现2、功能代码实现3 运行效果4、源代码获取1、案例效果 1、侧边栏分类 A类 :左侧弹出侧边栏B类 :右侧弹出侧边栏C类 :顶部弹出侧边栏D类 :底部弹出侧边栏2、CD类侧边弹窗实现 1、样式代码实现 在原有的…

揭开广告引擎的神秘面纱:如何在0.1秒内精准匹配用户需求?

目录 一、广告系统与广告引擎介绍 &#xff08;一&#xff09;广告系统与广告粗分 &#xff08;二&#xff09;广告引擎在广告系统中的重要性分析 二、广告引擎整体架构和工作过程 &#xff08;一&#xff09;一般概述 &#xff08;二&#xff09;核心功能架构图 三、标…

[论文阅读]A Survey of Embodied Learning for Object-Centric Robotic Manipulation

Abstract --以对象为中心的机器人操纵的Embodied learning是体现人工智能中一个快速发展且具有挑战性的领域。它对于推进下一代智能机器人至关重要&#xff0c;最近引起了人们的极大兴趣。与数据驱动的机器学习方法不同&#xff0c;具身学习侧重于通过与环境的物理交互和感知反…

NFTScan Site:以蓝标认证与高级项目管理功能赋能 NFT 项目

自 NFTScan Site 上线以来&#xff0c;它迅速成为 NFT 市场中的一支重要力量&#xff0c;凭借对各类 NFT 集合、市场以及 NFTfi 项目的认证获得了广泛认可。这个平台帮助许多项目提升了曝光度和可见性&#xff0c;为它们在竞争激烈的 NFT 市场中创造了更大的成功机会。 在最新更…

指数分布的原理和应用

本文介绍指数分布&#xff0c;及其推导原理。 Ref: 指数分布 开始之前&#xff0c;先看个概率密度函数的小问题&#xff1a; 问题描述&#xff1a;你于上午10点到达车站&#xff0c;车在10点到10:30 之间到达的时刻 X 的概率密度函数如图&#xff1a; 则使用分段积分&#xff0…

Javase——正则表达式

正则表达式的相关使用 public static void main(String[] args) {//校验QQ号 System.out.println("3602222222".matches("[1-9][0-9]{4,}"));// 校验18位身份证号 System.out.println("11050220240830901X".matches("^([0-9]){7,18}…

安装中文版 Matlab R2022a

下载安装包 压缩包有点大&#xff0c;大概20G 百度网盘&#xff1a;下载链接 提取码&#xff1a;rmja 安装 解压后打开目录&#xff0c;右键以管理员身份运行 setup.exe 选择输入安装秘钥 输入秘钥&#xff1a; 50874-33247-14209-37962-45495-25133-28159-33348-18070-6088…

SICTF Round #4|MISC

1.派森 腐乳昂木 奥普瑞特儿 阴坡尔特 艾克斯奥尔 腐乳昂木 提克有第爱慕 阴坡尔特 ⭐ 弗拉格 等于 布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉布拉 印刻 等于 左中括号右中括号 佛儿 唉 因 梯软者左括号 零&#xff0c;楞左括号弗拉格右…

保研考研机试攻略:python笔记(2)

&#x1f428;&#x1f428;&#x1f428;宝子们好呀&#xff0c;今天我们继续来学习N诺提供的python笔记&#xff0c;fighting&#xff01;( •̀ ω •́ )✧ 对这个系列感兴趣的宝子欢迎关注保研考研机试攻略专栏哦 ~ 目录 &#x1f428;&#x1f428;&#x1f428;4进制转…

Hyper-V 安装 KylinOS V10【图文教程】

文章目录 下载 KylinOSHyper-V 安装 KylinOS新建虚拟机配置虚拟机启动虚拟机并配置下载 KylinOS KylinOS 没有直接提供下载地址,需要在页面上点试用,填写个人信息后,才能看到下载地址。 https://www.kylinos.cn/support/trial.html?trial=425887 试用地址:产品试用申请国…

LeetCode 0685.冗余连接 II:并查集(和I有何不同分析)——详细题解(附图)

【LetMeFly】685.冗余连接 II&#xff1a;并查集&#xff08;和I有何不同分析&#xff09;——详细题解(附图) 力扣题目链接&#xff1a;https://leetcode.cn/problems/redundant-connection-ii/ 在本问题中&#xff0c;有根树指满足以下条件的 有向 图。该树只有一个根节点&…

mysql查表相关练习

作业要求&#xff1a; 单表练习&#xff1a; 1 . 查询出部门编号为 D2019060011 的所有员工 2 . 所有财务总监的姓名、编号和部门编号。 3 . 找出奖金高于工资的员工。 4 . 找出奖金高于工资 40% 的员工。 5 找出部门编号为 D2019090011 中所有财务总监&#xff0c;和…

GHuNeRF: Generalizable Human NeRF from a Monocular Video

研究背景 研究问题&#xff1a;这篇文章要解决的问题是学习一个从单目视频中泛化的人类NeRF模型。尽管现有的泛化人类NeRF已经取得了令人印象深刻的成果&#xff0c;但它们需要多视图图像或视频&#xff0c;这在某些情况下可能不可用。此外&#xff0c;一些基于单目视频的人类…

Linux - grep的正则用法

新建u.txt&#xff0c;文本内容如图&#xff1a; 搜寻特定字符串 利用中括号[]搜寻集合字符 行首与行位字符^$ 任意一个字符.与重复字符*限定连续RE字符范围{} 总结:

项目模块十五:HttpResponse模块

一、模块设计思路 存储HTTP应答要素&#xff0c;提供简单接口 二、成员变量 int _status; // 应答状态码 unordered_map<string, string> _headers; // 报头字段 string _body; // 应答正文 bool _redirect_flag; // 是否重定向信息 stri…