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

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

结构体的特性

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

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

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

高级代码:

struct TagList
{
    char ch;
    int  number1;
    short int number2;
    double dbl;
    float flt;
}; 

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

公式:

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

成员偏移量的公式

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个字节,也就是第二个成员位置.

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

void MyFun(struct TagList *pThis)
{
    pThis->ch = ‘b‘;

}
int main(int argc, char* argv[])
{
    struct TagList text = {
    ‘a‘,
    1,
    2,
    3.14,
    0.0
    };

    MyFun(&text);
    printf("%d\r\n",text.number1);
    return 0;
}

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函数调用传递结构体地址的时候,只需要三行汇编

lea eax,[esp + 20h + Var_20]
push eax
call MyFun

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

看下MyFun内部

其结构和Debug差不多

1.获得结构体的首地址

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

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

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

高级代码:

void MyFun(struct TagList pThis)    //这个地方变了.不是指针了
{
    pThis.ch = ‘b‘;
    pThis.number1 = 2;

}
int main(int argc, char* argv[])
{
    struct TagList text = {
    ‘a‘,
    1,
    2,
    3.14,
    0.0
    };

    MyFun(text);          //传参不用取地址了
    printf("%d\r\n",text.number1);
    return 0;
}

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个字节以上(不确定,视编译器而决定).

最后一种的高级代码:

struct TagList MyFun()
{
    struct TagList text  =
    {
        ‘a‘,
        1,
        2,
        3.0,
        4.0,
    };
    return text;
}
int main(int argc, char* argv[])
{
    struct TagList text;
    text = MyFun();
    printf("%c\r\n",text.ch);
    return 0;
}

Debug下的汇编代码

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

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

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

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

参数问题:

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

Release汇编代码一样.

转载于:

作者:IBinary
出处:http://www.cnblogs.com/iBinary/

原文地址:https://www.cnblogs.com/gd-luojialin/p/11219889.html

时间: 2024-10-11 19:53:05

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

CV学习资料《卷积神经网络与视觉计算》+《深度学习实践计算机视觉》+《视觉SLAM十四讲从理论到实践》电子资料代码分析

视觉和图形学真是一家,基础都一样! 如果学习图像识别,计算机视觉,推荐电子书<视觉SLAM十四讲:从理论到实践>,系统介绍了视觉SLAM(同时定位与地图构建)所需的基本知识与核心算法,既包括数学理论基础,如三维空间的刚体运动.非线性优化,又包括计算机视觉的算法实现,例如多视图几何.回环检测等. 一个周读完了,代码很清晰!Particle Filtering,KF,EKF, Batch Optimization, Lie Group,ICP,LK光流... 尤其惊喜的是文末作者看好的IMU-SL

《上古天真论》第十四讲文字版

上古天真论篇第十四讲 主讲:徐文兵  主持:梁  冬 播出时间:2009-03-14  23:00—24:00 经文:季以恬愉为务,以自得为功,形体不敝,精神不散,亦可以百数.其次有贤人者,法则天地,象似日月,辨列星辰,逆从阴阳,分别四时,将从上古合同于道,亦可使益寿而有极时. 梁冬:是的,重新发现中医太美,大家好!欢迎收听在这么晚,晚上十一点,坚持收听国学堂之重新发现中医太美,非常感谢!也同时呢,感谢我们今天的徐老师来到我们今天的演播室,徐老师你好!徐文兵:梁冬好!听众朋友们大家好!梁冬:是的

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

目前实验室做机器人,主要分三个方向,定位导航,建图,图像识别,之前做的也是做了下Qt上位机,后面又弄红外识别,因为这学期上课也没怎么花时间在项目,然后导师让我们确定一个方向来,便于以后发论文什么.上个礼拜看了些论文,感觉视觉slam方向还可以,图像识别毕竟不是计算机科班,可能真正要弄也很难有成果,slam也是最近才研究起来,也挺适合我们搞,需要一些高数.c++.ros等知识,学的东西也挺多的,但这样才能体现研究生的价值,不然本科生也能做,然后确定了这个研究方向,希望好好研究个一两年有所成就,研三

视觉SLAM十四讲随笔

**************************************************************************************************************************************************ch1:clion的使用 断点设置之后,逐行执行 (Step Into) ( F7 ),逐函数执行 (Step Over) ( F8 ),注意0和O在clion中的显示区别,0是中间有个点的 O看起来像0,中

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

http://blog.csdn.net/l281865263/article/details/50278745 本栏目(Machine learning)包括单参数的线性回归.多参数的线性回归.Octave Tutorial.Logistic Regression.Regularization.神经网络.机器学习系统设计.SVM(Support Vector Machines 支持向量机).聚类.降维.异常检测.大规模机器学习等章节.内容大多来自Standford公开课machine lear

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

下载<视觉SLAM十四讲:从理论到实践>源码:https://github.com/gaoxiang12/slambook 第二讲:初识SLAM 2.4.2 Hello SLAM(书本P27) 1.从github上下载源码,并解压 Ubuntu上,解压zip,先找到zip文件所在位置,然后运行下面代码,进行解压. unzip slambook-master.zip 解压后,找到ch2文件夹,在文件夹中找到helloSLAM.cpp文件 运行cpp文件 g++ helloSLAM.cpp 如未安

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

0.引言 从六月末到八月初大概一个月时间一直在啃SLAM十四讲[1]这本书,这本书把SLAM中涉及的基本知识点都涵盖了,所以在这里做一个复习,对这本书自己学到的东西做一个梳理. 书本地址:http://www.broadview.com.cn/book/4938 书本代码:https://github.com/gaoxiang12/slambook 1.SLAM概述 SLAM:即时定位与地图构建(Simultaneous Localization and Mapping) 数学描述: 一个典型的

《视觉slam十四讲》之第3讲-实践Eigen库

<视觉slam十四讲>之第3讲-实践Eigen库 Eigen库的安装 sudo apt-get install libeigen3-dev 注:Eigen是一个由纯头文件搭建的线性代数库,头文件安装路径为/usr/include/eigen3/. 实例1:Eigen的基础运算 #include <iostream> #include <ctime> #include <Eigen/Core> // Eigen 部分 #include <Eigen/De

入门实战《深度学习技术图像处理入门》+《视觉SLAM十四讲从理论到实践》

学习图像识别处理,想在数据分析竞赛中取得较高的排名,看了<深度学习技术图像处理入门>电子书,一边看电子书一边做标记,对配套的代码也做了测试,收获颇多. 从机器学习.图像处理的基本概念入手,逐步阐述深度学习图像处理技术的基本原理以及简单的实现. 学习理论后做实验,使用卷积神经网络进行端到端学习,构建深度卷积神经网络,使用循环神经网络改进模型,评估模型,测试模型.最关键的是可以将模型运用于实战之中,将深度学习模型导入到工程中,数据类型转换函数,实施CAM可视化,这是我最需要的. 视觉和图形学真是一