循环语句的反汇编分析

for语句的句法

在这里插入图片描述

实例分析1

汇编代码的一般顺序:表达式1----->表达式3-----》表达式2,如下图
在这里插入图片描述
也可以如下汇编代码所示,按正常的顺序逻辑:1—2----3

1	mov eax,[ebp+8]//赋初值
2	mov [ebp-4],eax
	
3	mov edx,[ebp-4]//条件判断
4	cmp edx,[ebp-Ch]
5	jge  16
	
6	mov eax,[ebp-4]//循环体
7	push eax
8	push offset string "%d\n"
9	call 
10	add esp,8
11	jmp 12


12	mov ecx,[ebp-4]
13	add ecx,1
14	mov [ebp-4],ecx
15	jmp  3
16  end;

总结
第一个JMP之前为赋初值部分;
附一个JMP跳转的地址为循环条件判断部分起始;
判断条件后面的跳转指令成立时跳转的循环体外面;
条件判断跳转指令所指向的地址上面有个JMP地址为表达式3的起始位置;

实例分析2

优化外层循环的冒泡排序
在这里插入图片描述

//冒泡排序--外层循环优化
int arr[10] = { 0,1,2,3,4,5,6,7,8,9 };
00BD1AA5  mov         dword ptr [arr],0  
00BD1AAC  mov         dword ptr [ebp-28h],1  
00BD1AB3  mov         dword ptr [ebp-24h],2  
00BD1ABA  mov         dword ptr [ebp-20h],3  
00BD1AC1  mov         dword ptr [ebp-1Ch],4  
00BD1AC8  mov         dword ptr [ebp-18h],5  
00BD1ACF  mov         dword ptr [ebp-14h],6  
00BD1AD6  mov         dword ptr [ebp-10h],7  
00BD1ADD  mov         dword ptr [ebp-0Ch],8  
00BD1AE4  mov         dword ptr [ebp-8],9  
	int logo;
	for (int i = 0; i < 9; i++) {
00BD1AEB  mov         dword ptr [ebp-44h],0  
00BD1AF2  jmp         __$EncStackInitStart+71h (0BD1AFDh)  //int i=0;
00BD1AF4  mov         eax,dword ptr [ebp-44h]    //执行i++语句;
00BD1AF7  add         eax,1  
00BD1AFA  mov         dword ptr [ebp-44h],eax  
00BD1AFD  cmp         dword ptr [ebp-44h],9  //判断条件
00BD1B01  jge         __$EncStackInitStart+0DBh (0BD1B67h)  
		logo = 0;
00BD1B03  mov         dword ptr [logo],0  
		for (int j = 0; j < 9; j++) {
00BD1B0A  mov         dword ptr [ebp-50h],0  
00BD1B11  jmp         __$EncStackInitStart+90h (0BD1B1Ch)  
00BD1B13  mov         eax,dword ptr [ebp-50h]  
00BD1B16  add         eax,1  
00BD1B19  mov         dword ptr [ebp-50h],eax  
00BD1B1C  cmp         dword ptr [ebp-50h],9  
00BD1B20  jge         __$EncStackInitStart+0D1h (0BD1B5Dh)  //不满足条件则程序结束
			if (arr[j] > arr[j+1]) {//上面判断条件满足后,执行交换动作
00BD1B22  mov         eax,dword ptr [ebp-50h]  
00BD1B25  mov         ecx,dword ptr [ebp-50h]  
00BD1B28  mov         edx,dword ptr arr[eax*4]  
00BD1B2C  cmp         edx,dword ptr [ebp+ecx*4-28h]  
00BD1B30  jle         __$EncStackInitStart+0CFh (0BD1B5Bh)  
				int middle = arr[j];
00BD1B32  mov         eax,dword ptr [ebp-50h]  
00BD1B35  mov         ecx,dword ptr arr[eax*4]  
00BD1B39  mov         dword ptr [ebp-5Ch],ecx  
				arr[j] = arr[j+1];
00BD1B3C  mov         eax,dword ptr [ebp-50h]  
00BD1B3F  mov         ecx,dword ptr [ebp-50h]  
00BD1B42  mov         edx,dword ptr [ebp+ecx*4-28h]  
00BD1B46  mov         dword ptr arr[eax*4],edx  
				arr[j+1] = middle;
00BD1B4A  mov         eax,dword ptr [ebp-50h]  
00BD1B4D  mov         ecx,dword ptr [ebp-5Ch]  
00BD1B50  mov         dword ptr [ebp+eax*4-28h],ecx  
				logo = 1;
00BD1B54  mov         dword ptr [logo],1  
			}				
		}
00BD1B5B  jmp         __$EncStackInitStart+87h (0BD1B13h)  
		if (logo == 0){
00BD1B5D  cmp         dword ptr [logo],0  
00BD1B61  jne         __$EncStackInitStart+0D9h (0BD1B65h)  
			break;
00BD1B63  jmp         __$EncStackInitStart+0DBh (0BD1B67h)  
		}		
	}
00BD1B65  jmp         __$EncStackInitStart+68h (0BD1AF4h)  

do…while语句

在这里插入图片描述
在这里插入图片描述

总结

1、根据条件跳转指令所跳转的地址,可以得到循环语句块的起始地址
2、根据条件跳转指令所在的地址,可以得到循环语句块的结束地址
3、条件跳转的逻辑与源码相同(主要看jxx指令后面的地址是循环体还是结束循环的地址)

while语句

在这里插入图片描述
在这里插入图片描述
总结:
根据条件跳转指令所跳转的地址,可以得到循环语句块的结束地址;
根据JMP指令跳转的地址,可以得到循环语句块的起始地址;
在还原while比较时,条件跳转的逻辑与源码相反(主要看jxx指令后面的地址是循环体还是结束循环的地址)

课后作业

//数组操作
void func2() {
	/*int arr[10] = {4,11,9,12,13,7,5,6,8,20};*/
	int arr[10] = { 0,1,2,3,4,5,6,7,8,9 };
	//数组倒序输出
	/*int count = 0;
	for (int i = 9; i>-1; i--) {
		count++;
		printf("arr[%d]=%d\t", i,arr[i]);
		if (count % 5 == 0) {
			printf("\n\n");
		}
	}
	printf("\n\ndo--while实现\n\n");
	int i = 9;
	do {
		count++;
		printf("arr[%d]=%d\t", i, arr[i]);
		i--;
		if (count % 5 == 0) {
			printf("\n\n");
		}
	} while (i > -1);
	*/
	
	//数组找最大值;//俩俩比较数组的值,将最大的一个存储到数组的最后一个位置 
	/*for (int j = 0; j <= 8; j++) {
		if (arr[j] > arr[j + 1]) {
			int middle = arr[j];
			arr[j] = arr[j + 1];
			arr[j + 1] = middle;
		}
	}
	for (int i = 0; i < 10; i++) {
		printf("arr[%d]=%d\n", i, arr[i]);
	}*/

	//两个等长数组相加
	/*int arr2[10] = { 5,7,3,9,6,12,51,32,14,45 };
	int sum[10];
	for (int i = 0; i < 10; i++) {
		sum[i] = arr[i] + arr2[i];
	}
	for (int i = 0; i < 10; i++) {
		printf("sum[%d]=%d\n", i, sum[i]);
	}*/
	//冒泡排序-顺序1--嵌套一层for循环即可
	/*for (int i = 0; i < 10; i++) {
		for (int j = i+1; j < 10; j++) {
			if (arr[i] < arr[j]) {
				int middle = arr[j];
				arr[j] = arr[i];
				arr[i] = middle;
			}
		}
	}*/
	//冒泡排序--外层循环优化
	int logo;
	for (int i = 0; i < 9; i++) {
		logo = 0;
		for (int j = 0; j < 9; j++) {
			if (arr[j] > arr[j+1]) {
				int middle = arr[j];
				arr[j] = arr[j+1];
				arr[j+1] = middle;
				logo = 1;
			}				
		}
		if (logo == 0){
			break;
		}		
	}

	//优化内层循环(后续再做):内层的循环次数动态更改为上一次交换的位置,这样只需要在无序区作比较完成交换即可

//打印数组
	for (int i = 0; i < 10; i++) {
		printf("arr[%d]=%d\n", i, arr[i]);
	}
}

//素数判断,素数返回1,非素数返回0
int prime(int x) {
	int i = 2;
	for (; i <=sqrt(x); i++) {
		if (x % i == 0) {
			return 0;
		}
	}
	return 1;

}

//数组对称判断,对称则返回1,不对称则返回0
int JugeArr() {
	int arr[5] = { 1,5,6,25,1 };
	int length = sizeof(arr) / sizeof(arr[0]);
	printf("数组长度length=%d\n", length);
	int head=0,tail=length-1;
	for (; head<tail; head++, tail--) {
		if (arr[head] != arr[tail]) {
			printf("该数组不对称\n");
			return 0;
		}
	}
	return 1;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值