【多级指针】带你从反汇编角度认识指针,C语言指针,多级指针【滴水逆向三期(36)笔记】(下)

简介: 【多级指针】带你从反汇编角度认识指针,C语言指针,多级指针【滴水逆向三期(36)笔记】(下)
3. *( *(p2+1)+1)反汇编
//C语言代码:
short** p2;
printf("%d",*(*(p2+1)+1));

我们还是直接来到反汇编窗口来观察:

//反汇编代码:
mov         eax,dword ptr [ebp-4]
mov         ecx,dword ptr [eax+4]
movsx       edx,word ptr [ecx+2]

大家可以从下面这张图中来理解:

该图中,蓝色为未作任何操作时二级指针示意图,较细箭头为给p2+1时的指向,加粗箭头为最终指向

我们来逐步分析对*( *(p2+1)+1)取值的过程:

1.首先取出指针变量p2中存取的数据,放入eax

2.将eax内存放的数据当作地址,在该地址基础上+4,取出该地址内存放的数据,放入ecx(第一次取出的数据,是一个地址,指向第一个一级指针,如图所示,将二级指针+1,实际上就是要指向本来要指向的一级指针(一级指针1)的下一个(一级指针2),由于一级指针占据4个字节,所以要在二级指针内存放的数据+4(4 * 1))

3.将ecx中的值+2,再当作一个地址,取出该地址中存放的数据,放入edx(由于一级指针2本来指向的是数据2(short类型,占据2字节),所以要在一级指针内存放的地址上+2(2 * 1))

4. *( *(p2+2)+3)

这里其实是前三个的运用,为了加深理解,我们来定义char**类型的二级指针。

//C语言代码
char** p2;
printf("%d",*(*(p2+2)+3));
//反汇编代码
mov         eax,dword ptr [ebp-4]
mov         ecx,dword ptr [eax+8]
movsx       edx,byte ptr [ecx+3]

我们继续以画内存图的方式来为大家讲解:

该图中蓝色箭头为二级指针未作任何操作时的指向,较细橙色箭头为对二级指针操作后的指向,较粗箭头为对一级指针操作后的指向。

我们来逐步分析对*( *(p2+2)+3)取值的过程

1.取出二级指针变量p2中的数据,放入eax中

2.将eax中的值+8,将得到的值看作地址,取出该地址中存放的数据,放入ecx(第一次取出的地址指向一级指针,所以对二级指针+2的操作实际上是让改二级指针指向原本指向的一级地址再向后便宜两个一级指针,所以就是二级指针内存放的数据+8(4 * 2))

3.将ecx中的值+3,将得到的值看作地址,取出该地址内存取的数据,放入edx(由于ecx内存取的是一个地址(可以看作一级指针),指向char类型的数据,所以对一级指针+3的操作实际上是对一级指针内存放的数据+3(3 * 1))。

三级指针

我们先来了解一下三级指针:

//C语言代码:
char a=1;
char* p1=&a;
char** p2=&p1;
char*** p3=&p2;

这里我们定义一个char类型的变量a,定义一个char*类型的变量(一级指针)p1存放a的地址,定义一个char * *类型的变量(二级指针)存放p1的地址,再定义一个char * * *类型的变量存(三级指针)放p2的地址。

//反汇编代码:
mov         byte ptr [ebp-4],1
lea         eax,[ebp-4]
mov         dword ptr [ebp-8],eax
lea         ecx,[ebp-8]
mov         dword ptr [ebp-0Ch],ecx
lea         edx,[ebp-0Ch]
mov         dword ptr [ebp-10h],edx

根据反汇编分析:

将1存进a[ebp-4]中

将a[ebp-4]的地址存入eax,将eax存入p1[ebp-8]中————>一级指针

将p1[ebp-8]的地址存入ecx,将ecx存入p2[ebp-0ch]—————>二级指针

将p2[ebp-0ch]的地址存入edx,将edx存入p3[ebp-10h]——————>三级指针

1. 数据宽度

我们通过C语言sizeof函数可以得到三级指针所占据的数据宽度:

char*** a;
printf("%d",sizeof(a);

我们可以看到在程序输出框里输出:

4

所以三级指针占据4个字节存储空间,在C语言编译器中,我们有数据类型之分,但是实际在电脑内存中,内存条根本没有数据类型之分,它只负责存储数据。

2. 三级指针++,–,加或减一个整数运算

//C语言代码:
char*** a=(char***)100;
printf("%d",a++);

我们能够观察到在程序输出窗口输出:

104

char ***内存储的是一个char **类型变量的地址,对char ***类型+1,实际上是要char ***指向原本指向数据的下一个数据,而char **类型占据4个字节,所以要在原本char ***基础上+4(4 * 1)。

反汇编代码:

//反汇编代码:
mov         dword ptr [ebp-4],64h
mov         eax,dword ptr [ebp-4]
add         eax,4

我们来分析整个过程:

定义了一个char ***类型的变量,通过强制转换类型将100转换为char ***类型。然后对该变量里存储的值+4(在内存并不认为它是地址,只是编译器和我们认为它是地址,内存只负责存储,在内存眼里所有数据都一样)。

3. 三级指针反汇编

1. *(*p3)反汇编

C语言代码:

char*** p3;
printf("%d",*(*p3));

我们知道在带 *的数据类型前面加 *得到的数据类型就是原本的类型去掉一个 *,所以我们这里取到了一级指针,并没有取到一级指针所指的空间里所存储的数据。

反汇编代码:

mov         eax,dword ptr [ebp-4]
mov         ecx,dword ptr [eax]
mov         edx,dword ptr [ecx]

我们来逐步分析对*(*p3)取值的过程:

1.取出变量pa[ebp-4]内存储的数据,放入eax

2.将eax中的数据当作地址,取出该地址内存储的数据,放入ecx

3.将ecx中的数据当作地址,取出该地址中存储的数据,放入edx

2. *( *(*p3))反汇编

C语言代码:

char*** p3;
printf("%d",*(*(*p3)));

反汇编代码:

mov         eax,dword ptr [ebp-4]
mov         ecx,dword ptr [eax]
mov         edx,dword ptr [ecx]
movsx       eax,byte ptr [edx]

我们来逐步分析对*( *(*p3))取值的过程:

1.取出p3[ebp-4]中的数据,放入寄存器eax

2.将寄存器eax中存储的数据当作地址,取出该地址中存储的数据,放入寄存器ecx

3.将寄存器ecx中存储的数据当作地址,取出该地址中存储的数据,放入寄存器edx

4.将寄存器edx中存储的数据当作地址,取出该地址中存储的数据,放入寄存器eax

3. *( *( *( *p3+1)+2)+3)反汇编

C语言代码:

char*** p3;
printf("%d",*(*(*(p3+1)+2)+3));

反汇编代码:

mov         eax,dword ptr [ebp-4]
mov         ecx,dword ptr [eax+4]
mov         edx,dword ptr [ecx+8]
movsx       eax,byte ptr [edx+3]

我们来逐步分析对 *( *( *(p3+1)+2)+3)取值的过程:

由于此过程有点繁琐,我才用画内存图的方法带大家了解:

图中,蓝色箭头为未作任何操作时,三级指针的分别指向,较细橙色箭头为+1操作后三级指针指向的变化,较粗橙色箭头为+2操作后二级指针指向变化,绿色箭头为+3操作后一级指针指向的不安话

1.取出p3[ebp-4]中的数据,放入寄存器eax

2.将eax中存放的数据+4后当作地址,取出该地址中存放的数据,放入寄存器ecx(因为给变量p3本身+1,就是要三级指针指向原本指向的下一个数据,而三级指针指向的是二级指针类型,占据4个字节,所以给三级指针+1的操作事实上是给三级指针内存放的数据+4(4 * 1)

3.将寄存器ecx中的值+8后当作地址,取出该地址中存放的数据,放入寄存器edx(给二级指针+2的操作,就是要二级指针指向原本指向数据向再后偏移2个数据,所以事实上就是给二级指针内存放的数据+8(4 * 2)

4.将寄存器edx中存放的值+3后当作地址,取出该地址中存放的数据,放入寄存器eax(给一级指针+3的操作,就是要让指针指向原本指向数据再向后偏移三个数据,而此一级指针指向的数据为char类型,所以给该一级指针+3的操作,事实上是给该一级指针内存放的数据+3(1 * 3)

4. p3[1][2][3]反汇编

C语言代码:

char*** p3;
printf("%d",p3[1][2][3]);

反汇编代码:

mov         eax,dword ptr [ebp-4]
mov         ecx,dword ptr [eax+4]
mov         edx,dword ptr [ecx+8]
movsx       eax,byte ptr [edx+3]

我们来与*( *( *(p3+1)+2)+3的反汇编代码做个比较,发现它俩的反汇编代码竟惊人地相同!

在讲二级指针时我们已经讲过这个知识点,我们在这里就不再啰嗦了。

直接给出结论:

*(*(*(*(*(p+m) +n) +i) +j) +k)与p[m][n][i][j][k]可以互换

OK今天我们就学习到这里,当然希望大家可以指出此篇笔记的不足或者错误之处,当然希望我们能够共同学习,共同进步!!!

相关文章
|
5天前
|
安全 C语言
【C语言】如何规避野指针
【C语言】如何规避野指针
14 0
|
6天前
|
C语言
C语言:数组和指针笔试题解析(包括一些容易混淆的指针题目)
C语言:数组和指针笔试题解析(包括一些容易混淆的指针题目)
|
20天前
|
存储 程序员 编译器
爱上C语言:指针很难?来来来,看看这篇(基础篇)
爱上C语言:指针很难?来来来,看看这篇(基础篇)
|
1天前
|
存储 程序员 C语言
【C 言专栏】C 语言指针的深度解析
【4月更文挑战第30天】C 语言中的指针是程序设计的关键,它如同一把钥匙,提供直接内存操作的途径。指针是存储其他变量地址的变量,通过声明如`int *ptr`来使用。它们在动态内存分配、函数参数传递及数组操作中发挥重要作用。然而,误用指针可能导致错误,如空指针引用和内存泄漏。理解指针的运算、与数组和函数的关系,以及在结构体中的应用,是成为熟练 C 语言程序员的必经之路。虽然挑战重重,但掌握指针将增强编程效率和灵活性。不断实践和学习,我们将驾驭指针,探索更广阔的编程世界。
|
2天前
|
算法 搜索推荐 程序员
C语言中的函数指针和回调函数
C语言中的函数指针和回调函数
9 2
|
5天前
|
存储 编译器 C语言
【C语言】初步解决指针疑惑
【C语言】初步解决指针疑惑
6 0
|
6天前
|
存储 C语言
指针深入解析(C语言基础)带你走进指针,了解指针
指针深入解析(C语言基础)带你走进指针,了解指针
|
6天前
|
C语言 C++
C语言:指针运算笔试题解析(包括令人费解的指针题目)
C语言:指针运算笔试题解析(包括令人费解的指针题目)
|
8天前
|
存储 安全 编译器
C语言怎样定义指针变量
C语言怎样定义指针变量
7 0
|
8天前
|
安全 C语言
指针与字符串:C语言中的深入探索
指针与字符串:C语言中的深入探索
14 0