逆向知识第十四讲,(C语言完结)结构体在汇编中的表现形式

一丶了解什么是结构体,以及计算结构体成员的对其值以及总大小(类也是这样算)

结构体的特性

  1.结构体(struct)是由一系列具有相同类型或不同类型的数据构成的数据集合

  2.在C语言中,结构体(struct)指的是一种数据结构,是C语言中聚合数据类型(aggregate data type)的一类。

3. 结构体可以被声明为变量指针数组等,用以实现较复杂的数据结构。结构体同时也是一些元素的集合,这些元素称为结构体的成员(member),且这些成员可以为不同的类型,成员一般用名字访问。[1]

高级代码:

   

  1. struct TagList
  2. {
  3. char ch;
  4. int number1;
  5. short int number2;
  6. double dbl;
  7. float flt;
  8. };

上面就是一个简单的结构体,那么我们这个结构体在内存中的偏移要怎么计算.

公式:

下面是推理,如果不想看可以直接跳到总结去看总结.

  成员偏移量的公式

alg  设alg是编译器的对其值,offset为结构体首地址的偏移,从0开始.

Member offset % min(alg,sizeof(member type) == 0; 这个公式是求成员位于结构体首地址的偏移

比如计算 成员 flt位与结构体首地址的偏移 ,要先从 第一个成员开始计算

设alg对齐值为4

offset % min(4,sizeof(ch)) == 0;

  0 % min(4,1) == 0  得出ch变量位于结构体首地址为0的偏移处,占1个字节      +0    1

offset % min(4,sizeof(number1)) == 0

  因为上面求出了ch占的大小,所以求出占1字节,所以偏移+1变为了1的位置

那么现在的offset = 1,继续代入公式

1 % min(4,4) == 0,不成立,偏移继续++

2%min(4,4) == 0,不成立,偏移继续++

.....

一直到偏移为4的时候满足,所以  偏移为4的地方,放number1             +4     4

计算 number2所在的偏移

offset % min(4,sizeof(member type)) == 0;

8 % min(4,2) == 0,成立                              +8     2

计算dbl所在的位置

offset % min(4,sizeof(member type)) == 0;

10 % (4,8) == 0,不成立

11%(4,8) == 0,不成立

12%(4,8) == 0;成立,所以在                           +12  8

计算float的位置

offset % min(4,sizeof(member type)) == 0;

20 % min(4,4) == 0;  成立                          +20 4

那么各成员的偏移已经计算出来了.

其中float成员位与结构体的 +20偏移,占4个字节大小.

计算结构体总体大小

  公式:

    

  sizeof(struct) % min( Max type size,alg);   

结构体的大小我们上面计算出来了,是 24个字节

MAX type,是结构体中最大成员的数据类型大小, 现在是double,也就是8个字节

alg是编译器对齐值,现在是4

所以代入公式得到

  24 % 4 == 6...0 

所以总体的大小是24个字节.

总结:

   编译器对齐值,设置为 alg, MeMber offset 从0开始计算, 其中Member offset 要每次代入公式之后,加上自己成员所占的字节大小,继续参与下次运算.

  设置或者查看编译器对其值, VC6.0版本   Project (工程)  -> Settings(设置) -> C/C++ -> Category(种类) -> Code Generation(代码生成) -> Struct  Member alignment(结构体对齐值)

  结构体成员偏移计算公式:  MeMber offset % min(alg,sizeof(Member type)) == 0

  结构体总大小计算公式:   sizeof(struct) % min(Max type size,alg) == 0;

程序内存查看.

根据内存窗口赋值,可以得出结构体成语位与结构体的偏移是多少

第一个成员,   +0 偏移位置, 占1个字节

第二个成员,   +4 偏移位置, 占4个字节

第三个成员    +8 偏移位置, 占2个字节

第四个成员 +12偏移位置,占8个字节

PS: 其中成员的Member offset 从零开始,当计算完毕之后,需要加上自己所占的字节大小,然后继续参与运算,如果运算不成立,则偏移继续增加,一直到偏移成立

比如:

  比如我们计算第二个成员位置的偏移

公式:

  Member offset % min(alg,sizeof(member type size) == 0;

  0 % 1 == 0   +0  放第一个成员

Member offset = Mmeber offset + 占的字节大小,(1)

求第二个成员位置

  1 % 4  ==0; 偏移为1的时候,不成立,则偏移继续增加

  2 % 4 == 0,不成立继续增加

  3 % 4 ==0,不成立继续增加

  4%4 == 0;成立,所以在 +4位置,方放4个字节,也就是第二个成员位置.

二丶结构体当做参数传递,为指针的情况下

  1. void MyFun(struct TagList *pThis)
  2. {
  3. pThis->ch = 'b';
  4.  
  5. }
  6. int main(int argc, char* argv[])
  7. {
  8. struct TagList text = {
  9. 'a',
  10. ,
  11. ,
  12. 3.14,
  13. 0.0
  14. };
  15.  
  16. MyFun(&text);
  17. printf("%d\r\n",text.number1);
  18. return ;
  19. }

Debug下的汇编代码

产生了寻址公式其中eax是数组首地址,ebp +8则是参数,外面传入的是结构体首地址,所以ebp +8则是数组首

 所以 ebp +8 则是结构体的首地址

mov byte ptr[eax],62h    这一句直接产生了 +0位置偏移,取内容赋值了字符

mov ecx,[ebp + 8]

mov dword ptr[ecx +4],2 这一句产生了 +4 偏移赋值为了2,所以可以确定

1.结构体首地址   ebp + 8 (参数1)

2.结构体第一个成员偏移  +0 赋值为字符

3.结构体第二个成员偏移 +4 赋值为2

Release下的汇编

main函数调用传递结构体地址的时候,只需要三行汇编

  1. lea eax,[esp + 20h + Var_20]
  2. push eax
  3. call MyFun

上面都是流水线优化的汇编

看下MyFun内部

其结构和Debug差不多

1.获得结构体的首地址

2.+0偏移位置赋值字符

3.+4偏移位置,赋值为2

三丶结构体当做参数传递,为结构体本身的的情况下

高级代码:

  

  1. void MyFun(struct TagList pThis)    //这个地方变了.不是指针了
  2. {
  3. pThis.ch = 'b';
  4. pThis.number1 = ;
  5.  
  6. }
  7. int main(int argc, char* argv[])
  8. {
  9. struct TagList text = {
  10. 'a',
  11. ,
  12. ,
  13. 3.14,
  14. 0.0
  15. };
  16.  
  17. MyFun(text);          //传参不用取地址了
  18. printf("%d\r\n",text.number1);
  19. return ;
  20. }

Debug下的汇编

传参之前的操作

很明显

1.先抬栈

2.循环6次,每次4个字节4个字节的拷贝

3.获得结构体的首地址

4.将栈顶赋值给edi,意思就是说,从栈顶开始复制.

5.执行串操作指令,rep movsd 将 esi的内容复制到栈顶位置处,

因为要复制 24个字节,所以栈顶要+24所以这一段就是存储结构体成员的.

MyFun内部

1. 经过传参之后,esp的位置为数组首地址的,也就是+0位置偏移处

2.进入函数后压入返回地址,那么栈 esp -4, 然后push ebp,继续esp -4

3.mov ebp,esp,保存寻址,现在的ebp + 8正好是外面我们进行串拷贝的时候的结构体的首地址.

4.mov byte ptr[ebp +8],62h,相当于就是给我们结构体成员的 +0成员赋值

5.mov dword ptr[ebp + 0ch],2 则正好是我们的第二个成员.

所以为了解释这两句汇编代码,需要通过外面传参的栈环境来看.

 Release下的汇编

和Debug下一样,也是要进行串拷贝

MyFun函数内部

发现我们没有使用,所以直接给优化了.

三丶函数返回值为结构体的时候

1.返回为指针的时候,直接放到eax中

返回值,为结构体的情况

三种情况

1.当结构体大小小于(4这个数不确定)个字节,直接用eax返回

2.当结构大小小于(8这个数不确定)个字节,直接用 edx,eax返回

3.当结构体大小大于 8个字节以上(不确定,视编译器而决定).

最后一种的高级代码:

  

  1. struct TagList MyFun()
  2. {
  3. struct TagList text =
  4. {
  5. 'a',
  6. ,
  7. ,
  8. 3.0,
  9. 4.0,
  10. };
  11. return text;
  12. }
  13. int main(int argc, char* argv[])
  14. {
  15. struct TagList text;
  16. text = MyFun();
  17. printf("%c\r\n",text.ch);
  18. return ;
  19. }

Debug下的汇编代码

1.我们的函数没有参数,但是Debug会生成上面的代码,传入进入, 为什么? 因为返回值eax等等都装不下了,所以利用这块内存区域当做返回值

2.函数退出之前,也会对它进行串操作指令,因为要返回这块内存区域,所以写入内存.

3.返回值以前会把首地址给 eax保存

4.看外面是否使用eax,如果使用可以可以判断返回的是一个对象,(当然这一步可以省略,但是上面的三步少一步都不是返回对象)

参数问题:

  它会默认给我们生成一个参数传入,那么我们有了参数,则会跟在后面.

Release汇编代码一样.

逆向知识第十四讲,(C语言完结)结构体在汇编中的表现形式的更多相关文章

  1. 二十四、V4L2框架主要结构体分析和虚拟摄像头驱动编写

    一.V4L2框架主要结构体分析 V4L2(video for linux version 2),是内核中视频设备的驱动框架,为上层访问视频设备提供统一接口. V4L2整体框架如下图: 图中主要包括两层 ...

  2. C语言 Struct 结构体在 Java 中的体现

    大一整个学期完成了 C 语言的学习,大二就进入了Java 的学习. 和C语言一样,我们都会尝试写一个小小的学生管理系统什么的,学习过 C 语言同学知道,在管理系统中 Struct 结构体是个很好用的东 ...

  3. 视觉slam学习之路(一)看高翔十四讲所遇到的问题

      目前实验室做机器人,主要分三个方向,定位导航,建图,图像识别,之前做的也是做了下Qt上位机,后面又弄红外识别,因为这学期上课也没怎么花时间在项目,然后导师让我们确定一个方向来,便于以后发论文什么. ...

  4. 高翔《视觉SLAM十四讲》从理论到实践

    目录 第1讲 前言:本书讲什么:如何使用本书: 第2讲 初始SLAM:引子-小萝卜的例子:经典视觉SLAM框架:SLAM问题的数学表述:实践-编程基础: 第3讲 三维空间刚体运动 旋转矩阵:实践-Ei ...

  5. 《视觉SLAM十四讲》第1讲

    目录 一 视觉SLAM 注:原创不易,转载请务必注明原作者和出处,感谢支持! 一 视觉SLAM 什么是视觉SLAM? SLAM是Simultaneous Localization and Mappin ...

  6. 浅读《视觉SLAM十四讲:从理论到实践》--操作1--初识SLAM

    下载<视觉SLAM十四讲:从理论到实践>源码:https://github.com/gaoxiang12/slambook 第二讲:初识SLAM 2.4.2 Hello SLAM(书本P2 ...

  7. 高博-《视觉SLAM十四讲》

    0 讲座 (1)SLAM定义 对比雷达传感器和视觉传感器的优缺点(主要介绍视觉SLAM) 单目:不知道尺度信息 双目:知道尺度信息,但测量范围根据预定的基线相关 RGBD:知道深度信息,但是深度信息对 ...

  8. 《SLAM十四讲》个人学习知识点梳理

    0.引言 从六月末到八月初大概一个月时间一直在啃SLAM十四讲[1]这本书,这本书把SLAM中涉及的基本知识点都涵盖了,所以在这里做一个复习,对这本书自己学到的东西做一个梳理. 书本地址:http:/ ...

  9. Stanford机器学习---第十四讲.机器学习应用举例之Photo OCR

    http://blog.csdn.net/l281865263/article/details/50278745 本栏目(Machine learning)包括单参数的线性回归.多参数的线性回归.Oc ...

随机推荐

  1. 赋值运算符函数__from <剑指Offer>

    前段时间忙于项目,难得偷得几日闲,为即将到来的就业季做准备.在面试时,应聘者要注意多和考官交流,只有具备良好的沟通能力,才能充分了解面试官的需求,从而有针对性地选择算法解决问题. 题目来源于<剑 ...

  2. spark-shell启动报错:Yarn application has already ended! It might have been killed or unable to launch application master

    spark-shell不支持yarn cluster,以yarn client方式启动 spark-shell --master=yarn --deploy-mode=client 启动日志,错误信息 ...

  3. eclipse查看类源码出现failed to create the part's controls的解决方法

    刚装好eclipse和Tomcat ,在看准备使用的一个开源框架jeesite,可是在查看源代码的时候出现这个问题

  4. 【前端】主流API-promise解析,js基础。

    前言 在js领域,promise出现的时间已经很久了,从jquery的$.get().done().fail() 这样的API开始,到现在的es6默认支持的new Promise(),它的出现无疑使异 ...

  5. django 实现登录时候输入密码错误5次锁定用户十分钟

    在学习django的时候,想要实现登录失败后,进行用户锁定,切记录锁定时间,在网上找了很多资料,但是都感觉不是那么靠谱, 于是乎,我开始了我的设计,其实我一开始想要借助redis呢,但是想要先开发一个 ...

  6. QT生成PDF文件

    QString temp=""; //m_File_Content_Text_Edit->selectAll(); QString t_File_Content = m_Fi ...

  7. CodeForces 11D(状压DP 求图中环的个数)

    Given a simple graph, output the number of simple cycles in it. A simple cycle is a cycle with no re ...

  8. code force 424 A - Office Keys

    There are n people and k keys on a straight line. Every person wants to get to the office which is l ...

  9. Fibonacci again and again(SG函数应用)

    Fibonacci again and again Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/O ...

  10. 流式计算storm,spark文章

    使用Storm实现实时大数据分析!http://www.csdn.net/article/2012-12-24/2813117-storm-realtime-big-data-analysis     ...