《coredump问题原理探究》Linux x86版5.5节C风格数据结构内存布局之基本数据类型构成的结构体
来源:互联网 发布:matlab行程01矩阵 编辑:程序博客网 时间:2024/05/08 19:52
在C语言里,结构体是不同类型数据结构的集合。由于结构体比较复杂,分为几种情况来讨论:
1. 成员全是由基本数据类型构成
2. 成员有基本数据类型,也有其它结构体构成,构成成员的结构体是1,2两种情况。
3. 结构体构成的数组
这一节先讨论第一种情况.要了解这种类型结构体的内存布局,首先要知道成员在内存里是如何排序,及各个成员在内存占的大小。先看一个例子
#include <stdio.h> struct xuzhina_dump_c05_s3_stru { char a; short b; int c; long d; float e; double f; void* g; }; int main() { struct xuzhina_dump_c05_s3_stru test; printf( "addr:%x, 1st:%x, 2nd:%x, 3rd:%x, 4th:%x, 5th:%x, 6th:%x, 7th:%x ", &test, &test.a, &test.b, &test.c, &test.d, &test.e, &test.f, &te st.g ); return 0; }
运行结果:
addr:bf909eb4, 1st:bf909eb4, 2nd:bf909eb6, 3rd:bf909eb8, 4th:bf909ebc, 5th:bf909ec0, 6th:bf909ec4, 7th:bf909ecc
可得这样的结论:
1. 结构体对象的地址和第一个成员地址一样。也就是所谓的基地址
2. 第一个成员a和第二个成员b分别是char,short,不足dword大小,为了内存对齐,挤一个dword里。int, long, float, double,指针由于大小分别是4,4,4,8,4,直接按照4字节进行内存对齐,也分别占4,4,4,8,4个字节的空间.
3. 各个成员还是按照结构体的声明顺序由低到高排列。
4. 每个成员的地址都是它前面所有成员的大小(包括内存对齐)和基地址的累加。像test.d的地址就是bf909eb4+0x8 = bf909ebc.它前面的成员a ,b在一个dword, c占一个dword,刚好是8.
可能成员类型会由于内存对齐而分辨不出来。其实,用5.1节的方法是可以分辨得出来。有兴趣可以尝试一下。
那么一个结构体如何从汇编里识别出来呢,它究竟有什么特征?
先看一下这个例子。
struct xuzhina_dump_c05_s3_stru { char a; short b; int c; }; bool equal( struct xuzhina_dump_c05_s3_stru* first, struct xuzhina_dump_c05_s3_stru* second ) { if ( first->a != second->a ) { return false; } if ( first->b != second->b ) { return false; } if ( first->c != second->c ) { return false; } return true; } int main() { struct xuzhina_dump_c05_s3_stru first = { 'a', 10, 20 }; struct xuzhina_dump_c05_s3_stru second = {'a', 10, 21 }; if ( equal( &first, &second ) ) { return 0; } return 1; }
汇编代码
(gdb) disassemble equal Dump of assembler code for function _Z5equalP24xuzhina_dump_c05_s3_struS0_: 0x08048470 <+0>: push %ebp 0x08048471 <+1>: mov %esp,%ebp 0x08048473 <+3>: mov 0x8(%ebp),%eax 0x08048476 <+6>: movzbl (%eax),%edx 0x08048479 <+9>: mov 0xc(%ebp),%eax 0x0804847c <+12>: movzbl (%eax),%eax 0x0804847f <+15>: cmp %al,%dl 0x08048481 <+17>: je 0x804848a <_Z5equalP24xuzhina_dump_c05_s3_struS0_+26> 0x08048483 <+19>: mov $0x0,%eax 0x08048488 <+24>: jmp 0x80484c0 <_Z5equalP24xuzhina_dump_c05_s3_struS0_+80> 0x0804848a <+26>: mov 0x8(%ebp),%eax 0x0804848d <+29>: movzwl 0x2(%eax),%edx 0x08048491 <+33>: mov 0xc(%ebp),%eax 0x08048494 <+36>: movzwl 0x2(%eax),%eax 0x08048498 <+40>: cmp %ax,%dx 0x0804849b <+43>: je 0x80484a4 <_Z5equalP24xuzhina_dump_c05_s3_struS0_+52> 0x0804849d <+45>: mov $0x0,%eax 0x080484a2 <+50>: jmp 0x80484c0 <_Z5equalP24xuzhina_dump_c05_s3_struS0_+80> 0x080484a4 <+52>: mov 0x8(%ebp),%eax 0x080484a7 <+55>: mov 0x4(%eax),%edx 0x080484aa <+58>: mov 0xc(%ebp),%eax 0x080484ad <+61>: mov 0x4(%eax),%eax 0x080484b0 <+64>: cmp %eax,%edx 0x080484b2 <+66>: je 0x80484bb <_Z5equalP24xuzhina_dump_c05_s3_struS0_+75> 0x080484b4 <+68>: mov $0x0,%eax 0x080484b9 <+73>: jmp 0x80484c0 <_Z5equalP24xuzhina_dump_c05_s3_struS0_+80> 0x080484bb <+75>: mov $0x1,%eax 0x080484c0 <+80>: pop %ebp 0x080484c1 <+81>: ret End of assembler dump.(gdb) disassemble mainDump of assembler code for function main: 0x080484c2 <+0>: push %ebp 0x080484c3 <+1>: mov %esp,%ebp 0x080484c5 <+3>: sub $0x18,%esp 0x080484c8 <+6>: movb $0x61,-0x8(%ebp) 0x080484cc <+10>: movw $0xa,-0x6(%ebp) 0x080484d2 <+16>: movl $0x14,-0x4(%ebp) 0x080484d9 <+23>: movb $0x61,-0x10(%ebp) 0x080484dd <+27>: movw $0xa,-0xe(%ebp) 0x080484e3 <+33>: movl $0x15,-0xc(%ebp) 0x080484ea <+40>: lea -0x10(%ebp),%eax 0x080484ed <+43>: mov %eax,0x4(%esp) 0x080484f1 <+47>: lea -0x8(%ebp),%eax 0x080484f4 <+50>: mov %eax,(%esp) 0x080484f7 <+53>: call 0x8048470 <_Z5equalP24xuzhina_dump_c05_s3_struS0_> 0x080484fc <+58>: test %al,%al 0x080484fe <+60>: je 0x8048507 <main+69> 0x08048500 <+62>: mov $0x0,%eax 0x08048505 <+67>: jmp 0x804850c <main+74> 0x08048507 <+69>: mov $0x1,%eax 0x0804850c <+74>: leave 0x0804850d <+75>: ret End of assembler dump.
从equal函数的汇编代码可以看到,
1. 结构体都是一个基地址,从它三个成员的寻址看到,都是先把基地址放到某寄存器里。如mov 0x8(%ebp),%eax
2. 结构体成员的访问,都在基址基础上加上前面所有成员的大小。如成员c,前面a和b占四个字节,所以就有“mov 0x8(%ebp),%eax”, “mov 0x4(%eax),%edx”.
3. 每个成员与基址的偏移量,不是构成一个等差数列。
- 《coredump问题原理探究》Linux x86版5.5节C风格数据结构内存布局之基本数据类型构成的结构体
- 《coredump问题原理探究》Linux x86版5.6节C风格数据结构内存布局之复合类型构成的结构体
- 《coredump问题原理探究》Linux x86版5.2节C风格数据结构内存布局之基本数据类型
- 《coredump问题原理探究》Linux x86版5.7节C风格数据结构内存布局之结构体数组
- 《coredump问题原理探究》Linux x86版5.8节C风格数据结构内存布局之结构体数组结构体coredump
- 《coredump问题原理探究》Linux x86版5.1节C风格数据结构内存布局之引言
- 《coredump问题原理探究》Linux x86版5.3节C风格数据结构内存布局之数组
- 《coredump问题原理探究》Linux x86版5.9节C风格数据结构内存布局之联合体
- 《coredump问题原理探究》Linux x86版5.4节C风格数据结构内存布局之数组coredump例子
- 《coredump问题原理探究》Linux x86版6.1节C++风格数据结构内存布局之无成员变量的类
- 《coredump问题原理探究》Linux x86版6.2节C++风格数据结构内存布局之有成员变量的类
- 《coredump问题原理探究》Linux x86版3.8节栈布局之栈溢出coredump例子
- 《coredump问题原理探究》Linux x86版4.2节函数的逆向之顺序结构
- 《coredump问题原理探究》Linux x86版4.3节函数的逆向之条件结构
- 《coredump问题原理探究》Linux x86版4.4节函数的逆向之循环结构
- 《coredump问题原理探究》Linux x86版4.5节函数的逆向之coredump例子
- 《coredump问题原理探究》Linux x86版3.1节栈布局之概述
- 《coredump问题原理探究》Linux x86版3.2节栈布局之函数桢
- 国内外常用的分享按钮
- S3C6410 SD卡启动uboot分析(详细)
- 内核头文件
- 计算机的“层”概念
- SQL Server 2000架构
- 《coredump问题原理探究》Linux x86版5.5节C风格数据结构内存布局之基本数据类型构成的结构体
- Linux安装Eclipse
- voip 视频丢包处理相关RFC
- 第四次程序设计作业
- WriteOS: 制作一个 Boot Sector 并使用 Bochs 进行调试
- linux uboot 启动顺序
- 排列与组合读书笔记
- CF - 118A - String Task
- 期末考试题