滴水逆向初级-C语言(二)

2.1.C语言的汇编表示

c语言代码

int plus(int x,int y)
{
	return 0;
}

void main()
{

	__asm
	{
		mov eax,eax
	}

	//调用函数
	plus(1,2);

	return;
}

汇编代码

1:
2:    int plus(int x,int y)
3:    {
00401020   push        ebp
00401021   mov         ebp,esp
00401023   sub         esp,40h
00401026   push        ebx
00401027   push        esi
00401028   push        edi
00401029   lea         edi,[ebp-40h]
0040102C   mov         ecx,10h
00401031   mov         eax,0CCCCCCCCh
00401036   rep stos    dword ptr [edi]
4:        return 0;
00401038   xor         eax,eax
5:    }
0040103A   pop         edi
0040103B   pop         esi
0040103C   pop         ebx
0040103D   mov         esp,ebp
0040103F   pop         ebp
00401040   ret
--- No source file  -------------------------------------------------------------------------------------------------------------------------------------
00401041   int         3
00401042   int         3
00401043   int         3
00401044   int         3
0040104F   int         3
--- C:\Program Files\Microsoft Visual Studio\MyProjects\11\test.cpp  ------------------------------------------------------------------------------------
6:
7:    void main()
8:    {
00401050   push        ebp
00401051   mov         ebp,esp
00401053   sub         esp,40h
00401056   push        ebx
00401057   push        esi
00401058   push        edi
00401059   lea         edi,[ebp-40h]
0040105C   mov         ecx,10h
00401061   mov         eax,0CCCCCCCCh
00401066   rep stos    dword ptr [edi]
9:        plus(1,2);    //调用函数
00401068   push        2
0040106A   push        1
0040106C   call        @ILT+0(plus) (00401005)
00401071   add         esp,8
10:
11:       return;
12:   }
00401074   pop         edi
00401075   pop         esi
00401076   pop         ebx
00401077   add         esp,40h
0040107A   cmp         ebp,esp
0040107C   call        __chkesp (004010a0)
00401081   mov         esp,ebp
00401083   pop         ebp
00401084   ret
--- No source file  -------------------------------------------------------------------------------------------------------------------------------------
00401085   int         3


2.2.参数传递与返回值

1、函数定义

返回类型函数名(参数列表)
{
	return
}

例子:
int plus(int x,int y)
{
    return x+y;
}

2.画堆栈图

int plus(int x,int y)
{
	return x+y;
}

void main()
{
	__asm
	{
		mov eax,eax     //断点调试   F7,F5,右键Go To Disassembly. F10单步,call按F11
	}

	plus(1,2);    

	return;
}

image
3.汇编代码

1:
2:    int plus(int x,int y)
3:    {
00401020   push        ebp
00401021   mov         ebp,esp
00401023   sub         esp,40h                       //提升堆栈
00401026   push        ebx
00401027   push        esi
00401028   push        edi                           //保存要用到的寄存器的值
00401029   lea         edi,[ebp-40h]
0040102C   mov         ecx,10h                       //ecx=10h,ecx是计数器  
00401031   mov         eax,0CCCCCCCCh                //eax=CCCCCCCC
00401036   rep stos    dword ptr [edi]              //把eax的值写到[edi],写的次数:ecx的值
4:        return x+y;
00401038   mov         eax,dword ptr [ebp+8]         //第一个参数的值,eax=1
0040103B   add         eax,dword ptr [ebp+0Ch]       //第一个参数+第二个参数  eax=1+2
5:    }
0040103E   pop         edi
0040103F   pop         esi
00401040   pop         ebx                           
00401041   mov         esp,ebp
00401043   pop         ebp                            //还原堆栈
00401044   ret                                        //eip=00401083,  esp+4
--- No source file  -------------------------------------------------------------------------------------------------------------------------------------
00401045   int         3
00401046   int         3

--- C:\Program Files\Microsoft Visual Studio\MyProjects\11\test.cpp  ------------------------------------------------------------------------------------
6:
7:    void main()
8:    {
00401050   push        ebp
00401051   mov         ebp,esp
00401053   sub         esp,40h
00401056   push        ebx
00401057   push        esi
00401058   push        edi
00401059   lea         edi,[ebp-40h]
0040105C   mov         ecx,10h
00401061   mov         eax,0CCCCCCCCh
00401066   rep stos    dword ptr [edi]
9:        __asm
10:       {
11:           mov eax,eax
00401068   mov         eax,eax
12:       }
13:
14:       plus(1,2);
0040106A   push        2								//通过堆栈传参数				
0040106C   push        1
0040106E   call        @ILT+0(plus) (00401005)
00401073   add         esp,8                           //还原堆栈
15:
16:       return;
17:   }
00401076   pop         edi
00401077   pop         esi
00401078   pop         ebx
00401079   add         esp,40h
0040107C   cmp         ebp,esp
0040107E   call        __chkesp (004010a0)
00401083   mov         esp,ebp
00401085   pop         ebp
00401086   ret
--- No source file  -------------------------------------------------------------------------------------------------------------------------------------
00401087   int         3
00401088   int         3

3、参数是如何传递的
C语言中参数传递:堆栈传参数从右到左

4、返回值存在哪里?返回值用了吗?
C语言中,返回值存储在EAX中

2.3.变量

1、声明变量
变量类型变量名;
变量类型用来说明宽度是多大
int 4个字节
short 2个字节
char 1个字节

变量名的命名规则:
1、只能以字母、数字、下划线组成,且第一个字母必须是字母或下划线
2、区分大小写
3、不能使用C语言的关键字

2、全局变量:
1)编译的时候就已经确定了内存地址和宽度,变量名就是内存地址的别名。
2)如果不重写编译,全局变量的内存地址不变。游戏外挂中的找“基址”,其实就
是找全局变量。|
3)全局变量中的值任何程序都可以改,是公用的。
例子: CE搜索基址

C语言代码

#include <windows.h>
#include <stdio.h>

int x;

void main()
{
	x = 1234567;

	while(1)
	{
		Sleep(3000);
		printf("%d\n",x);
	}

	return;
}

image
3、局部变量
1)局部变量是函数内部申请的,如果函数没有执行,那么局部变量没有内存空间。
2)局部变量的内存是在堆栈中分配的,程序执行时才分配。我们无法预知程序何时
执行,这也就意味着,我们无法确定局部变量的内存地址。
3)因为局部变量地址内存是不确定的,所以,局部变量只能在函数内部使用,其他
函数不能使用。

2.4.变量与参数的内存布局

c语言代码

int plus(int x,int y)
{
	int z = x + y;
	return z;
}

void main()
{
	int r;
	r = plus(1,2);
	return;
} 

汇编代码

1:
2:    int plus(int x,int y)
3:    {
00401020   push        ebp
00401021   mov         ebp,esp
00401023   sub         esp,44h
00401026   push        ebx
00401027   push        esi
00401028   push        edi
00401029   lea         edi,[ebp-44h]
0040102C   mov         ecx,11h
00401031   mov         eax,0CCCCCCCCh
00401036   rep stos    dword ptr [edi]
4:        int z = x + y;
00401038   mov         eax,dword ptr [ebp+8]
0040103B   add         eax,dword ptr [ebp+0Ch]
0040103E   mov         dword ptr [ebp-4],eax            //[ebp-4]存放局部变量
5:        return z;
00401041   mov         eax,dword ptr [ebp-4]
6:    }
00401044   pop         edi
00401045   pop         esi
00401046   pop         ebx
00401047   mov         esp,ebp
00401049   pop         ebp
0040104A   ret
--- No source file  -----------------------------------------------------------------------------------------------
0040104B   int         3
0040104C   int         3

--- C:\Program Files\Microsoft Visual Studio\MyProjects\11\test.cpp  ----------------------------------------------
7:
8:    void main()
9:    {
00401060   push        ebp
00401061   mov         ebp,esp
00401063   sub         esp,44h
00401066   push        ebx
00401067   push        esi
00401068   push        edi
00401069   lea         edi,[ebp-44h]
0040106C   mov         ecx,11h
00401071   mov         eax,0CCCCCCCCh
00401076   rep stos    dword ptr [edi]
10:       int r;
11:       r = plus(1,2);
00401078   push        2
0040107A   push        1
0040107C   call        @ILT+0(plus) (00401005)
00401081   add         esp,8
00401084   mov         dword ptr [ebp-4],eax
12:       return;
13:   }
00401087   pop         edi
00401088   pop         esi
00401089   pop         ebx
0040108A   add         esp,44h
0040108D   cmp         ebp,esp
0040108F   call        __chkesp (004010b0)
00401094   mov         esp,ebp
00401096   pop         ebp
00401097   ret
--- No source file  -----------------------------------------------------------------------------------------------
00401098   int         3
00401099   int         3

堆栈图
image
1.5.函数嵌套调用的内存布局

C语言代码

#include<stdio.h>

int plus1(int x,int y)
{
	return x+y;
}

int plus(int x,int y,int z)
{
	int m = plus1(x,y);
	return m+z;
}

void main()
{
	int r;
	r = plus(1,2,3);
	printf("%d",r);
	return;
}

汇编代码

1:    #include<stdio.h>
2:
3:    int plus1(int x,int y)
4:    {
00401020   push        ebp
00401021   mov         ebp,esp
00401023   sub         esp,40h
00401026   push        ebx
00401027   push        esi
00401028   push        edi
00401029   lea         edi,[ebp-40h]
0040102C   mov         ecx,10h
00401031   mov         eax,0CCCCCCCCh
00401036   rep stos    dword ptr [edi]
5:        return x+y;
00401038   mov         eax,dword ptr [ebp+8]
0040103B   add         eax,dword ptr [ebp+0Ch]
6:    }
0040103E   pop         edi
0040103F   pop         esi
00401040   pop         ebx
00401041   mov         esp,ebp
00401043   pop         ebp
00401044   ret
--- No source file  -----------------------------------------------------------------------------------------------
00401045   int         3
00401046   int         3

7:
8:    int plus(int x,int y,int z)
9:    {
00401060   push        ebp
00401061   mov         ebp,esp
00401063   sub         esp,44h
00401066   push        ebx
00401067   push        esi
00401068   push        edi
00401069   lea         edi,[ebp-44h]
0040106C   mov         ecx,11h
00401071   mov         eax,0CCCCCCCCh
00401076   rep stos    dword ptr [edi]                 
10:       int m = plus1(x,y);
00401078   mov         eax,dword ptr [ebp+0Ch]
0040107B   push        eax
0040107C   mov         ecx,dword ptr [ebp+8]
0040107F   push        ecx
00401080   call        @ILT+10(plus) (0040100f)
00401085   add         esp,8
00401088   mov         dword ptr [ebp-4],eax
11:       return m+z;
0040108B   mov         eax,dword ptr [ebp-4]
0040108E   add         eax,dword ptr [ebp+10h]
12:   }
00401091   pop         edi
00401092   pop         esi
00401093   pop         ebx
00401094   add         esp,44h
00401097   cmp         ebp,esp
00401099   call        __chkesp (004010b0)
0040109E   mov         esp,ebp
004010A0   pop         ebp
004010A1   ret
--- No source file  -----------------------------------------------------------------------------------------------
004010A2   int         3
004010A3   int         3

13:
14:   void main()
15:   {
0040B500   push        ebp
0040B501   mov         ebp,esp
0040B503   sub         esp,44h
0040B506   push        ebx
0040B507   push        esi
0040B508   push        edi
0040B509   lea         edi,[ebp-44h]
0040B50C   mov         ecx,11h
0040B511   mov         eax,0CCCCCCCCh
0040B516   rep stos    dword ptr [edi]     
16:       int r;
17:       r = plus(1,2,3);
0040B518   push        3
0040B51A   push        2
0040B51C   push        1                  //传三个参数
0040B51E   call        @ILT+15(plus) (00401014)
0040B523   add         esp,0Ch
0040B526   mov         dword ptr [ebp-4],eax
18:       printf("%d",r);
0040B529   mov         eax,dword ptr [ebp-4]
0040B52C   push        eax
0040B52D   push        offset string "%d" (0041f10c)
0040B532   call        printf (0040b770)
0040B537   add         esp,8
19:       return;
20:   }
0040B53A   pop         edi
0040B53B   pop         esi
0040B53C   pop         ebx
0040B53D   add         esp,44h
0040B540   cmp         ebp,esp
0040B542   call        __chkesp (004010b0)
0040B547   mov         esp,ebp
0040B549   pop         ebp
0040B54A   ret
--- No source file  -----------------------------------------------------------------------------------------------
0040B54B   int         3
0040B54C   int         3

堆栈图
image

2.5.整数类型

1、整数类型的宽度:

char、short、 int、 long

char 8BIT 1字节 0~ 0xFF
short 16BIT 2字节 0~ 0xFFFF
int 32BIT 4字节 0 ~ 0xFFFFFFFF
long 32BIT 4字节 0 ~ 0xFFFFFFFF

特别说明:
int在16计算机中与short宽度-样,在32以上的计算机中与long同

2、存储格式:
charx=1; //0000 0001 0x01
charx= 1; //1111 1111 0xFF

5、有符号与无符号数(signed、 unsigned)
1)什么时候使用有符号、无符号
2)有符号与无符号的区别:
<1>正确理解有符号数与无符号数
<2>拓展时与比较时才有区别

2.6.if语句

C语言代码

#include<stdio.h>
#include<windows.h>

void main()
{
	int x = 10;
	int y = 20;

	if(x>y)
	{
		printf("+++++\n");
	}
	else
	{
		printf("------\n");
	}

	return;
} 

汇编代码

1:    #include<stdio.h>
2:    #include<windows.h>
3:
4:    void main()
5:    {
00401010   push        ebp
00401011   mov         ebp,esp
00401013   sub         esp,48h
00401016   push        ebx
00401017   push        esi
00401018   push        edi
00401019   lea         edi,[ebp-48h]
0040101C   mov         ecx,12h
00401021   mov         eax,0CCCCCCCCh
00401026   rep stos    dword ptr [edi]
6:        int x = 10;
00401028   mov         dword ptr [ebp-4],0Ah
7:        int y = 20;
0040102F   mov         dword ptr [ebp-8],14h
8:
9:        if(x>y)
00401036   mov         eax,dword ptr [ebp-4]
00401039   cmp         eax,dword ptr [ebp-8]
0040103C   jle         main+3Dh (0040104d)
10:       {
11:           printf("+++++\n");
0040103E   push        offset string "+++++\n" (00420028)
00401043   call        printf (00401090)
00401048   add         esp,4
12:       }
13:       else
0040104B   jmp         main+4Ah (0040105a)
14:       {
15:           printf("------\n");
0040104D   push        offset string "------\n" (0042001c)
00401052   call        printf (00401090)
00401057   add         esp,4
16:       }
17:
18:       return;
19:   }
0040105A   pop         edi
0040105B   pop         esi
0040105C   pop         ebx
0040105D   add         esp,48h
00401060   cmp         ebp,esp
00401062   call        __chkesp (00401110)
00401067   mov         esp,ebp
00401069   pop         ebp
0040106A   ret
--- No source file  -----------------------------------------------------------------------------------------------
0040106B   int         3
0040106C   int         3

2.7.switch语句

当分支条件比较多得时候switch比if语句高效很多。

case条件按顺序时候的汇编代码

C语言代码

#include<stdio.h>
#include<windows.h>

void Myprint(int x)
{
	switch(x)
	{
	case 1:
		printf("A\n");
		break;
	case 2:
		printf("B\n");
		break;
	case 3:
		printf("C\n");
		break;
	case 4:
		printf("D\n");
		break;
	case 5:
		printf("E\n");
		break;
	}
}

void main()
{
	Myprint(3);

	return ;
} 

汇编语言代码

1:    #include<stdio.h>
2:    #include<windows.h>
3:
4:    void Myprint(int x)
5:    {
00401020   push        ebp
00401021   mov         ebp,esp
00401023   sub         esp,44h
00401026   push        ebx
00401027   push        esi
00401028   push        edi
00401029   lea         edi,[ebp-44h]
0040102C   mov         ecx,11h
00401031   mov         eax,0CCCCCCCCh
00401036   rep stos    dword ptr [edi]
6:        switch(x)
7:        {
00401038   mov         eax,dword ptr [ebp+8]
0040103B   mov         dword ptr [ebp-4],eax
0040103E   mov         ecx,dword ptr [ebp-4]
00401041   sub         ecx,1
00401044   mov         dword ptr [ebp-4],ecx
00401047   cmp         dword ptr [ebp-4],4
0040104B   ja          $L42195+0Dh (004010a0)
0040104D   mov         edx,dword ptr [ebp-4]
00401050   jmp         dword ptr [edx*4+4010B1h]
8:        case 1:
9:            printf("A\n");
00401057   push        offset string "A\n" (0042002c)
0040105C   call        printf (00401130)
00401061   add         esp,4
10:           break;
00401064   jmp         $L42195+0Dh (004010a0)
11:       case 2:
12:           printf("B\n");
00401066   push        offset string "B\n" (00420028)
0040106B   call        printf (00401130)
00401070   add         esp,4
13:           break;
00401073   jmp         $L42195+0Dh (004010a0)
14:       case 3:
15:           printf("C\n");
00401075   push        offset string "C\n" (00420024)
0040107A   call        printf (00401130)
0040107F   add         esp,4
16:           break;
00401082   jmp         $L42195+0Dh (004010a0)
17:       case 4:
18:           printf("D\n");
00401084   push        offset string "D\n" (00420020)
00401089   call        printf (00401130)
0040108E   add         esp,4
19:           break;
00401091   jmp         $L42195+0Dh (004010a0)
20:       case 5:
21:           printf("E\n");
00401093   push        offset string "E\n" (0042001c)
00401098   call        printf (00401130)
0040109D   add         esp,4
22:           break;
23:       }
24:   }
004010A0   pop         edi
004010A1   pop         esi
004010A2   pop         ebx
004010A3   add         esp,44h
004010A6   cmp         ebp,esp
004010A8   call        __chkesp (004011b0)
004010AD   mov         esp,ebp
004010AF   pop         ebp
004010B0   ret
004010B1   push        edi
004010B2   adc         byte ptr [eax],al
004010B5   adc         byte ptr [eax],al
004010B9   jne         Myprint+0ABh (004010cb)
004010BB   inc         eax
004010BC   add         byte ptr [eax+edx+10930040h],al
004010C3   inc         eax
004010C4   add         ah,cl
--- No source file  -----------------------------------------------------------------------------------------------
004010C6   int         3
004010C7   int         3

case条件不按顺序时候的汇编代码

c语言代码

#include<stdio.h>
#include<windows.h>

void Myprint(int x)
{
	switch(x)
	{
	case 1:
		printf("A\n");
		break;
	case 2:
		printf("B\n");
		break;
	case 4:
		printf("C\n");
		break;
	case 7:
		printf("D\n");
		break;
	case 8:
		printf("E\n");
		break;
	}
}

void main()
{
	Myprint(3);

	return ;
} 

汇编代码

:    #include<stdio.h>
2:    #include<windows.h>
3:
4:    void Myprint(int x)
5:    {
00401020   push        ebp
00401021   mov         ebp,esp
00401023   sub         esp,44h
00401026   push        ebx
00401027   push        esi
00401028   push        edi
00401029   lea         edi,[ebp-44h]
0040102C   mov         ecx,11h
00401031   mov         eax,0CCCCCCCCh
00401036   rep stos    dword ptr [edi]
6:        switch(x)
7:        {
00401038   mov         eax,dword ptr [ebp+8]
0040103B   mov         dword ptr [ebp-4],eax
0040103E   mov         ecx,dword ptr [ebp-4]
00401041   sub         ecx,1
00401044   mov         dword ptr [ebp-4],ecx
00401047   cmp         dword ptr [ebp-4],7
0040104B   ja          $L42196+0Dh (004010a0)
0040104D   mov         edx,dword ptr [ebp-4]
00401050   jmp         dword ptr [edx*4+4010B1h]
8:        case 1:
9:            printf("A\n");
00401057   push        offset string "A\n" (0042002c)
0040105C   call        printf (00401130)
00401061   add         esp,4
10:           break;
00401064   jmp         $L42196+0Dh (004010a0)
11:       case 2:
12:           printf("B\n");
00401066   push        offset string "B\n" (00420028)
0040106B   call        printf (00401130)
00401070   add         esp,4
13:           break;
00401073   jmp         $L42196+0Dh (004010a0)
14:       case 4:
15:           printf("C\n");
00401075   push        offset string "C\n" (00420024)
0040107A   call        printf (00401130)
0040107F   add         esp,4
16:           break;
00401082   jmp         $L42196+0Dh (004010a0)
17:       case 7:
18:           printf("D\n");
00401084   push        offset string "D\n" (00420020)
00401089   call        printf (00401130)
0040108E   add         esp,4
19:           break;
00401091   jmp         $L42196+0Dh (004010a0)
20:       case 8:
21:           printf("E\n");
00401093   push        offset string "E\n" (0042001c)
00401098   call        printf (00401130)
0040109D   add         esp,4
22:           break;
23:       }
24:   }
004010A0   pop         edi
004010A1   pop         esi
004010A2   pop         ebx
004010A3   add         esp,44h
004010A6   cmp         ebp,esp
004010A8   call        __chkesp (004011b0)
004010AD   mov         esp,ebp
004010AF   pop         ebp
004010B0   ret
004010B1   push        edi
004010B2   adc         byte ptr [eax],al
004010B5   adc         byte ptr [eax],al
004010B9   mov         al,[75004010]
004010BE   adc         byte ptr [eax],al
004010C1   mov         al,[A0004010]
004010C6   adc         byte ptr [eax],al
004010C9   test        byte ptr [eax],dl
004010CB   inc         eax
004010CC   add         byte ptr [ebx-33FFBFF0h],dl
--- No source file  -----------------------------------------------------------------------------------------------
004010D2   int         3
004010D3   int         3

case条件中间不连续(3,5,6)的地方,会填充为default的地址,
image

2.8.for循环

C语言代码

#include<stdio.h>
#include<windows.h>

void Myprint()
{
	int i;
	for(i=0;i<10;i++)
	{
		printf("%d\n",i);
	}
}

void main()
{
	Myprint();

	return ;
} 

汇编代码

1:    #include<stdio.h>
2:    #include<windows.h>
3:
4:    void Myprint()
5:    {
00401020   push        ebp
00401021   mov         ebp,esp
00401023   sub         esp,44h
00401026   push        ebx
00401027   push        esi
00401028   push        edi
00401029   lea         edi,[ebp-44h]
0040102C   mov         ecx,11h
00401031   mov         eax,0CCCCCCCCh
00401036   rep stos    dword ptr [edi]
6:        int i;
7:        for(i=0;i<10;i++)
00401038   mov         dword ptr [ebp-4],0
0040103F   jmp         Myprint+2Ah (0040104a)
00401041   mov         eax,dword ptr [ebp-4]
00401044   add         eax,1
00401047   mov         dword ptr [ebp-4],eax
0040104A   cmp         dword ptr [ebp-4],0Ah
0040104E   jge         Myprint+43h (00401063)
8:        {
9:            printf("%d\n",i);
00401050   mov         ecx,dword ptr [ebp-4]
00401053   push        ecx
00401054   push        offset string "E\n" (0042001c)
00401059   call        printf (00401130)
0040105E   add         esp,8
10:       }
00401061   jmp         Myprint+21h (00401041)
11:   }
00401063   pop         edi
00401064   pop         esi
00401065   pop         ebx
00401066   add         esp,44h
00401069   cmp         ebp,esp
0040106B   call        __chkesp (004011b0)
00401070   mov         esp,ebp
00401072   pop         ebp
00401073   ret
--- No source file  ---------------------------------------------------------------------------------------------------------------------
00401074   int         3
00401075   int         3

2.9.数组

C语言代码

#include<stdio.h>
#include<windows.h>


void main()
{
	int age[5]={1,2,3,4,5};
	int x,y;
	x = age[0];
	age[1]=6;
	y = age[1];
	printf("%d\n%d",x,y);
	return ;
} 

汇编代码

1:    #include<stdio.h>
2:    #include<windows.h>
3:
4:
5:    void main()
6:    {
00401020   push        ebp
00401021   mov         ebp,esp
00401023   sub         esp,5Ch
00401026   push        ebx
00401027   push        esi
00401028   push        edi
00401029   lea         edi,[ebp-5Ch]
0040102C   mov         ecx,17h
00401031   mov         eax,0CCCCCCCCh
00401036   rep stos    dword ptr [edi]
7:        int age[5]={1,2,3,4,5};
00401038   mov         dword ptr [ebp-14h],1
0040103F   mov         dword ptr [ebp-10h],2
00401046   mov         dword ptr [ebp-0Ch],3
0040104D   mov         dword ptr [ebp-8],4
00401054   mov         dword ptr [ebp-4],5
8:        int x,y;
9:        x = age[0];
0040105B   mov         eax,dword ptr [ebp-14h]
0040105E   mov         dword ptr [ebp-18h],eax
10:       age[1]=6;
00401061   mov         dword ptr [ebp-10h],6
11:       y = age[1];
00401068   mov         ecx,dword ptr [ebp-10h]
0040106B   mov         dword ptr [ebp-1Ch],ecx
12:       printf("%d\n%d",x,y);
0040106E   mov         edx,dword ptr [ebp-1Ch]
00401071   push        edx
00401072   mov         eax,dword ptr [ebp-18h]
00401075   push        eax
00401076   push        offset string "%d\n%d" (0042001c)
0040107B   call        printf (00401130)
00401080   add         esp,0Ch
13:       return ;
14:   }
00401083   pop         edi
00401084   pop         esi
00401085   pop         ebx
00401086   add         esp,5Ch
00401089   cmp         ebp,esp
0040108B   call        __chkesp (004011b0)
00401090   mov         esp,ebp
00401092   pop         ebp
00401093   ret
--- No source file  ---------------------------------------------------------------------------------------------------------------------
00401094   int         3
00401095   int         3

2.10.多维数组

C语言代码

#include<stdio.h>
#include<windows.h>


void main()
{
	int arr[3][4] = 
	{
		{1,2,3,4},
		{5,6,7,8},
		{9,10,11,12}
	};

	return ;
} 

汇编代码

1:    #include<stdio.h>
2:    #include<windows.h>
3:
4:
5:    void main()
6:    {
00401010   push        ebp
00401011   mov         ebp,esp
00401013   sub         esp,70h
00401016   push        ebx
00401017   push        esi
00401018   push        edi
00401019   lea         edi,[ebp-70h]
0040101C   mov         ecx,1Ch
00401021   mov         eax,0CCCCCCCCh
00401026   rep stos    dword ptr [edi]
7:        int arr[3][4] =
8:        {
9:            {1,2,3,4},
00401028   mov         dword ptr [ebp-30h],1
0040102F   mov         dword ptr [ebp-2Ch],2
00401036   mov         dword ptr [ebp-28h],3
0040103D   mov         dword ptr [ebp-24h],4
10:           {5,6,7,8},
00401044   mov         dword ptr [ebp-20h],5
0040104B   mov         dword ptr [ebp-1Ch],6
00401052   mov         dword ptr [ebp-18h],7
00401059   mov         dword ptr [ebp-14h],8
11:           {9,10,11,12}
00401060   mov         dword ptr [ebp-10h],9
00401067   mov         dword ptr [ebp-0Ch],0Ah
0040106E   mov         dword ptr [ebp-8],0Bh
00401075   mov         dword ptr [ebp-4],0Ch
12:       };
13:
14:       return ;
15:   }
0040107C   pop         edi
0040107D   pop         esi
0040107E   pop         ebx
0040107F   mov         esp,ebp
00401081   pop         ebp
00401082   ret
--- No source file  ---------------------------------------------------------------------------------------------------------------------
00401083   int         3
00401084   int         3

2.11.结构体

结构体类型的定义:

struct类型名{
	//可以定义多种类型
	inta;
	char b;
	short c;
};

<1> char/int/数组等是编译器已经认识的类型:内置类型
<2>结构体是编译器不认识的,用的时候需要告诉编译器-声:自定义类型
<3>.上面的代码仅仅是告诉编译器我们自己定义的类型是什么样的,本身并不占用内存。

定义结构体类型的时候,直接定义变量

struct stPoint{
	int x;
	int y;
}point1 ,point2,point3;

//这种方式是分配内存的,因为不仅仅是定义新的类型,还定义了3个全局变量

2.12.字节对齐

1.什么是字节对齐呢?
char X;
short y;|
intz;

字节对齐:
一个变量占用n个字节,则该变量的起始地址必须是n的整数倍,即:存放起始地址% n=0。

如果是结构体,那么结构体的起始地址是其最宽数据类型成员的整数倍。

2.结构体字节对齐占用空间大小

#include<stdio.h>
#include<windows.h>

struct test1{
	char a;
	int b;
};

struct test2{
	char c;
	double d;
};

int check()
{
	printf("%d\n",sizeof(test1));    //8
	printf("%d\n",sizeof(test2));    //16
	return 0;
}


void main()
{
	check();
	getchar();
	return ;
} 

3.当对空间要求较高的时候,可以通过#pragma pack(n)来改变结构体成员的对齐方式

#pragma pack(1)
structTest{
	char a;
	int b;
};
#pragma pack()

<1> #pragma pack(n)中n用来设定变量以n字节对齐方式,可以设定的值包括: 1、2、4、8,VC编译器默认是8。
<2>若需取消强制对齐方式,则可用命令#pragma pack()

<3>结构体大总大小: N = Min(最大成员,对齐参数)是N的整数倍
image

2.13.指针类型

1、定义带“*”类型的变量

1、带有**的变量类型的标准写法:变量类型* * 变量名。
2、任何类型都可以带* 加上* 以后是新的类型,统称“指针类型”。
3、*可以是任意多个。

2、指针宽度

指针类型的变量宽度永远是4字节、无论类型是什么,无论有几个*。

char* a
short* b
int* c

3、指针类型的自加和自减
1、不带类型的变量,++或者-都是加1或者减1
2、带
类型的变量,++或者-新增(减少)的数量是去掉-一个*后变量的宽度

#include<stdio.h>
#include<windows.h>

void main()
{

	char* a;
	short* b;
	int* c;

	a = (char*)100;
	b = (short*)100;
	c = (int*)100;
	a++;   //减掉一个*后就是char的宽度,1
	b++;   //减掉一个*后就是short的宽度,2
	c++;   //减掉一个*后就是int的宽度,4
	printf("%d %d %d\n",a,b,c);   //101 102 104
		
	system("pause");
	return ;
} 
#include<stdio.h>
#include<windows.h>

void main()
{

	char** a;
	short** b;
	int** c;

	a = (char**)100;
	b = (short**)100;
	c = (int**)100;
	a++;   //减掉一个*后就是char*的宽度,4
	b++;   //减掉一个*后就是short*的宽度,4
	c++;   //减掉一个*后就是int*的宽度,4
	printf("%d %d %d\n",a,b,c);   //104 104 104
		
	system("pause");
	return ;
} 

4、指针类型的加减运算
1、指针类型的变量可以加、减-一个整数,但不能乘或者除.
2、指针类型变量与其他整数相加或者相减时:
指针类型变量+N = 指针类型变量+ N * (去掉-一个* 后类型的宽度)
指针类型变量-N = 指针类型变量- N * (去掉-一个 * 后类型的宽度)

#include<stdio.h>
#include<windows.h>

void main()
{
	char* a;
	short* b;
	int* c;

	a = (char*)100;
	b = (short*)100;
	c = (int*)100;
	a = a + 5;     // a = 100+(1x5)
	b = b + 5;     // b = 100+(2x5)
	c = c + 5;     // c = 100+(4x5)
	printf("%d %d %d\n",a,b,c);   //105 110 120
		
	system("pause");
	return ;
} 
#include<stdio.h>
#include<windows.h>

void main()
{
	char** a;
	short** b;
	int** c;

	a = (char**)100;
	b = (short**)100;
	c = (int**)100;
	a = a + 5;     // a = 100+(4x5)
	b = b + 5;     // b = 100+(4x5)
	c = c + 5;     // c = 100+(4x5)
	printf("%d %d %d\n",a,b,c);   //120 120 120
		
	system("pause");
	return ;
} 

5、指针类型可以做大小比较

#include<stdio.h>
#include<windows.h>

void main()
{

	char* a;
	char* b;

	a = (char*)200;
	b = (char*)100;

	if(a>b)
	{
		printf("1\n");     //1
	}
	else
	{
		printf("2\n");
	}
		
	system("pause");
	return ;
} 

2.14.&的使用

&是取地址符,任何变量都可以使用&来获取地址,但不能用在常量上。

指针变量赋值

#include<stdio.h>
#include<windows.h>

void main()
{

	char x;
	char* p1;
	char** p2;
	char*** p3;
	char**** p4;

	p1 = &x;        //char*
	p2 = &p1;		//char**
	p3 = &p2;		//cahr***
	p4 = &p3;		//char****
	
	system("pause");
	return ;
} 

2.15.取值运算符

1、 * 指针类型 的类型

*加指针类型 的类型是 指针类型减去一个 *

#include<stdio.h>
#include<windows.h>

void main()
{
	int*** a;
	int** b;
	int* c;

	int x = *(a);		//a是int***类型,*(a)是int**类型 
	int y = *(b);		//b是int**类型,*(b)是int*类型
	int z = *(c);		//c是int*类型,*(c)是int类型
		
	system("pause");
	return ;
} 

取值运算符举例

C语言代码

#include<stdio.h>
#include<windows.h>

int x = 1;
int* p1;
int** p2;
int*** p3;

void main()
{
	p1 = &x;
	p2 = &p1;
	p3=&p2;

	int r = *(*(*(p3)));
	printf("%d\n",r);

	system("pause");
	return ;
} 

汇编代码

1:    #include<stdio.h>
2:    #include<windows.h>
3:
4:    int x = 1;
5:    int* p1;
6:    int** p2;
7:    int*** p3;
8:
9:    void main()
10:   {
00401010   push        ebp
00401011   mov         ebp,esp
00401013   sub         esp,44h
00401016   push        ebx
00401017   push        esi
00401018   push        edi
00401019   lea         edi,[ebp-44h]
0040101C   mov         ecx,11h
00401021   mov         eax,0CCCCCCCCh
00401026   rep stos    dword ptr [edi]
11:       p1 = &x;
00401028   mov         dword ptr [p1 (004255ec)],offset x (00424a30)
12:       p2 = &p1;
00401032   mov         dword ptr [p2 (004255f0)],offset p1 (004255ec)
13:       p3=&p2;
0040103C   mov         dword ptr [p3 (004255f4)],offset p2 (004255f0)
14:
15:       int r = *(*(*(p3)));
00401046   mov         eax,[p3 (004255f4)]
0040104B   mov         ecx,dword ptr [eax]
0040104D   mov         edx,dword ptr [ecx]
0040104F   mov         eax,dword ptr [edx]
00401051   mov         dword ptr [ebp-4],eax
16:       printf("%d\n",r);
00401054   mov         ecx,dword ptr [ebp-4]
00401057   push        ecx
00401058   push        offset string "%d\n" (00422024)
0040105D   call        printf (004011b0)
00401062   add         esp,8
17:
18:       system("pause");
00401065   push        offset string "pause" (0042201c)
0040106A   call        system (004010a0)
0040106F   add         esp,4
19:       return ;
20:   }
00401072   pop         edi
00401073   pop         esi
00401074   pop         ebx
00401075   add         esp,44h
00401078   cmp         ebp,esp
0040107A   call        __chkesp (00401230)
0040107F   mov         esp,ebp
00401081   pop         ebp
00401082   ret
--- No source file  --------------------------------------------------------------------------------------------------------------------------------
00401083   int         3

2.16.数组参数传递

1、数组作为参数:****

1.传递的是数组的首地址(也就是数组 第一个元素的地址)

2.应该传递数组的长度

C语言代码

#include<stdio.h>
#include<windows.h>

void PrintArray(int arr[], int nLength)
{
	for(int i=0;i<nLength;i++)
	{
		printf("%d\n",arr[i]);
	}
}

void main()
{
	int arr[5] = {1,2,3,4,5};
	PrintArray(arr,5);
	
	system("pause");
	return ;
} 

汇编代码

1:    #include<stdio.h>
2:    #include<windows.h>
3:
4:    void PrintArray(int arr[], int nLength)
5:    {
00401020   push        ebp
00401021   mov         ebp,esp
00401023   sub         esp,44h
00401026   push        ebx
00401027   push        esi
00401028   push        edi
00401029   lea         edi,[ebp-44h]
0040102C   mov         ecx,11h
00401031   mov         eax,0CCCCCCCCh
00401036   rep stos    dword ptr [edi]
6:        for(int i=0;i<nLength;i++)
00401038   mov         dword ptr [ebp-4],0
0040103F   jmp         PrintArray+2Ah (0040104a)
00401041   mov         eax,dword ptr [ebp-4]
00401044   add         eax,1
00401047   mov         dword ptr [ebp-4],eax
0040104A   mov         ecx,dword ptr [ebp-4]
0040104D   cmp         ecx,dword ptr [ebp+0Ch]
00401050   jge         PrintArray+4Bh (0040106b)
7:        {
8:            printf("%d\n",arr[i]);
00401052   mov         edx,dword ptr [ebp-4]
00401055   mov         eax,dword ptr [ebp+8]
00401058   mov         ecx,dword ptr [eax+edx*4]
0040105B   push        ecx
0040105C   push        offset string "%d\n" (0042201c)
00401061   call        printf (00401120)
00401066   add         esp,8
9:        }
00401069   jmp         PrintArray+21h (00401041)
10:   }
0040106B   pop         edi
0040106C   pop         esi
0040106D   pop         ebx
0040106E   add         esp,44h
00401071   cmp         ebp,esp
00401073   call        __chkesp (004011a0)
00401078   mov         esp,ebp
0040107A   pop         ebp
0040107B   ret
--- No source file  --------------------------------------------------------------------------------------------------------------------------------
0040107C   int         3

--- c:\program files\microsoft visual studio\myprojects\11\test.cpp  -------------------------------------------------------------------------------
11:
12:   void main()
13:   {
004010A0   push        ebp
004010A1   mov         ebp,esp
004010A3   sub         esp,54h
004010A6   push        ebx
004010A7   push        esi
004010A8   push        edi
004010A9   lea         edi,[ebp-54h]
004010AC   mov         ecx,15h
004010B1   mov         eax,0CCCCCCCCh
004010B6   rep stos    dword ptr [edi]
14:       int arr[5] = {1,2,3,4,5};
004010B8   mov         dword ptr [ebp-14h],1
004010BF   mov         dword ptr [ebp-10h],2
004010C6   mov         dword ptr [ebp-0Ch],3
004010CD   mov         dword ptr [ebp-8],4
004010D4   mov         dword ptr [ebp-4],5
15:       PrintArray(arr,5);
004010DB   push        5
004010DD   lea         eax,[ebp-14h]
004010E0   push        eax
004010E1   call        @ILT+0(PrintArray) (00401005)
004010E6   add         esp,8
16:
17:       system("pause");
004010E9   push        offset string "pause" (00422020)
004010EE   call        system (004011e0)
004010F3   add         esp,4
18:       return ;
19:   }
004010F6   pop         edi
004010F7   pop         esi
004010F8   pop         ebx
004010F9   add         esp,54h
004010FC   cmp         ebp,esp
004010FE   call        __chkesp (004011a0)
00401103   mov         esp,ebp
00401105   pop         ebp
00401106   ret
--- No source file  --------------------------------------------------------------------------------------------------------------------------------
00401107   int         3

2、用指针来操作数组

数组作为参数时,传递的人是地址

C语言代码

#include<stdio.h>
#include<windows.h>

void PrintArray(int* p, int nLength)
{
	for(int i=0;i<nLength;i++)
	{
		printf("%d\n",*(p+i));
	}
}

void main()
{
	int arr[5] = {1,2,3,4,5};
	PrintArray(&arr[0],5);
	
	system("pause");
	return ;
} 

汇编代码

1:    #include<stdio.h>
2:    #include<windows.h>
3:
4:    void PrintArray(int* p, int nLength)
5:    {
00401020   push        ebp
00401021   mov         ebp,esp
00401023   sub         esp,44h
00401026   push        ebx
00401027   push        esi
00401028   push        edi
00401029   lea         edi,[ebp-44h]
0040102C   mov         ecx,11h
00401031   mov         eax,0CCCCCCCCh
00401036   rep stos    dword ptr [edi]
6:        for(int i=0;i<nLength;i++)
00401038   mov         dword ptr [ebp-4],0
0040103F   jmp         PrintArray+2Ah (0040104a)
00401041   mov         eax,dword ptr [ebp-4]
00401044   add         eax,1
00401047   mov         dword ptr [ebp-4],eax
0040104A   mov         ecx,dword ptr [ebp-4]
0040104D   cmp         ecx,dword ptr [ebp+0Ch]
00401050   jge         PrintArray+4Bh (0040106b)
7:        {
8:            printf("%d\n",*(p+i));
00401052   mov         edx,dword ptr [ebp-4]
00401055   mov         eax,dword ptr [ebp+8]
00401058   mov         ecx,dword ptr [eax+edx*4]
0040105B   push        ecx
0040105C   push        offset string "%d\n" (0042201c)
00401061   call        printf (00401120)
00401066   add         esp,8
9:        }
00401069   jmp         PrintArray+21h (00401041)
10:   }
0040106B   pop         edi
0040106C   pop         esi
0040106D   pop         ebx
0040106E   add         esp,44h
00401071   cmp         ebp,esp
00401073   call        __chkesp (004011a0)
00401078   mov         esp,ebp
0040107A   pop         ebp
0040107B   ret
--- No source file  --------------------------------------------------------------------------------------------------------------------------------
0040107C   int         3
--- C:\Program Files\Microsoft Visual Studio\MyProjects\11\test.cpp  -------------------------------------------------------------------------------
11:
12:   void main()
13:   {
004010A0   push        ebp
004010A1   mov         ebp,esp
004010A3   sub         esp,54h
004010A6   push        ebx
004010A7   push        esi
004010A8   push        edi
004010A9   lea         edi,[ebp-54h]
004010AC   mov         ecx,15h
004010B1   mov         eax,0CCCCCCCCh
004010B6   rep stos    dword ptr [edi]
14:       int arr[5] = {1,2,3,4,5};
004010B8   mov         dword ptr [ebp-14h],1
004010BF   mov         dword ptr [ebp-10h],2
004010C6   mov         dword ptr [ebp-0Ch],3
004010CD   mov         dword ptr [ebp-8],4
004010D4   mov         dword ptr [ebp-4],5
15:       PrintArray(&arr[0],5);
004010DB   push        5
004010DD   lea         eax,[ebp-14h]
004010E0   push        eax
004010E1   call        @ILT+10(PrintArray) (0040100f)
004010E6   add         esp,8
16:
17:       system("pause");
004010E9   push        offset string "pause" (00422020)
004010EE   call        system (004011e0)
004010F3   add         esp,4
18:       return ;
19:   }
004010F6   pop         edi
004010F7   pop         esi
004010F8   pop         ebx
004010F9   add         esp,54h
004010FC   cmp         ebp,esp
004010FE   call        __chkesp (004011a0)
00401103   mov         esp,ebp
00401105   pop         ebp
00401106   ret
--- No source file  --------------------------------------------------------------------------------------------------------------------------------
00401107   int         3

2.17.指针与字符串

1、字符串的几种表示方式有什么区别?

char str[6] = {'A','B','C','D',E','0'};	//结尾要 '\O'或者0
char str[] = "ABCDE", 	//编译器末尾填0
char* str= "ABCDE";		//常量区

//打印
print("%s\n" ,str);

2、常用的字符串函数

1、int strlen (char* s)
返回值是字符串s的长度。不包括结束符'/0'。

2、char* strcpy (char* dest, char* src);
复制字符串src到dest中。返回指针为dest的值。

3、char* strcat (char* dest, char* src);
将字符串src添加到dest尾部。返回指针为dest的值。

4、int strcmp ( char* s1, char* s2);
一样返回0 不一样返回非0

2.18.指针取值的两种方式

1、一级指针和多级指针

c语言代码

#include<stdio.h>
#include<windows.h>

void main()
{
	int i = 100;

	int* p1 = &i;
	int** p2 = &p1;
	int*** p3 = &p2;
	int**** p4 = &p3;
	int***** p5 = &p4;
	int****** p6 = &p5;
	int******* p7 = &p6;

	int y = *******p7;  //y=1

	int z= p7[0][0][0][0][0][0][0]; //z=1 

	
	system("pause");
	return ;
} 

汇编代码

1:    #include<stdio.h>
2:    #include<windows.h>
3:
4:    void main()
5:    {
00401010   push        ebp
00401011   mov         ebp,esp
00401013   sub         esp,68h
00401016   push        ebx
00401017   push        esi
00401018   push        edi
00401019   lea         edi,[ebp-68h]
0040101C   mov         ecx,1Ah
00401021   mov         eax,0CCCCCCCCh
00401026   rep stos    dword ptr [edi]
6:        int i = 100;
00401028   mov         dword ptr [ebp-4],64h
7:
8:        int* p1 = &i;
0040102F   lea         eax,[ebp-4]
00401032   mov         dword ptr [ebp-8],eax
9:        int** p2 = &p1;
00401035   lea         ecx,[ebp-8]
00401038   mov         dword ptr [ebp-0Ch],ecx
10:       int*** p3 = &p2;
0040103B   lea         edx,[ebp-0Ch]
0040103E   mov         dword ptr [ebp-10h],edx
11:       int**** p4 = &p3;
00401041   lea         eax,[ebp-10h]
00401044   mov         dword ptr [ebp-14h],eax
12:       int***** p5 = &p4;
00401047   lea         ecx,[ebp-14h]
0040104A   mov         dword ptr [ebp-18h],ecx
13:       int****** p6 = &p5;
0040104D   lea         edx,[ebp-18h]
00401050   mov         dword ptr [ebp-1Ch],edx
14:       int******* p7 = &p6;
00401053   lea         eax,[ebp-1Ch]
00401056   mov         dword ptr [ebp-20h],eax
15:
16:       int y = *******p7;  //y=1
00401059   mov         ecx,dword ptr [ebp-20h]
0040105C   mov         edx,dword ptr [ecx]
0040105E   mov         eax,dword ptr [edx]
00401060   mov         ecx,dword ptr [eax]
00401062   mov         edx,dword ptr [ecx]
00401064   mov         eax,dword ptr [edx]
00401066   mov         ecx,dword ptr [eax]
00401068   mov         edx,dword ptr [ecx]
0040106A   mov         dword ptr [ebp-24h],edx
17:
18:       int z= p7[0][0][0][0][0][0][0]; //z=1
0040106D   mov         eax,dword ptr [ebp-20h]
00401070   mov         ecx,dword ptr [eax]
00401072   mov         edx,dword ptr [ecx]
00401074   mov         eax,dword ptr [edx]
00401076   mov         ecx,dword ptr [eax]
00401078   mov         edx,dword ptr [ecx]
0040107A   mov         eax,dword ptr [edx]
0040107C   mov         ecx,dword ptr [eax]
0040107E   mov         dword ptr [ebp-28h],ecx
19:
20:
21:       system("pause");
00401081   push        offset string "pause" (0042201c)
00401086   call        system (004010d0)
0040108B   add         esp,4
22:       return ;
23:   }
0040108E   pop         edi
0040108F   pop         esi
00401090   pop         ebx
00401091   add         esp,68h
00401094   cmp         ebp,esp
00401096   call        __chkesp (004011e0)
0040109B   mov         esp,ebp
0040109D   pop         ebp
0040109E   ret
--- No source file  --------------------------------------------------------------------------------------------------------------------------------
0040109F   int         3

2、总结:

*(p+i)= p[i]
*(*(p+i)+k) = p[i][k]
*(*(*(p+i)+k)+m) = p[i][k][m]
(*(p+i)+k)+m)+W)+t) = p[jIk]Im][W[t]

*()与[]可以相互转换

2.19.结构体指针

通过结构体指针读取和修改值

#include<stdio.h>
#include<stdlib.h>
#include<windows.h>

Point{
	int x;
	int y;
}

void main()
{
	Point p = {1,2};

	Point* px = &p;
	
	int x = px->x;        //x=1
	px->y =100;
	int u = px->y;		  //y=100

	system("pause");
	return ;
} 

2.20.指针数组和数组指针

1、指针数组的定义

char arr[10];   	 //10 char
char* arr[10];		 //10 指针(char*)	 每个成员4字节
Point* arr[10];		 //10 指针(Point*) 每个成员4字节
int******* arr[10];	  // //10 指针(int*******) 每个成员4字节

2、指针数组的赋值

char* a = "hello";  //a存的是地址,里面存放的值是 “hello”
char* b = "你好";

//汇编代码
7:        char* a = "hello";
00401028   mov         dword ptr [ebp-4],offset string "hello" (004230cc)
8:        char* b = "你好";
0040102F   mov         dword ptr [ebp-8],offset string "\xc4\xe3\xba\xc3" (004230c4)
char* arr1[2] = {a,b};    //存放两个地址a和b

char* arr2[2] = {"hello","你好"};   //存放的也是两个地址
    
//汇编代码
7:        char* a = "hello";
00401028   mov         dword ptr [ebp-4],offset string "hello" (0042202c)
8:        char* b = "你好";
0040102F   mov         dword ptr [ebp-8],offset string "\xc4\xe3\xba\xc3" (00422024)
9:
10:       char* arr1[2] = {a,b};
00401036   mov         eax,dword ptr [ebp-4]
00401039   mov         dword ptr [ebp-10h],eax
0040103C   mov         ecx,dword ptr [ebp-8]
0040103F   mov         dword ptr [ebp-0Ch],ecx
11:       char* arr2[2] = {"hello","你好"};
00401042   mov         dword ptr [ebp-18h],offset string "hello" (0042202c)
00401049   mov         dword ptr [ebp-14h],offset string "\xc4\xe3\xba\xc3" (00422024)

3、结构体指针数组

struct Point
{
    int x;
    int y;
};

Point p;	//8字节
Point arr[10];	//8x10字节
Point* arrPoint[10;	//4x10字节

4、数组指针的定义

int(*px)[5];
char(*px)[5];	//一维数组指针

int(*px)[5][4];	//二维数组指针

5、数组指针的宽度与赋值

int(*px1) [5];	//一维数组指针
char(*px2) [3];
int(*px3) [2][2];	//二维数组指针
char(*px4) [3][3][3);	//三维数组指针
print("%d %d %d %d \n" ,sizeof(px1),sizeof(px2),sizeof(px3),sizeof(px4));   //4 4 4 4
                  
px1 = (int (*)[5])1;
px2 = (char (*)[(3])2;
px3 = (int (*)[2][2])3;
px4 = (char (*)[3][3][3])4;

6、数组指针的使用

#include<stdio.h>
#include<stdlib.h>
#include<windows.h>

void main()
{
	int arr[] = {1,2,3,4,5,6,7,8,9,0};

	int(*px)[10] = &arr;

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

	system("pause");
	return ;
} 
#include<stdio.h>
#include<stdlib.h>
#include<windows.h>

void main()
{
	int arr[3][3] = 
	{
		{1,2,3},
		{4,5,6},
		{7,8,9}
	};
	
	int(*px)[3] = &arr[0];

	printf("%d %d\n",(*px)[0],(*px)[2]);    //1  3

	px++;

	printf("%d %d\n",(*px)[0],(*px)[2]);	//4  6

	system("pause");
	return ;
} 

2.21.常见的几种调用约定:

三种常见调用约定

调用约定			参数压栈顺序			  平衡堆栈
cdecl			   从右至左入栈		   调用者清理栈

stdcall			   从右至左入栈		   自身清理堆栈

_ _fastcall     ECX/EDX传送前两个          自身清理堆栈
                剩下:从右至左入栈

2.22.函数指针

1、函数指针类型变量的定义
函数指针变量定义的格式:

返回类型(调用约定 *变量名)(参数列表);
如:
int ( _cdecl *pFun)(int,int);

2、通过函数指针绕过断点

<1>函数指针变量的定义
int (__stdcall *pFun)(int,int,int,int,int);

<2>正常调用
MessaleBox(0,0,0,0);

<3>通过函数指针绕过断点
pFun = (int (__stdcall *)(int,int,int,int,int))0x77D5055C;
pFun(0,0,0,0,0);

2.23.预处理之宏定义

1、什么是预处理:
预处理一般是指在程序源代码被转换为二进制代码之前,由预处理器对程序源代码文本进行处理处理后的结再由编译器进- -步编译。
预处理功能主要包括宏定义,文件包含,条件编译三部分

2、宏定义

<1>简单宏: #define 标识符字符序列
# define FALSE 0
# define NAME "测试"
# define_ IN
# define__ OUT

<2>带参数的宏: #define 标识符(参数表)字符序列
#define MAX(A,B) ((A)> (B)?(A):(B))

注意事项:
1、只作字符序列的替换工作,不作任何语法的检查,在编译前处理。
2、宏名标识符与左圆括号之间不允许有空白符,应紧接在- -起。
3、为了避免出错,宏定义中给形参加上括号。
4、多行声明时,回车换行前要加上字符‘\’,即“[enter]” ,注意字符
‘\’ 后要紧跟回车键,中间不能有空格或其他字符。
5、末尾不需要分号。

2.24.条件编译与文件包含

1、什么是条件编译?

#if 0
	printf("------")
#endif        

2、预处理指令:条件编译是通过预处理指令实现的
image
3、文件包含有两种格式
分别是: #include “file”和#include
1.使用双引号,系统首先到当前目录下查找被包含的文件,如果没找到,再到系
统指定的”包含文件目录” (由用户在配置环境时设置)去找。
2.使用尖括号:直接到系统指定的”包含文件目录”去查找。
总结:
系统文件用<>
自己定义的文件用””

4、如何解决重复包含问题

  • 条件编译
  • 前置声明

版权声明:本文为derek1184405959原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/derek1184405959/p/14636602.html