您的位置:首页 > 理论基础 > 数据结构算法

《coredump问题原理探究》Linux x86版5.7节C风格数据结构内存布局之结构体数组

2013-04-22 21:35 501 查看
在探究过数组和结构体这两种非原生的数据类型之后,可能会想知道这两种类型结合成结构体数组,会有什么特征。

先看一个例子:

#include <stdlib.h>
struct xuzhina_dump_c05_s3_3
{
short idx;
int sq;
};

void init( struct xuzhina_dump_c05_s3_3* test, int n )
{
for ( int i = 0; i < n; i++ )
{
test[i].idx = i;
test[i].sq = i*i;
}
}

int sum( struct xuzhina_dump_c05_s3_3* test, int n )
{
int sum = 0;
for ( int i = 0; i < n; i++ )
{
sum += test[i].sq;
}
return sum;
}

int main(int argc, char* argv[] )
{
if ( argc < 2 )
{
return 1;
}

int num = atoi( argv[1] );

struct xuzhina_dump_c05_s3_3* test =
(struct xuzhina_dump_c05_s3_3*)malloc( num * sizeof( struct xuzhina_dump_c05_s3_3 ) );

init( test, num );

return sum( test, num );
}

汇编(只看init和sum即可)

(gdb) disassemble init
Dump of assembler code for function _Z4initP21xuzhina_dump_c05_s3_3i:
0x080484d0 <+0>:     push   %ebp
0x080484d1 <+1>:     mov    %esp,%ebp
0x080484d3 <+3>:     sub    $0x10,%esp
0x080484d6 <+6>:     movl   $0x0,-0x4(%ebp)		;i
0x080484dd <+13>:    jmp    0x8048511 <_Z4initP21xuzhina_dump_c05_s3_3i+65>

0x080484df <+15>:    mov    -0x4(%ebp),%eax
0x080484e2 <+18>:    lea    0x0(,%eax,8),%edx		;edx = i*8
0x080484e9 <+25>:    mov    0x8(%ebp),%eax		;eax = test
0x080484ec <+28>:    add    %eax,%edx				;edx = test[i]
0x080484ee <+30>:    mov    -0x4(%ebp),%eax		;i
0x080484f1 <+33>:    mov    %ax,(%edx)			;test[i].idx = i
0x080484f4 <+36>:    mov    -0x4(%ebp),%eax		;i
0x080484f7 <+39>:    lea    0x0(,%eax,8),%edx		;edx = i*8
0x080484fe <+46>:    mov    0x8(%ebp),%eax		;eax = test
0x08048501 <+49>:    add    %eax,%edx				;edx = test[i]
0x08048503 <+51>:    mov    -0x4(%ebp),%eax		;eax = i
0x08048506 <+54>:    imul   -0x4(%ebp),%eax		;eax *= i
0x0804850a <+58>:    mov    %eax,0x4(%edx)		;test[i].sq = eax
0x0804850d <+61>:    addl   $0x1,-0x4(%ebp)			;i++
0x08048511 <+65>:    mov    -0x4(%ebp),%eax
0x08048514 <+68>:    cmp    0xc(%ebp),%eax
0x08048517 <+71>:    setl   %al
0x0804851a <+74>:    test   %al,%al
0x0804851c <+76>:    jne    0x80484df <_Z4initP21xuzhina_dump_c05_s3_3i+15>

0x0804851e <+78>:    leave
0x0804851f <+79>:    ret
End of assembler dump.

(gdb) disassemble sum
Dump of assembler code for function _Z3sumP21xuzhina_dump_c05_s3_3i:
0x08048520 <+0>:     push   %ebp
0x08048521 <+1>:     mov    %esp,%ebp
0x08048523 <+3>:     sub    $0x10,%esp
0x08048526 <+6>:     movl   $0x0,-0x4(%ebp)		;sum
0x0804852d <+13>:    movl   $0x0,-0x8(%ebp)		;i
0x08048534 <+20>:    jmp    0x804854f <_Z3sumP21xuzhina_dump_c05_s3_3i+47>

0x08048536 <+22>:    mov    -0x8(%ebp),%eax		;i
0x08048539 <+25>:    lea    0x0(,%eax,8),%edx
0x08048540 <+32>:    mov    0x8(%ebp),%eax		;test
0x08048543 <+35>:    add    %edx,%eax
0x08048545 <+37>:    mov    0x4(%eax),%eax		;test[i].sq
0x08048548 <+40>:    add    %eax,-0x4(%ebp)
0x0804854b <+43>:    addl   $0x1,-0x8(%ebp)			;i++
0x0804854f <+47>:    mov    -0x8(%ebp),%eax
0x08048552 <+50>:    cmp    0xc(%ebp),%eax		;i < n
0x08048555 <+53>:    setl   %al
0x08048558 <+56>:    test   %al,%al
0x0804855a <+58>:    jne    0x8048536 <_Z3sumP21xuzhina_dump_c05_s3_3i+22>

0x0804855c <+60>:    mov    -0x4(%ebp),%eax
0x0804855f <+63>:    leave
0x08048560 <+64>:    ret
End of assembler dump.

从上面的汇编,结构体数组的特征如下:

1.        先是找到数组的首地址

2.        再根据索引找到每个元素,得到每个元素的地址。

3.        再以每个元素的地址作为结构体基址,再获取成员变量的地址。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐