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.xdnf.cn/news/787.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

Leetcode - 周赛421

目录 一&#xff0c;3334. 数组的最大因子得分 二&#xff0c;3335. 字符串转换后的长度 I 三&#xff0c;3336. 最大公约数相等的子序列数量 四&#xff0c;3337. 字符串转换后的长度 II 一&#xff0c;3334. 数组的最大因子得分 暴力方法就不演示&#xff0c;这里介绍一个…

文件管理工具的按路径名称归类功能大公开,将大量文件批量复制或移动到指定路径,办公软件达人的秘密武器

是否还在为成堆的文件归类而苦恼&#xff1f;想要一键就能将海量文件按路径名称轻松归类&#xff0c;无论是复制还是移动&#xff1f;别急&#xff0c;今天就让文件批量改名高手软件的按路径名称归类功能来拯救你的文件管理世界&#xff01;让我们一起告别繁琐&#xff0c;迎接…

建设NFS服务器并实现文件共享

关闭防火墙和s0 systemctl stop firewalld setenforce 0 安装NFS yum install nfs-utils -y 新建共享目录并设置权限 echo "hello" > /nfs/shared/test1 chmod -Rf 777 /nfs/shared/ 配置服务端的NFS配置文件 vim /etc/exports /nfs/shared *(ro) 启动…

曹操出行借助 ApsaraMQ for Kafka Serverless 提升效率,成本节省超 20%

本文整理于 2024 年云栖大会主题演讲《云消息队列 ApsaraMQ Serverless 演进》&#xff0c;杭州优行科技有限公司消息中间件负责人王智洋分享 ApsaraMQ for Kafka Serverless 助力曹操出行实现成本优化和效率提升的实践经验。 曹操出行&#xff1a;科技驱动共享出行未来 曹操…

(转载)Tools for Learning LLVM TableGen

前提 最近在学习有关llvm的东西&#xff0c;其中TableGen占了一部分&#xff0c;所以想特意学习下TableGen相关的语法。这里找到了LLVM官网的一篇介绍TableGen的博客&#xff0c;学习并使用机器翻译为中文。在文章的最后也添加了一些学习TableGen的资源。 原文地址&#xff1…

vue3uniapp实现自定义拱形底部导航栏,解决首次闪烁问题

前言&#xff1a; 我最初在网上翻阅查找了很多方法&#xff0c;发现大家都是说在page.json中tabbar中添加&#xff1a;"custom": true,即可解决首次闪烁的问题&#xff0c;可是添加了我这边还是会闪烁&#xff0c;因此我这边改变了思路&#xff0c;使用了虚拟页面来解…

【P2-5】ESP8266 WIFI模块在AP模式下作为TCP服务器与多个电脑/手机网络助手(TCP客户端)通信——TCP数据透传

前言:完成ESP8266 WIFI模块在AP模式下作为TCP服务器与多个电脑/手机网络助手(TCP客户端)通信——实现TCP数据透传 AP模式,通俗来说模块可以发出一个WIFI热点提供给电脑/手机连接。 TCP服务端,通俗来说就是模块/单片机作为服务器,可以接收多个客户通道的连接。 本…

Kali Linux 新工具推荐: Sploitscan

在 2024.2 版本 Kali Linux 增加了一个新攻击工具: Sploitscan 1.简介: Sploitscan 能够发现操作系统和应用程序中的安全漏洞。 2.特点: 简单的命令行界面 扫描多个操作系统和应用程序 检测多种漏洞 提供详细信息 可定制性强 3.示例: 2024.2 及以后的版本 Kali Linux…

11.Three.js使用indexeddb前端缓存模型优化前端加载效率

11.Three.js使用indexeddb前端缓存模型优化前端加载效率 1.简述 在使用Three.js做数字孪生应用场景时&#xff0c;我们常常需要用到大量模型或数据。在访问我们的数字孪生应用时&#xff0c;每次刷新都需要从web端进行请求大量的模型数据或其他渲染数据等等&#xff0c;会极大…

基于PyTorch的大语言模型微调指南:Torchtune完整教程与代码示例

近年来,大型语言模型(Large Language Models, LLMs)在自然语言处理(Natural Language Processing, NLP)领域取得了显著进展。这些模型通过在大规模文本数据上进行预训练,能够习得语言的基本特征和语义,从而在各种NLP任务上取得了突破性的表现。为了将预训练的LLM应用于特定领域…

探索Unity:从游戏引擎到元宇宙体验,聚焦内容创作

unity是实时3D互动内容创作和运营平台&#xff0c;包括游戏开发、美术、建筑、汽车设计、影视在内的所有创作者&#xff0c;借助Unity将创意变成现实。提供一整套完善的软件解决方案&#xff0c;可用于创作、运营和变现任何实时互动的2D和3D内容&#xff0c;支持平台包括手机、…

3、setup语法糖

setup 概述 setup是Vue3中一个新的配置项&#xff0c;值是一个函数&#xff0c;它是 Composition API 组件中所用到的&#xff1a;数据、方法、计算属性、监视......等等&#xff0c;均配置在setup中。 特点如下&#xff1a; setup函数返回的对象中的内容&#xff0c;可直接…

USB协议学习

文章目录 USB发展背景发展变化速度等级通讯接口 四种传输主设备 & 从设备主设备从设备 连接与检测高速设备与主机连接USB总线常见的几种状态 枚举过程特点 控制传输学习资料 USB发展背景 发展变化 USB1.1&#xff1a;规范了USB低全速传输&#xff1b; USB2.0&#xff1a;…

讲讲 kafka 维护消费状态跟踪的方法?

大家好&#xff0c;我是锋哥。今天分享关于【讲讲 kafka 维护消费状态跟踪的方法&#xff1f;】面试题&#xff1f;希望对大家有帮助&#xff1b; 讲讲 kafka 维护消费状态跟踪的方法&#xff1f; 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 在 Kafka 中&#x…

【成都新篇】龙信科技电子取证实验室,引领科技取证新时代

文章关键词&#xff1a;电子数据取证实验室、手机取证、介质取证、云取证、现场勘查、电子物证 在科技创新的浪潮中&#xff0c;龙信科技成都实验室以其卓越的电子数据取证服务&#xff0c;成为了中西部地区一颗璀璨的明珠。随着新址的搬迁&#xff0c;我们不仅扩大了业务范围…

linux自动清理管理日志文件 logrotate

logrotate是linux通常会自带的工具&#xff0c;可以自动切割清理日志文件 一、安装&#xff08;通常无需&#xff09; 通常系统自带 sudo apt install logrotate或者 sudo dnf install logrotate二、具体使用 以nginx日志为例 1.创建脚本文件 vi /etc/logrotate.d/nginx…

JDBC学习笔记

九月十八: 需要添加jar包到依赖 虽然能驱动了,但是仍然不知道当时为什么不能驱动, 8.0以上会自动驱动, 也就是说只需要做好connection和statement 连接数据库的五种方式: 方式五: Statement: SQL注入小案例: ? 相当于占位符 JDBCUtils: 事务与批处理: String sql "INS…

wps Excel下拉框生成填充及下拉框内容颜色格式修改

一、Excel下拉框生成&#xff1a;(路径&#xff1a;数据-下拉列表) 1、先选中需要插入下拉列表的单元格 2、然后进入“数据-下拉列表”中增加对应的下拉项目(例如&#xff1a;√&#xff0c;X) 二、下拉框选项颜色和字体修改 1、先选中需要修改的下拉列表的所有单元格 2、然…

预约小程序多选修改——思路分享

预约小程序——多选的修改 预约小程序模版的来源&#xff1a;yunzizyy/ZixiAppt: 在这个小程序上做了较多的修改&#xff08;补充了丢失的代码、二维码签到、惩罚封禁机制、多选时间段和设置日期&#xff09;&#xff0c;其中有一个涉及到了时间段选择中的多选功能的添加&…

PostgreSQL核心揭秘(二)-进程和内存架构

目录 1、进程架构2、进程架构图 3、内存架构 4、内存架构图 PostgreSQL 的进程架构采用了一个多进程的设计&#xff0c;这使其能够有效地管理并发连接和资源。以下是 PostgreSQL 的主要进程架构组成部分的详细描述&#xff1a; 1. 主进程&#xff08;Postmaster&#xff09; 功…