前言

本文的写作目的在于装逼,没有要产生实际价值的意思。

前几天在做编译器的项目,有一个项目团队成员一直在问我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仿真结果如下:

AXD Debugger仿真结果(1)

我们对这个仿真结果做一个简单的分析。一些关键的地方我已经在图上用不同颜色的框标记出来。程序从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

相应的仿真结果:

AXD Debugger仿真结果(2)

程序仍然能正确读取结构体的数据。但是观察绿框可以发现:成员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语言结构体数据相关推荐

  1. C语言结构体变量 指针以及对结构体成员的访问

    文章目录 结构体 结构体变量访问成员的方法 结构体指针变量访问成员的方法 结构体 struct AGE {int year;int month;int day; }; struct STUDENT { ...

  2. 解决 王爽写的汇编语言的第七个验七- 寻址方式在结构化数据访问中的应用

    原文: 汇编语言-(第三版) 王爽-著 (实验七) 寻址方式在结构化数据访问中的应用 https://www.52pojie.cn/thread-1241289-1-1.html (出处: 吾爱破解论 ...

  3. JNA嵌套结构体,如何访问内嵌结构体的成员?

    如果不明白如何创建DLL动态链接库项目,可参照文章:https://blog.csdn.net/Xeon_CC/article/details/124873221 提出问题: C语言程序有个结构体叫B ...

  4. C语言之结构体以及结构体对齐访问

    1:简单理解,结构体就是数组的进一步发展,数据的优点和缺陷在于数据里面是元素类型必须相同,但是结构体没有这个要求,结构体里面元素的类型可以相同也可以不同. 2:结构体的定义: struct stude ...

  5. c语言基础知识_结构体访问,共同体,枚举类型

    C语言结构体变量的引用: 对于定义的结构体类型的普通变量,访问其成员用圆点运算符("."),标准访问方式如下: 结构体变量名.成员名 对于定义为指向结构体的指针变量,用箭头运算符( ...

  6. arm汇编指令_ARM汇编伪指令介绍.

    符号定义( Symbol Definition )伪指令 符号定义伪指令用于定义 ARM 汇编程序中的变量.对变量赋值以及定义寄存器的别名等操作. 常见的符号定义伪指令有如下几种: - 用于定义全局变 ...

  7. 【Android 逆向】arm 汇编 ( 使用 IDA 解析 arm 架构的动态库文件 | 分析 malloc 函数的 arm 汇编语言 )

    文章目录 一.分析 malloc 函数的 arm 汇编语言 一.分析 malloc 函数的 arm 汇编语言 在上一篇博客 [Android 逆向]arm 汇编 ( 使用 IDA 解析 arm 架构的 ...

  8. 使用arm混合汇编计算两个64位的和_混合使用C、C++和汇编语之: C、C++ 和 ARM 汇编语言之间的调用...

    12.4C' target='_blank' style='cursor:pointer;color:#D05C38;text-decoration:underline;'>C.C++和ARM汇 ...

  9. att格式汇编指令_ARM汇编伪指令介绍.

    符号定义( Symbol Definition )伪指令 符号定义伪指令用于定义 ARM 汇编程序中的变量.对变量赋值以及定义寄存器的别名等操作. 常见的符号定义伪指令有如下几种: - 用于定义全局变 ...

最新文章

  1. Linux系统 proc self,linux – / proc / self / maps中的“— p”权限是什么意思?
  2. java异常处理机简答题,【简答题】JAVA 语言如何进行异常处理,关键字: throws,throw,try,catch,finally 分别代表什么意义?...
  3. linux fuse 阻塞,FUSE原理总结
  4. 乌托邦式的经理人日记——小的奖励激发员工热情
  5. 额外参数_Redis的复制参数学习笔记
  6. android opencl sdk,在新的Android Studio中使用OpenCL
  7. 可行性研究报告模板 Shane版
  8. 微信小程序 抓css,微信小程序css篇
  9. Mybatis sql查不到数据
  10. 腾讯QQ大数据:机器学习建模问题中的特征构造方法
  11. python数据类型的应用
  12. 谷歌浏览器——默认搜索为百度
  13. 西游记孙悟空迅速从石猴飙升至斗战胜佛大罗金仙的辉煌人生旅程
  14. 杰力科创手持小风扇芯片——DLTAP703SC
  15. 关于移动端在cubeui中cube-scroll(以及better-scroll)里面写click会触发两次的问题
  16. Google浏览器打不开
  17. E. Boxers(贪心)
  18. GNSS定位原理(伪距)
  19. java框架基础教程_Java零基础教学,分分钟掌握基础学习框架
  20. 吃一堑长一智!mysql格式化查询结果

热门文章

  1. HDU-5723 Abandoned country
  2. 上周热点回顾(10.27-11.2)
  3. asp.net 页面刷新后,滚动条仍保持在原来的位置
  4. android java.lang.IllegalArgumentException: The observer is null.异常解决
  5. 解决方案:Error:Execution failed for task ‘:app:compileDebugAidl‘. > aidl is missing
  6. 解决:org.xml.sax.SAXParseException: 元素类型 “head“ 必须由匹配的结束标记 “</head>问题
  7. Failed to read schema document ‘http://code.alibabatech.com/schema/dubbo/dubbo.xsd‘问题解决方法
  8. docx.opc.exceptions.PackageNotFoundError: Package not found at ‘文件名.docx‘ 问题解决
  9. 返回,返回无,根本没有返回?
  10. 范围规则的简短描述?