ARM汇编语言实现peek()_ARM汇编之访问C语言结构体数据
前言
本文的写作目的在于装逼,没有要产生实际价值的意思。
前几天在做编译器的项目,有一个项目团队成员一直在问我ARM汇编能不能读C语言的结构体。我心想,我这生成ARM汇编的代码是用C++写的呀,又不是用汇编写的,干嘛问我这个?我跟他说,能啊。还非要我出demo。
作为一个《汇编语言程序设计》课程绩点只有5.0的渣渣,我的内心有一万只草泥马奔腾而过。好吧,菜鸡的我没说什么,默默地用二十分钟准备了相关代码、AXD Debugger仿真截图,并且标注了C语言定义的全局变量在内存中的位置、寄存器的数值。
虽然并没有什么卵用,但是能拿来装逼鸭hhhh。基于这个问题,我稍微地做了一下进一步的讨论。
先来点开胃小菜
我们先从这个简单的结构体开始,做一个实验,验证ARM能访问C语言结构体的数据。
struct
先写C语言的代码,目的是为了声明并初始化一个结构体变量,让ARM汇编进行访问。
#include
然后再来写配套的ARM汇编。
area armFunc, code, readonlycode32export myFuncmyFunc ldr r4,[r0] ;读取t.a,其值存储在R4寄存器ldr r5,[r0,#4] ;读取t.b,其值存储在R5寄存器ldr r6,[r0,#8] ;读取t.c,其值存储在R6寄存器b . ;程序卡在这里,方便我们停下来观察end
AXD Debugger仿真结果如下:
我们对这个仿真结果做一个简单的分析。一些关键的地方我已经在图上用不同颜色的框标记出来。程序从main函数开始执行,并且为结构体t的三个成员分别进行初始化。它们的值按照小端序依次存放在内存中(红框、绿框和紫框)。
再调用myFunc函数,将结构体t的指针(0x000083FC)作为参数传递过去(根据ATPCS规范可知)。在myFunc里面利用基址变址寻址将结构体t的数据读取出来。黄框中寄存器的数值分别为三个成员的初值。
万一,类型长度不是4字节呢?
在上面给的汇编代码里,地址偏移量总是为4的倍数。这是因为int类型的数据长度正好是4字节。那么,如果用的数据类型的长度不是4字节呢?
还是举一个结构体的例子。
struct
在这个例子里,包含了char、short和int三种类型的成员。它们代表着字节数据、半字数据和字数据(字长32位)。相应地,C语言代码和对应的ARM汇编代码也要作出改动。
C语言代码如下:
struct
ARM汇编代码如下:
area armFunc, code, readonlycode32export myFuncmyFunc ldr r4,[r0] ;读取t.a,其值存储在R4寄存器ldrs r5,[r0,#4] ;读取t.b,其值存储在R5寄存器ldrh r6,[r0,#6] ;读取t.c,其值存储在R6寄存器b . ;程序卡在这里,方便我们停下来观察end
相应的仿真结果:
程序仍然能正确读取结构体的数据。但是观察绿框可以发现:成员b占用了两个字节的空间。这是由于编译器在分配myData2各成员在内存中的位置时,以半字为单位进行字节对齐。不同的编译器在编译C语言代码时,对于字节对齐的规定有可能不同,需要具体情况具体分析。回到这个仿真结果来:因此在后续访问成员c的指令中,地址偏移量为4+2=6,而不是4+1=5。在编写结构体访问的相关指令时,要注意结构体各成员在内存空间中的分布。
算法举例:二叉树的递归先序遍历
在访问结构体数据的基础上,我们还可以用ARM汇编做链表的访问、二叉树的遍历等。这里稍微举个栗子:二叉树的先序遍历,采用递归实现。
先写一段C语言代码,主要用来准备用来先序遍历的二叉树,以及编写输出的相关代码。
#include
先序遍历的算法主体则放在了ARM汇编里。
area armFunc, code, readonlycode32export preVisitimport myPrintpreVisit STMFD sp!,{r4,fp,lr};调用myPrint函数输出data成员LDR r4,[r0]STMFD sp!,{r0}MOV r0,r4BL myPrintLDMFD sp!,{r0};递归调用preVisit遍历左子树LDR r4,[r0,#4]CMP r4,#0BEQ rightSTMFD sp!,{r0}MOV r0,r4BL preVisitLDMFD sp!,{r0};递归调用preVisit遍历右子树
right LDR r4,[r0,#8]CMP r4,#0BEQ funcEndSTMFD sp!,{r0}MOV r0,r4BL preVisitLDMFD sp!,{r0}
funcEnd LDMFD sp!,{r4,fp,pc}end
如果没有猜错的话,输出结果应该是ABCDEFG:
后记
在写作本文的过程,发现自己在不知不觉中巩固了所学知识,提高了自己的知识迁移能力。比如说用ARM汇编写二叉树的先序遍历,既巩固了自己的数据结构知识,又能将数据结构的实现迁移到ARM汇编上。
参考文献
《汇编语言程序设计——基于ARM体系结构》
ARM汇编语言实现peek()_ARM汇编之访问C语言结构体数据相关推荐
- C语言结构体变量 指针以及对结构体成员的访问
文章目录 结构体 结构体变量访问成员的方法 结构体指针变量访问成员的方法 结构体 struct AGE {int year;int month;int day; }; struct STUDENT { ...
- 解决 王爽写的汇编语言的第七个验七- 寻址方式在结构化数据访问中的应用
原文: 汇编语言-(第三版) 王爽-著 (实验七) 寻址方式在结构化数据访问中的应用 https://www.52pojie.cn/thread-1241289-1-1.html (出处: 吾爱破解论 ...
- JNA嵌套结构体,如何访问内嵌结构体的成员?
如果不明白如何创建DLL动态链接库项目,可参照文章:https://blog.csdn.net/Xeon_CC/article/details/124873221 提出问题: C语言程序有个结构体叫B ...
- C语言之结构体以及结构体对齐访问
1:简单理解,结构体就是数组的进一步发展,数据的优点和缺陷在于数据里面是元素类型必须相同,但是结构体没有这个要求,结构体里面元素的类型可以相同也可以不同. 2:结构体的定义: struct stude ...
- c语言基础知识_结构体访问,共同体,枚举类型
C语言结构体变量的引用: 对于定义的结构体类型的普通变量,访问其成员用圆点运算符("."),标准访问方式如下: 结构体变量名.成员名 对于定义为指向结构体的指针变量,用箭头运算符( ...
- arm汇编指令_ARM汇编伪指令介绍.
符号定义( Symbol Definition )伪指令 符号定义伪指令用于定义 ARM 汇编程序中的变量.对变量赋值以及定义寄存器的别名等操作. 常见的符号定义伪指令有如下几种: - 用于定义全局变 ...
- 【Android 逆向】arm 汇编 ( 使用 IDA 解析 arm 架构的动态库文件 | 分析 malloc 函数的 arm 汇编语言 )
文章目录 一.分析 malloc 函数的 arm 汇编语言 一.分析 malloc 函数的 arm 汇编语言 在上一篇博客 [Android 逆向]arm 汇编 ( 使用 IDA 解析 arm 架构的 ...
- 使用arm混合汇编计算两个64位的和_混合使用C、C++和汇编语之: C、C++ 和 ARM 汇编语言之间的调用...
12.4C' target='_blank' style='cursor:pointer;color:#D05C38;text-decoration:underline;'>C.C++和ARM汇 ...
- att格式汇编指令_ARM汇编伪指令介绍.
符号定义( Symbol Definition )伪指令 符号定义伪指令用于定义 ARM 汇编程序中的变量.对变量赋值以及定义寄存器的别名等操作. 常见的符号定义伪指令有如下几种: - 用于定义全局变 ...
最新文章
- Linux系统 proc self,linux – / proc / self / maps中的“— p”权限是什么意思?
- java异常处理机简答题,【简答题】JAVA 语言如何进行异常处理,关键字: throws,throw,try,catch,finally 分别代表什么意义?...
- linux fuse 阻塞,FUSE原理总结
- 乌托邦式的经理人日记——小的奖励激发员工热情
- 额外参数_Redis的复制参数学习笔记
- android opencl sdk,在新的Android Studio中使用OpenCL
- 可行性研究报告模板 Shane版
- 微信小程序 抓css,微信小程序css篇
- Mybatis sql查不到数据
- 腾讯QQ大数据:机器学习建模问题中的特征构造方法
- python数据类型的应用
- 谷歌浏览器——默认搜索为百度
- 西游记孙悟空迅速从石猴飙升至斗战胜佛大罗金仙的辉煌人生旅程
- 杰力科创手持小风扇芯片——DLTAP703SC
- 关于移动端在cubeui中cube-scroll(以及better-scroll)里面写click会触发两次的问题
- Google浏览器打不开
- E. Boxers(贪心)
- GNSS定位原理(伪距)
- java框架基础教程_Java零基础教学,分分钟掌握基础学习框架
- 吃一堑长一智!mysql格式化查询结果
热门文章
- HDU-5723 Abandoned country
- 上周热点回顾(10.27-11.2)
- asp.net 页面刷新后,滚动条仍保持在原来的位置
- android java.lang.IllegalArgumentException: The observer is null.异常解决
- 解决方案:Error:Execution failed for task ‘:app:compileDebugAidl‘. > aidl is missing
- 解决:org.xml.sax.SAXParseException: 元素类型 “head“ 必须由匹配的结束标记 “</head>问题
- Failed to read schema document ‘http://code.alibabatech.com/schema/dubbo/dubbo.xsd‘问题解决方法
- docx.opc.exceptions.PackageNotFoundError: Package not found at ‘文件名.docx‘ 问题解决
- 返回,返回无,根本没有返回?
- 范围规则的简短描述?