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;
}