反汇编:指针数组和数组指针

前言:作为指针数组和数组指针的学习

指针数组

第一种写法

代码如下:

#include<stdio.h>

int main(){
	//指针数组
	char arr[3][10] = {
		"aaaaa",
		"bbbbb",
		"ccccc"
	};

	printf("%s",arr[1]);
}

反汇编如下:

0040D440 >/> \55            PUSH EBP
0040D441  |.  8BEC          MOV EBP,ESP
0040D443  |.  83EC 60       SUB ESP,60
0040D446  |.  53            PUSH EBX
0040D447  |.  56            PUSH ESI
0040D448  |.  57            PUSH EDI
0040D449  |.  8D7D A0       LEA EDI,DWORD PTR SS:[EBP-60]
0040D44C  |.  B9 18000000   MOV ECX,18
0040D451  |.  B8 CCCCCCCC   MOV EAX,CCCCCCCC
0040D456  |.  F3:AB         REP STOS DWORD PTR ES:[EDI]
0040D458  |.  A1 2C204200   MOV EAX,DWORD PTR DS:[??_C@_05NHMN@aaaaa?$AA@]         ;  将保存字符串的地址四个字节赋值给eax
0040D45D  |.  8945 E0       MOV DWORD PTR SS:[EBP-20],EAX                          ;  将eax赋值给ebp-20
0040D460  |.  66:8B0D 30204>MOV CX,WORD PTR DS:[422030]                            ;  除了那四个字节之后存储字符串的地址中的双字节赋值给cx
0040D467  |.  66:894D E4    MOV WORD PTR SS:[EBP-1C],CX                            ;  也就是把aaaaa最后一个a的值赋值给ebp-1c,以0结尾
0040D46B  |.  33D2          XOR EDX,EDX                                            ;  清空edx
0040D46D  |.  8955 E6       MOV DWORD PTR SS:[EBP-1A],EDX
0040D470  |.  A1 24204200   MOV EAX,DWORD PTR DS:[??_C@_05GKCJ@bbbbb?$AA@]
0040D475  |.  8945 EA       MOV DWORD PTR SS:[EBP-16],EAX
0040D478  |.  66:8B0D 28204>MOV CX,WORD PTR DS:[422028]
0040D47F  |.  66:894D EE    MOV WORD PTR SS:[EBP-12],CX
0040D483  |.  33D2          XOR EDX,EDX
0040D485  |.  8955 F0       MOV DWORD PTR SS:[EBP-10],EDX
0040D488  |.  A1 1C204200   MOV EAX,DWORD PTR DS:[??_C@_05BHF@ccccc?$AA@]
0040D48D  |.  8945 F4       MOV DWORD PTR SS:[EBP-C],EAX
0040D490  |.  66:8B0D 20204>MOV CX,WORD PTR DS:[422020]
0040D497  |.  66:894D F8    MOV WORD PTR SS:[EBP-8],CX
0040D49B  |.  33D2          XOR EDX,EDX
0040D49D  |.  8955 FA       MOV DWORD PTR SS:[EBP-6],EDX                           ;  清空ebp-6的高位两字节
0040D4A0  |.  8D45 EA       LEA EAX,DWORD PTR SS:[EBP-16]                          ;  取bbbbb的字符串赋值给eax
0040D4A3  |.  50            PUSH EAX                                               ; /<%s>
0040D4A4  |.  68 0C244200   PUSH OFFSET my.??_C@_02DILL@?$CFs?$AA@                 ; |format = "%s"
0040D4A9  |.  E8 82020000   CALL my.printf                                         ; \printf

第二种写法

代码如下:

#include<stdio.h>

int main(){
	//指针数组


	//还可以这样表示

	//相当于定义为arr[][10]
	char* arr[10] = {
		"aaaaa",
		"bbbbb",
		"ccccc"
	};
	
	printf("%s",arr[1]);

}

反汇编如下:

0040D440 >/> \55            PUSH EBP
0040D441  |.  8BEC          MOV EBP,ESP
0040D443  |.  83EC 68       SUB ESP,68
0040D446  |.  53            PUSH EBX
0040D447  |.  56            PUSH ESI
0040D448  |.  57            PUSH EDI
0040D449  |.  8D7D 98       LEA EDI,DWORD PTR SS:[EBP-68]
0040D44C  |.  B9 1A000000   MOV ECX,1A
0040D451  |.  B8 CCCCCCCC   MOV EAX,CCCCCCCC
0040D456  |.  F3:AB         REP STOS DWORD PTR ES:[EDI]
0040D458  |.  C745 D8 2C204>MOV DWORD PTR SS:[EBP-28],OFFSET my.??_C@_05NHMN@aaaaa?$AA@     ;  将保存字符串的地址赋值给ebp-28中
0040D45F  |.  C745 DC 24204>MOV DWORD PTR SS:[EBP-24],OFFSET my.??_C@_05GKCJ@bbbbb?$AA@     ;  将保存字符串的地址赋值给ebp-24中
0040D466  |.  C745 E0 1C204>MOV DWORD PTR SS:[EBP-20],OFFSET my.??_C@_05BHF@ccccc?$AA@      ;  将保存字符串的地址赋值给ebp-20中
0040D46D  |.  B9 07000000   MOV ECX,7                                                       ;  ecx赋值为7
0040D472  |.  33C0          XOR EAX,EAX                                                     ;  清空eax
0040D474  |.  8D7D E4       LEA EDI,DWORD PTR SS:[EBP-1C]                                   ;  ebp-1c的地址赋值给edi
0040D477  |.  F3:AB         REP STOS DWORD PTR ES:[EDI]                                     ;  初始化00000000
0040D479  |.  8B45 DC       MOV EAX,DWORD PTR SS:[EBP-24]                                   ;  将存储bbbbb的地址赋值给eax
0040D47C  |.  50            PUSH EAX                                                        ; /<%s>
0040D47D  |.  68 0C244200   PUSH OFFSET my.??_C@_02DILL@?$CFs?$AA@                          ; |format = "%s"
0040D482  |.  E8 A9020000   CALL my.printf                                                  ; \printf
0040D487  |.  83C4 08       ADD ESP,8
0040D48A  |.  5F            POP EDI
0040D48B  |.  5E            POP ESI
0040D48C  |.  5B            POP EBX
0040D48D  |.  83C4 68       ADD ESP,68
0040D490  |.  3BEC          CMP EBP,ESP
0040D492  |.  E8 59020000   CALL my.__chkesp
0040D497  |.  8BE5          MOV ESP,EBP
0040D499  |.  5D            POP EBP
0040D49A  \.  C3            RETN

总结:

1、第一种方式:赋值的是字符串的字符数据

2、第二种方式:赋值的是字符串的地址

数组指针

代码如下:

#include<stdio.h>

int main(){
	int arr[] = {1,2,3,4,5,6,7,8,9,0};  //一维数组

	int(*px)[2][2] = (int (*)[2][2])arr; 

	printf("%d\n",(*px)[1][1]);
	px++;
	printf("%d\n",(*px)[1][1]);
	return 0;

}

反汇编如下:

0040D756  |.  F3:AB         REP STOS DWORD PTR ES:[EDI]
0040D758  |.  C745 D8 01000>MOV DWORD PTR SS:[EBP-28],1              ;  1
0040D75F  |.  C745 DC 02000>MOV DWORD PTR SS:[EBP-24],2              ;  2
0040D766  |.  C745 E0 03000>MOV DWORD PTR SS:[EBP-20],3              ;  3
0040D76D  |.  C745 E4 04000>MOV DWORD PTR SS:[EBP-1C],4              ;  4
0040D774  |.  C745 E8 05000>MOV DWORD PTR SS:[EBP-18],5              ;  5
0040D77B  |.  C745 EC 06000>MOV DWORD PTR SS:[EBP-14],6              ;  6
0040D782  |.  C745 F0 07000>MOV DWORD PTR SS:[EBP-10],7              ;  7
0040D789  |.  C745 F4 08000>MOV DWORD PTR SS:[EBP-C],8               ;  8
0040D790  |.  C745 F8 09000>MOV DWORD PTR SS:[EBP-8],9               ;  9
0040D797  |.  C745 FC 00000>MOV DWORD PTR SS:[EBP-4],0               ;  0
0040D79E  |.  8D45 D8       LEA EAX,DWORD PTR SS:[EBP-28]            ;  数组的首地址赋值给eax,eax就为0012FF58
0040D7A1  |.  8945 D4       MOV DWORD PTR SS:[EBP-2C],EAX            ;  将存储数组的首地址赋值给ebp-2c指向的值
0040D7A4  |.  8B4D D4       MOV ECX,DWORD PTR SS:[EBP-2C]            ;  将 当前数组首地址 赋值给ecx
0040D7A7  |.  8B51 0C       MOV EDX,DWORD PTR DS:[ECX+C]             ;  ecx+C 相当于当前的地址加上0xC,可以理解为跳过两个int字节取下一组的第一个,也就是(*px)[1][1]
0040D7AA  |.  52            PUSH EDX                                 ; /<%d>
0040D7AB  |.  68 1C204200   PUSH OFFSET my.??_C@_03HMFC@?$CFd?6?$AA@ ; |format = "%d
"
0040D7B0  |.  E8 FB38FFFF   CALL my.printf                           ; \printf
0040D7B5  |.  83C4 08       ADD ESP,8                                ;  堆栈平衡,下面就是准备输出代码中第二个printf了
0040D7B8  |.  8B45 D4       MOV EAX,DWORD PTR SS:[EBP-2C]            ;  当前的数组的首地址赋值给eax
0040D7BB  |.  83C0 10       ADD EAX,10                               ;  现在是eax+10,相当于跳过两段,每段2个数,8字节,那就是跳过16字节
0040D7BE  |.  8945 D4       MOV DWORD PTR SS:[EBP-2C],EAX            ;  当前的eax地址赋值给ebp-2c指向的值
0040D7C1  |.  8B4D D4       MOV ECX,DWORD PTR SS:[EBP-2C]            ;  取其中的值给ecx
0040D7C4  |.  8B51 0C       MOV EDX,DWORD PTR DS:[ECX+C]             ;  ecx+C指向的值赋值给edx
0040D7C7  |.  52            PUSH EDX                                 ; /<%d>
0040D7C8  |.  68 1C204200   PUSH OFFSET my.??_C@_03HMFC@?$CFd?6?$AA@ ; |format = "%d
"
0040D7CD  |.  E8 DE38FFFF   CALL my.printf                           ; \printf
0040D7D2  |.  83C4 08       ADD ESP,8
0040D7D5  |.  33C0          XOR EAX,EAX
0040D7D7  |.  5F            POP EDI
0040D7D8  |.  5E            POP ESI
0040D7D9  |.  5B            POP EBX
0040D7DA  |.  83C4 6C       ADD ESP,6C
0040D7DD  |.  3BEC          CMP EBP,ESP
0040D7DF  |.  E8 4C39FFFF   CALL my.__chkesp
0040D7E4  |.  8BE5          MOV ESP,EBP
0040D7E6  |.  5D            POP EBP
0040D7E7  \.  C3            RETN

posted @ 2020-02-21 15:34  zpchcbd  阅读(308)  评论(0编辑  收藏  举报