Bootstrap

C语言与汇编

函数调用

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

int main()
{
	
	plus(1, 2);

	return 0;
}

对应的汇编分析

plus(1, 2);
00231DAF  push        2                                    将参数2压入堆栈              参数的入栈顺序是从右往左
00231DB1  push        1                                    将参数1压入堆栈
00231DB3  call        00231370                        调用plus      这里使用vs2017   00231370是一个jmp 002318B0
00231DB8  add         esp,8                              平衡堆栈   2个参数 

 

int plus(int x, int y)
{
002318B0  push        ebp                                   将ebp压入堆栈临时保存
002318B1  mov         ebp,esp                             ebp = esp
002318B3  sub         esp,0C0h                            开辟方法栈空间      48(0x30)个空间
002318B9  push        ebx                                     保存ebx       保存现场
002318BA  push        esi                                      保存ebx       保存现场
002318BB  push        edi                                      保存edi       保存现场
002318BC  lea         edi,[ebp+FFFFFF40h]          [ebp+FFFFFF40h] = [ebp - 0c0H]  
002318C2  mov         ecx,30h                               ecx = 0x30   循环0x30次    用于将新开辟的栈空间 置0xcc
002318C7  mov         eax,0CCCCCCCCh            eax = 0xCCCCCCCC         0xcc表示断点如果访问出问题可以断点异常
002318CC  rep stos    dword ptr es:[edi]               将 eax的值存入 [edi] 然后edi +=4    rep 按(ecx)中的次数重复执行字符串指令
002318CE  mov         ecx,23B000h  
002318D3  call        00231203  
    
    return x + y;             这里我重新编译了一下代码地址有点问题
                   mov         eax,dword ptr [ebp+8]             函数参数1  最后一个压入堆栈的参数
                   add          eax,dword ptr  [ebp+0Ch]         函数参数2 
}
002318DA  pop         edi                                         从堆栈中拿出 edi   还原现场
002318DB  pop         esi                                        从堆栈中拿出 esi   还原现场
002318DC  pop         ebx                                        从堆栈中拿出 ebx   还原现场
002318DD  add         esp,0C0h                               释放栈空间                
002318E3  cmp         ebp,esp            
002318E5  call        0023120D  
002318EA  mov         esp,ebp                                  esp  = ebp   恢复 esp 
002318EC  pop         ebp                                           恢复ebp
002318ED  ret                                                            函数返回

堆栈变化

变量

全局变量

1)编译的时候就已经确定了内存地址和宽度,变量名就是内存地址的别名。

2)如果不重写编译,全局变量的内存地址不变。游戏外挂中的找“基址”,其实就是找全局变量。|

3)全局变量中的值任何函数都可以改,是公用的。

例子:CE搜索基址

int x;
int main()
{
	x = 0x456;

	return 0;
}

    x = 0x456;
00EF1DA8  mov         dword ptr ds:[00EF9148h],456h           将0x456保存到全局变量中

 

局部变量

1)局部变量是函数内部申请的,如果函数没有执行,那么局部变量没有内存空间。

2)局部变量的内存是在堆栈中分配的,程序执行时才分配。我们无法预知程序何时执行,这也就意味着,我们无法确定局部变量的内存地址。

3)因为局部变量地址内存是不确定的,所以,局部变量只能在函数内部使用,其他函数不能使用。

函数参数和局部变量在方法中的访问

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

int main()
{
	plus(1, 2);

	return 0;
}

对应汇编

int main()
{
00311D80  push        ebp  
00311D81  mov         ebp,esp  
00311D83  sub         esp,0C0h  
00311D89  push        ebx  
00311D8A  push        esi  
00311D8B  push        edi  
00311D8C  lea         edi,[ebp+FFFFFF40h]  
00311D92  mov         ecx,30h  
00311D97  mov         eax,0CCCCCCCCh  
00311D9C  rep stos    dword ptr es:[edi]  
00311D9E  mov         ecx,31B000h  
00311DA3  call        00311203  
    plus(1, 2);
00311DA8  push        2  
00311DAA  push        1  
    plus(1, 2);
00311DAC  call        00311370  
00311DB1  add         esp,8  

    return 0;
00311DB4  xor         eax,eax  
}
00311DB6  pop         edi  
00311DB7  pop         esi  
00311DB8  pop         ebx  
00311DB9  add         esp,0C0h  
00311DBF  cmp         ebp,esp  
00311DC1  call        0031120D  
00311DC6  mov         esp,ebp  
00311DC8  pop         ebp  
00311DC9  ret  

 

int plus(int x, int y)
{
003124A0  push        ebp  
003124A1  mov         ebp,esp  
003124A3  sub         esp,0CCh  
003124A9  push        ebx  
003124AA  push        esi  
003124AB  push        edi  
003124AC  lea         edi,[ebp+FFFFFF34h]  
003124B2  mov         ecx,33h  
003124B7  mov         eax,0CCCCCCCCh  
003124BC  rep stos    dword ptr es:[edi]  
003124BE  mov         ecx,31B000h  
003124C3  call        00311203  
    int z = x + y;
003124C8  mov         eax,dword ptr [ebp+8]  
003124CB  add         eax,dword ptr [ebp+0Ch]  
003124CE  mov         dword ptr [ebp-8],eax  
    return z;
003124D1  mov         eax,dword ptr [ebp-8]  
}
003124D4  pop         edi  
003124D5  pop         esi  
003124D6  pop         ebx  
003124D7  add         esp,0CCh  
003124DD  cmp         ebp,esp  
003124DF  call        0031120D  
003124E4  mov         esp,ebp  
003124E6  pop         ebp  
003124E7  ret  

 

数据类型与数据存储

C语言数据类型汇编数据宽度
charbyte
shortword
intdword
longdword
  1. 无符号跟有符号,在内存中存储的是一样的,根据使用的人来决定

  2. 默认有符号,类型转换--比较大小--数学运算要注意

  3. jbe跟jle 低于等于,小于等于

 

浮点类型

这部分就是计算机组成原理

float的存储方法

12.5 在内存中存储为

整数部分: 12

计算余数
12/2=60
6/2=30
3/2=11
1/2=01

从下往上: 1100

小数部分: 0.5

计算小数
0.5*2=1.01

从上往下:1

1100.1=1.1001*2的3次方

1位符号位 中间8位指数 后面23位尾数

尾数从左往右写就行

中间8位开头,左移为1,右移为0,

后面7位,存储指数-1,比如3次方,就是存10,如果是-2次方就是-3,也就是fd, 11111101,然后只取后7位

127 +(3) = 130 = 0x82 = 1000 0010 这里直接加指数

0 10000010 10010000000000000000000

0100 0001 0100 1000 0000 0000 0000 0000

41480000

如果是-12.5呢

就变成

1100 0001 0100 1000 0000 0000 0000 0000

C1480000

编码

ASCII 英文字符

GB2312或GB2312-80 中文字符中国定义的中文标准,两个字节一个汉字(两个大于127的字符表示一个中文)

在半角的情况下英文字符不变占一个字节,全角的情况下英文也被重新定义用2个字节表示    

分支语句

if else语句

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

	if (x > y)
	{
		printf("true");
	}
	else
	{
		printf("false");
	}
	return 0;
}


int main()
{
01381870  push        ebp                                  保存ebp
01381871  mov         ebp,esp                              ebp作为新的栈底
01381873  sub         esp,0D8h                             开辟局部变量空间 
01381879  push        ebx                                  保存现场
0138187A  push        esi                                  保存现场
0138187B  push        edi                                  保存现场
0138187C  lea         edi,[ebp+FFFFFF28h]                  初始化局部变量开始的位置                 
01381882  mov         ecx,36h                              循环次数
01381887  mov         eax,0CCCCCCCCh                       局部变量的初值
0138188C  rep stos    dword ptr es:[edi]                   填充初值
0138188E  mov         ecx,138C003h                         
01381893  call        01381217  
	int x = 10;
01381898  mov         dword ptr [ebp-8],0Ah                局部变量x 初值
	int y = 20;
0138189F  mov         dword ptr [ebp-14h],14h              局部变量y 初值

	if (x > y)
013818A6  mov         eax,dword ptr [ebp-8]                把局部变量x赋值给eax
013818A9  cmp         eax,dword ptr [ebp-14h]              比较x和y  
013818AC  jle         013818BD                             小于或等于跳转(这里是会跳转)
	{
		printf("true");
013818AE  push        1387B30h                              参数压入堆栈
013818B3  call        0138104B                              调用printf
013818B8  add         esp,4                                  平栈
	}    
	else
013818BB  jmp         013818CA                              执行完true部分的代码直接跳走
	{
		printf("false");
013818BD  push        1387B38h  
013818C2  call        0138104B  
013818C7  add         esp,4  
	}
	return 0;
013818CA  xor         eax,eax  
}

if else if

int main()
{
	int n = 10;
	if (n == 1)
	{
		printf("1");
	}
	else if(n == 10)
	{
		printf("10");
	}
	else if (n == 20)
	{
		printf("20");
	}
	else
	{
		printf("else");
	}
	return 0;
}


int main()
{
01184EB0  push        ebp  
01184EB1  mov         ebp,esp  
01184EB3  sub         esp,0CCh  
01184EB9  push        ebx  
01184EBA  push        esi  
01184EBB  push        edi  
01184EBC  lea         edi,[ebp+FFFFFF34h]  
01184EC2  mov         ecx,33h  
01184EC7  mov         eax,0CCCCCCCCh  
01184ECC  rep stos    dword ptr es:[edi]  
01184ECE  mov         ecx,118C003h  
01184ED3  call        01181217  
	int n = 10;
01184ED8  mov         dword ptr [ebp-8],0Ah     局部变量10
	if (n == 1)
01184EDF  cmp         dword ptr [ebp-8],1       局部变量和1比较
01184EE3  jne         01184EF4               不相等的时候跳转到下一个判断  相等执行里面的内容
	{
		printf("1");
01184EE5  push        1187B30h  
01184EEA  call        0118104B  
01184EEF  add         esp,4  
01184EF2  jmp         01184F2B                  跳到if结束的后一条语句
	}
	else if(n == 10)
01184EF4  cmp         dword ptr [ebp-8],0Ah       局部变量和10比较
01184EF8  jne         01184F09                    不相等时跳转到下一个判断
	{
		printf("10");
01184EFA  push        1187B38h  
01184EFF  call        0118104B  
01184F04  add         esp,4  
01184F07  jmp         01184F2B                 里面的内容执行完毕后跳出整个if
	}
	else if (n == 20)
01184F09  cmp         dword ptr [ebp-8],14h       局部变量和20比较
01184F0D  jne         01184F1E                    不相等时跳转到else
	{
		printf("20");
01184F0F  push        1187B34h  
01184F14  call        0118104B  
01184F19  add         esp,4  
	}
	else
01184F1C  jmp         01184F2B                     里面的内容执行完毕后跳出整个if
	{
		printf("else");
01184F1E  push        1187BE8h  
01184F23  call        0118104B  
01184F28  add         esp,4  
	}
	return 0;
01184F2B  xor         eax,eax  
}

switch语句

小于3个分支

int main()
{
	int n = 10;
	switch (n)
	{
	case 1:
	{
		printf("1");
	}
	break;
	case 2:
	{
		printf("2");
	}
	case 3:
	{
		printf("3");
	}
	break;
	default:
	{
		printf("default");
	}
		break;
	}
	return 0;
}



int main()
{
01151850  push        ebp  
01151851  mov         ebp,esp  
01151853  sub         esp,0D0h  
01151859  push        ebx  
0115185A  push        esi  
0115185B  push        edi  
0115185C  lea         edi,[ebp+FFFFFF30h]  
01151862  mov         ecx,34h  
01151867  mov         eax,0CCCCCCCCh  
0115186C  rep stos    dword ptr es:[edi]  
0115186E  mov         ecx,115C003h  
01151873  call        01151217  
	int n = 10;
01151878  mov         dword ptr [ebp-8],0Ah                 局部变量n赋初值
	switch (n)
0115187F  mov         eax,dword ptr [ebp-8]                 局部变量赋值给eax
01151882  mov         dword ptr [ebp+FFFFFF30h],eax         eax传给一个临时局部变量
01151888  cmp         dword ptr [ebp+FFFFFF30h],1           这个临时局部变量和1比较
0115188F  je          011518A5                              je相等时跳转到case 1处执行
01151891  cmp         dword ptr [ebp+FFFFFF30h],2           和2比较
01151898  je          011518B4                              je相等时跳转到case 2处执行
0115189A  cmp         dword ptr [ebp+FFFFFF30h],3           和3比较
011518A1  je          011518C1                              je相等时跳转到case 3处执行
011518A3  jmp         011518D0                              如果都不能跳转跳到default
	{
	case 1:
	{
		printf("1");
011518A5  push        1157B30h  
011518AA  call        0115104B  
011518AF  add         esp,4  
	}
	break;
011518B2  jmp         011518DD  
	case 2:
	{
		printf("2");
011518B4  push        1157B38h  
011518B9  call        0115104B  
011518BE  add         esp,4  
	}
	case 3:                                    这里case 2没有写break也就没有了jmp
	{
		printf("3");
011518C1  push        1157B34h  
011518C6  call        0115104B  
011518CB  add         esp,4  
	}
	break;
011518CE  jmp         011518DD  
	default:
	{
		printf("default");
011518D0  push        1157BDCh  
011518D5  call        0115104B  
011518DA  add         esp,4  
	}
		break;
	}
	return 0;
011518DD  xor         eax,eax              返回0
}

增加分支

int main()
{
	int n = 10;
	switch (n)
	{
	case 1:
	{
		printf("1");
	}
	break;
	case 2:
	{
		printf("2");
	}
	case 3:
	{
		printf("3");
	}
	break;
	case 4:
	{
		printf("4");
	}
	break;
	case 10:
	{
		printf("10");
	}
	break;
	default:
	{
		printf("default");
	}
		break;
	}
	return 0;
}



int main()
{
011B4EB0  push        ebp  
011B4EB1  mov         ebp,esp  
011B4EB3  sub         esp,0D0h  
011B4EB9  push        ebx  
011B4EBA  push        esi  
011B4EBB  push        edi  
011B4EBC  lea         edi,[ebp+FFFFFF30h]  
011B4EC2  mov         ecx,34h  
011B4EC7  mov         eax,0CCCCCCCCh  
011B4ECC  rep stos    dword ptr es:[edi]  
011B4ECE  mov         ecx,11BC003h  
011B4ED3  call        011B1217  
	int n = 10;
011B4ED8  mov         dword ptr [ebp-8],0Ah                   临时局部变量10
	switch (n)
011B4EDF  mov         eax,dword ptr [ebp-8]  
011B4EE2  mov         dword ptr [ebp+FFFFFF30h],eax  
011B4EE8  mov         ecx,dword ptr [ebp+FFFFFF30h]  
011B4EEE  sub         ecx,1                       减去case的最小值 所有case值从0开始重新计算
011B4EF1  mov         dword ptr [ebp+FFFFFF30h],ecx  
011B4EF7  cmp         dword ptr [ebp+FFFFFF30h],9  //case最大值-最小值也就是重新计算后的最大值
011B4EFE  ja          011B4F56                          大于直接跳转到default
011B4F00  mov         edx,dword ptr [ebp+FFFFFF30h]     将重新计算的case值 从0开始
011B4F06  jmp         dword ptr [edx*4+011B4F7Ch]  用一个数组保存所有case的地址 
	{
	case 1:
	{
		printf("1");
011B4F0D  push        11B7B30h  
011B4F12  call        011B104B  
011B4F17  add         esp,4  
	}
	break;
011B4F1A  jmp         011B4F63  
	case 2:
	{
		printf("2");
011B4F1C  push        11B7B38h  
	case 2:
	{
		printf("2");
011B4F21  call        011B104B  
011B4F26  add         esp,4  
	}
	case 3:
	{
		printf("3");
011B4F29  push        11B7B34h  
011B4F2E  call        011B104B  
011B4F33  add         esp,4  
	}
	break;
011B4F36  jmp         011B4F63  
	case 4:
	{
		printf("4");
011B4F38  push        11B7BDCh  
011B4F3D  call        011B104B  
011B4F42  add         esp,4  
	}
	break;
011B4F45  jmp         011B4F63  
	case 10:
	{
		printf("10");
011B4F47  push        11B7B3Ch  
011B4F4C  call        011B104B  
011B4F51  add         esp,4  
	}
	break;
011B4F54  jmp         011B4F63  
	default:
	{
		printf("default");
011B4F56  push        11B7BE0h  
011B4F5B  call        011B104B  
011B4F60  add         esp,4  
	}
		break;
	}
	return 0;
011B4F63  xor         eax,eax                   返回0
}

上面的地址表     [edx*4+011B4F7Ch]

0x011B4F7C  0d 4f 1b 01        重新计算的case 0  原来的case 1
0x011B4F80  1c 4f 1b 01         重新计算的case 1  原来的case 2
0x011B4F84  29 4f 1b 01         重新计算的case 2  原来的case 3
0x011B4F88  38 4f 1b 01          重新计算的case 3  原来的case4
0x011B4F8C  56 4f 1b 01         重新计算的case 4  原来的case5     没有这个case所以地址为defalut的地址
0x011B4F90  56 4f 1b 01          重新计算的case 5  原来的case6    没有这个case所以地址为defalut的地址
0x011B4F94  56 4f 1b 01         
0x011B4F98  56 4f 1b 01  
0x011B4F9C  56 4f 1b 01  
0x011B4FA0  47 4f 1b 01        重新计算的case 9  原来的case10    

 

大于255就采用了平衡二叉树方式优化算法

 

循环语句

for循环

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

	return 0;
}




int main()
{
00824EB0  push        ebp  
00824EB1  mov         ebp,esp  
00824EB3  sub         esp,0CCh  
00824EB9  push        ebx  
00824EBA  push        esi  
00824EBB  push        edi  
00824EBC  lea         edi,[ebp+FFFFFF34h]  
00824EC2  mov         ecx,33h  
00824EC7  mov         eax,0CCCCCCCCh  
00824ECC  rep stos    dword ptr es:[edi]  
00824ECE  mov         ecx,82C003h  
00824ED3  call        00821217  
	for (int i  = 0; i < 10; i++)
00824ED8  mov         dword ptr [ebp-8],0               局部变量初始0
00824EDF  jmp         00824EEA                          无条件跳到判断语句
00824EE1  mov         eax,dword ptr [ebp-8]             循环变量赋值给eax
00824EE4  add         eax,1                             eax自增1
00824EE7  mov         dword ptr [ebp-8],eax             eax传给循环变量
00824EEA  cmp         dword ptr [ebp-8],0Ah             比较循环变量和10
00824EEE  jge         00824F03                          大于等于跳出循环
	{
		printf("%d\n", i);
00824EF0  mov         eax,dword ptr [ebp-8]             执行循环体
00824EF3  push        eax  
00824EF4  push        827B30h  
00824EF9  call        0082104B  
00824EFE  add         esp,8  
	}
00824F01  jmp         00824EE1                    循环体执行完毕后,无条件跳到循环变量自增

	return 0;
00824F03  xor         eax,eax  
}

 

while循环

int main()
{
	int i = 0;
	while (i < 10)
	{
		printf("%d\n", i);
		i++;
	}

	return 0;
}





int main()
{
01054EB0  push        ebp  
01054EB1  mov         ebp,esp  
01054EB3  sub         esp,0CCh  
01054EB9  push        ebx  
01054EBA  push        esi  
01054EBB  push        edi  
01054EBC  lea         edi,[ebp+FFFFFF34h]  
01054EC2  mov         ecx,33h  
01054EC7  mov         eax,0CCCCCCCCh  
01054ECC  rep stos    dword ptr es:[edi]  
01054ECE  mov         ecx,105C003h  
01054ED3  call        01051217  
	int i = 0;
01054ED8  mov         dword ptr [ebp-8],0             局部变量初值
	while (i < 10)
01054EDF  cmp         dword ptr [ebp-8],0Ah           局部变量和10比价
01054EE3  jge         01054F01                        大于等于跳转
	{
		printf("%d\n", i);
01054EE5  mov         eax,dword ptr [ebp-8]           循环体内容
01054EE8  push        eax  
01054EE9  push        1057B30h  
01054EEE  call        0105104B                        打印i
01054EF3  add         esp,8                           平栈
		i++;
01054EF6  mov         eax,dword ptr [ebp-8]           局部变量传给eax
01054EF9  add         eax,1                           eax自增1
01054EFC  mov         dword ptr [ebp-8],eax           eax传给局部变量
	}
01054EFF  jmp         01054EDF                        跳到判断

	return 0;
01054F01  xor         eax,eax                          返回0
}

do while循环

int main()
{
	int i = 0;
	do 
	{
		printf("%d\n", i);
		i++;
	} while (i < 10);

	return 0;
}





int main()
{
01214EB0  push        ebp  
01214EB1  mov         ebp,esp  
01214EB3  sub         esp,0CCh  
01214EB9  push        ebx  
01214EBA  push        esi  
01214EBB  push        edi  
01214EBC  lea         edi,[ebp+FFFFFF34h]  
01214EC2  mov         ecx,33h  
01214EC7  mov         eax,0CCCCCCCCh  
01214ECC  rep stos    dword ptr es:[edi]  
01214ECE  mov         ecx,121C003h  
01214ED3  call        01211217  
	int i = 0;
01214ED8  mov         dword ptr [ebp-8],0             局部变量初值
	do 
	{
		printf("%d\n", i);                            循环体内容
01214EDF  mov         eax,dword ptr [ebp-8]  
01214EE2  push        eax  
01214EE3  push        1217B30h  
01214EE8  call        0121104B                        打印i
01214EED  add         esp,8  
		i++;
01214EF0  mov         eax,dword ptr [ebp-8]           自增1
01214EF3  add         eax,1  
01214EF6  mov         dword ptr [ebp-8],eax  
	} while (i < 10);
01214EF9  cmp         dword ptr [ebp-8],0Ah          局部变量和10比较
01214EFD  jl          01214EDF                       小于跳转到循环体

	return 0;
01214EFF  xor         eax,eax  
}

数组

一维数组

int main()
{
	int arr[5] = { 1, 2, 3, 4, 5 };
	for (int i = 0; i < 5; i++)
	{
		printf("%d\n", arr[i]);
	}

	system("pause");
	return 0;
}


int main()
{
011E1D50  push        ebp  
011E1D51  mov         ebp,esp  
011E1D53  sub         esp,0E8h  
011E1D59  push        ebx  
011E1D5A  push        esi  
011E1D5B  push        edi  
011E1D5C  lea         edi,[ebp+FFFFFF18h]  
011E1D62  mov         ecx,3Ah  
011E1D67  mov         eax,0CCCCCCCCh  
011E1D6C  rep stos    dword ptr es:[edi]  
011E1D6E  mov         ecx,11F0028h  
011E1D73  call        011E133E  
	int arr[5] = { 1, 2, 3, 4, 5 };
011E1D78  mov         dword ptr [ebp-18h],1           数组初始化  数组元素0赋值1
011E1D7F  mov         dword ptr [ebp-14h],2           数组初始化  数组元素1赋值2
011E1D86  mov         dword ptr [ebp-10h],3           数组初始化  数组元素2赋值3
011E1D8D  mov         dword ptr [ebp-0Ch],4           数组初始化  数组元素3赋值4
011E1D94  mov         dword ptr [ebp-8],5             数组初始化  数组元素4赋值5
	for (int i = 0; i < 5; i++)
011E1D9B  mov         dword ptr [ebp-24h],0           循环变量初始为0
011E1DA2  jmp         011E1DAD                        跳到判断语句
011E1DA4  mov         eax,dword ptr [ebp-24h]  
011E1DA7  add         eax,1  
011E1DAA  mov         dword ptr [ebp-24h],eax  
011E1DAD  cmp         dword ptr [ebp-24h],5           循环变量和5比较
011E1DB1  jge         011E1DCD                        大于等于跳转
	{
		printf("%d\n", arr[i]);
011E1DB3  lfence  
011E1DB6  mov         eax,dword ptr [ebp-24h]            循环变量
011E1DB9  mov         ecx,dword ptr [ebp+eax*4-18h]  数组开始地址ebp-18H  eax*4为偏移int大小为4
011E1DBD  push        ecx                             打印函数
011E1DBE  push        11EBB54h  
011E1DC3  call        011E15AA  
011E1DC8  add         esp,8  
	}
011E1DCB  jmp         011E1DA4                         跳到判断语句是否继续循环

	system("pause");
011E1DCD  mov         esi,esp  
011E1DCF  push        11EBB30h  
011E1DD4  call        dword ptr ds:[011EF1E0h]  
011E1DDA  add         esp,4  
011E1DDD  cmp         esi,esp  
011E1DDF  call        011E1357  
	return 0;
011E1DE4  xor         eax,eax  
}

多维数组

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

	printf("%d\n", arr[1][2]);

	system("pause");
	return 0;
}


int main()
{
01091D53  sub         esp,0F8h  
01091D59  push        ebx  
01091D5A  push        esi  
01091D5B  push        edi  
01091D5C  lea         edi,[ebp+FFFFFF08h]  
01091D62  mov         ecx,3Eh  
01091D67  mov         eax,0CCCCCCCCh  
01091D6C  rep stos    dword ptr es:[edi]  
01091D6E  mov         ecx,10A0028h  
01091D73  call        0109133E  
	int arr[][4] = { 1,2,3,4,5,6,7,8,9,10,11,12 };
01091D78  mov         dword ptr [ebp-34h],1           多维数组初始化和一维数组没有区别
01091D7F  mov         dword ptr [ebp-30h],2  
01091D86  mov         dword ptr [ebp-2Ch],3  
01091D8D  mov         dword ptr [ebp-28h],4  
01091D94  mov         dword ptr [ebp-24h],5  
01091D9B  mov         dword ptr [ebp-20h],6  
01091DA2  mov         dword ptr [ebp-1Ch],7  
01091DA9  mov         dword ptr [ebp-18h],8  
01091DB0  mov         dword ptr [ebp-14h],9  
01091DB7  mov         dword ptr [ebp-10h],0Ah  
01091DBE  mov         dword ptr [ebp-0Ch],0Bh  
01091DC5  mov         dword ptr [ebp-8],0Ch  

	printf("%d\n", arr[1][2]);
01091DCC  mov         eax,10h                        二维数组的列数为4 int大小为4 4*4=10h
01091DD1  shl         eax,0                          左移0位
01091DD4  lea         ecx,[ebp+eax-34h]              行地址为ebp-34数组开始地址+eax数组偏移个数
01091DD8  mov         edx,4                          int大小
01091DDD  shl         edx,1                          左移1位   *2 
01091DDF  mov         eax,dword ptr [ecx+edx]        数组行地址加上第二个元素的位置8  4*2
01091DE2  push        eax  
01091DE3  push        109BB54h  
01091DE8  call        010915AA  
01091DED  add         esp,8  

	system("pause");
01091DF0  mov         esi,esp  
01091DF2  push        109BB30h  
01091DF7  call        dword ptr ds:[0109F1E0h]  
01091DFD  add         esp,4  
01091E00  cmp         esi,esp  
01091E02  call        01091357  
	return 0;
01091E07  xor         eax,eax  
}

调用约定

常用的调用约定分为四种:

_stdcall(windowsAPI默认调用方式):参数压栈方式右到左,函数内平衡,函数结束ret xxx   注意使用windows API函数指针时

声明的时候要带_stdcall

_cdecl(c/c++默认调用方式):参数压栈方式右到左,函数外平衡堆栈,call后面跟着add esp,xxx

_fastcall:参数压栈方式右到左,寄存器方式传参,函数内平衡堆栈

_thiscall:参数压栈方式右到左,ecx传递this指针,函数内平衡堆栈
————————————————
版权声明:本文为CSDN博主「ly1390811049」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/ly1390811049/article/details/104933854

;