汇编Q2: 多重循环
来源:互联网 发布:psp游戏王arcv最新数据 编辑:程序博客网 时间:2024/05/01 05:44
2、C语言编写多重循环程序,查看其反汇编码,分析各条语句功能,并采用汇编语言编写相同功能程序。
(1)冒泡排序
汇编代码:
;冒泡排序实现数组从小到大排序.386.model flat,stdcalloption casemap:noneincludelib msvcrt.libprintf PROTO C:dword,:vararg.dataarray dword 20,15,70,30,32,89,12 ;等待被排序的数组items equ ($ - array) / 4 ;数组元素的个数szFmt byte 'array[%d] = %d', 0ah, 0 ;输出结果格式字符串.codestart: mov ECX, items - 1 ;ECX相当于数组最大下标i10: ;外层循环起始处 xor ESI, ESI ;ESI计数i20: ;内层循环起始处 mov EAX, array[ESI * 4] mov EBX, array[ESI * 4 + 4] cmp EAX, EBX JL i30 ;JL 两个带符号数的比较,小于则跳转,EAX\EBX不进行交换 mov array[ESI * 4], EBX mov array[ESI * 4 +4], EAXi30: inc ESI; cmp ESI, ECX JB i20 ;JB 两个无符号数的比较,小于表示不越界则跳转进行内层循环 loop i10 ;外层循环 xor EDI, EDIi40: ;输出 invoke printf, offset szFmt, EDI, array[EDI * 4] inc EDI cmp EDI, items JB i40 retend start
C语言:
#include <stdio.h>int main(){ int array[7] = { 20,15,70,30,32,89,12 }; for (int i = 0; i < 6; i++) { for (int j = 0; j < 6; j++) if (array[j] > array[j + 1]) { int temp = array[j]; array[j] = array[j + 1]; array[j + 1] = temp; } } for (int i = 0; i < 7; i++) { printf("array[%d]=%d", i, array[i]); printf("\n"); } return 0;}
(2)插入排序
汇编代码:
;插入排序.386.model flat,stdcalloption casemap:noneincludelib msvcrt.libprintf PROTO C:dword,:vararg;ESI = i;EDI = j;EDX = tmp = array[i] = array[ESI * 4];EBX = array[j] = array[EDI * 4].dataarray dword 20,15,70,30,32,89,12 ;等待被排序的数组len equ ($ - array) / 4 ;数组元素的个数szFmt byte 'array[%d] = %d', 0ah, 0 ;输出结果格式字符串.codestart:mov ECX, len - 1 ;外层循环的次数放在ECX中xor ESI, ESI mov ESI, 1 ;ESI表示i,int i = 1; OuterLoop: ;外层循环起始处 mov EDX, array[ESI * 4] ;int tmp = array[i]; xor EDI, EDI mov EAX, ESI dec EAX mov EDI, EAX ;EDI表示j,int j = i - 1InnerLoop: ;内层循环起始处 cmp array[EDI * 4], EDX ;比较array[j]和tmp JL NoMovement ;JL 两个带符号数的比较,若array[j] <= tmp,则跳出内层循环到NoMovement mov EBX, array[EDI * 4] mov array[EDI * 4 + 4], EBX ;若array[j] > tmp,则执行array[j + 1] = array[j]; dec EDI ;j -- cmp EDI, 0 ;比较是否j>=0 JNB InnerLoop ;若j>=0,则继续进行内层循环NoMovement: mov array[EDI * 4 + 4], EDX ;array[j + 1] = tmp; inc ESI ;i++ loop OuterLoop ;若循环次数未到6次,则继续进行外层循环 xor EDI,EDI ;进入OutPut段OutPut: ;输出 invoke printf, offset szFmt, EDI, array[EDI * 4] ;为什么把EDI换成EAX就不行??只输出第一个数 inc EDI cmp EDI, len JB OutPut retend start
C语言:
#include <stdio.h>int main(){ int array[7] = { 20,15,70,30,32,89,12 }; for (int i = 1; i < 7; i++) { int tmp = array[i]; int j; for (j = i - 1; j >= 0; j--) { if (array[j] > tmp) array[j + 1] = array[j]; else break; } array[j + 1] = tmp; } for (int i = 0; i < 7; i++) { printf("array[%d]=%d", i, array[i]); printf("\n"); } return 0;}
反汇编码:
int 3 ;中断(来自CPU内部的中断:内中断,不可屏蔽的),空的地方用int 3填上,一旦EIP跑飞就单步中断 ;int 3对应的机器码是CC,要用CC填充空的空间#include <stdio.h>int main(){00BD17E0 push ebp ;ebp压栈 00BD17E1 mov ebp,esp ;ebp,esp都指向栈顶00BD17E3 sub esp,114h ;esp上移114h00BD17E9 push ebx ;ebx入栈00BD17EA push esi ;esi入栈00BD17EB push edi ;edi入栈00BD17EC lea edi,[ebp-114h] ;edi指向ebp-114h00BD17F2 mov ecx,45h ;循环次数为45h00BD17F7 mov eax,0CCCCCCCCh ;填充值都为0CCCCCCCCh,即int 3,出错会立刻中断00BD17FC rep stos dword ptr es:[edi] ;循环执行直到edi的位置 int array[7] = { 20,15,70,30,32,89,12 };00BD17FE mov dword ptr [array],14h ;如何知道array的地址???array[0]=2000BD1805 mov dword ptr [ebp-1Ch],0Fh ;array[1]=1500BD180C mov dword ptr [ebp-18h],46h ;array[2]=7000BD1813 mov dword ptr [ebp-14h],1Eh ;array[3]=3000BD181A mov dword ptr [ebp-10h],20h ;array[4]=3200BD1821 mov dword ptr [ebp-0Ch],59h ;array[5]=8900BD1828 mov dword ptr [ebp-8],0Ch ;array[6]=12,从上往下放数,低地址放低坐标,高地址放高坐标 for (int i = 1; i < 7; i++) ;外层循环 00BD182F mov dword ptr [ebp-2Ch],1 ;[ebp-2Ch]中存放着i的值,并把i的初值设为100BD1836 jmp main+61h (0BD1841h) ;无条件跳转到0BD1841h处00BD1838 mov eax,dword ptr [ebp-2Ch] ;i的值赋给eax00BD183B add eax,1 ;eax + 100BD183E mov dword ptr [ebp-2Ch],eax ;eax重新赋给i,即1838~183E三条语句实现i++00BD1841 cmp dword ptr [ebp-2Ch],7 ;i和7比较00BD1845 jge main+0B7h (0BD1897h) ;jge两个带符号数的比较,如果i大于等于7则跳转到0BD1897h,结束外层循环 { int tmp = array[i];00BD1847 mov eax,dword ptr [ebp-2Ch] ;若i小于7则把i的值放入eax中00BD184A mov ecx,dword ptr array[eax*4];ecx指向array[i]00BD184E mov dword ptr [ebp-38h],ecx ;[ebp-38h]中存着tmp的值,把array[i]的值赋给tmp int j; for (j = i - 1; j >= 0; j--)00BD1851 mov eax,dword ptr [ebp-2Ch] ;把i的值赋给eax 00BD1854 sub eax,1 ;eax - 100BD1857 mov dword ptr [ebp-44h],eax ;eax的值赋给[ebp-44h],即j的值存放在[ebp-44h]中00BD185A jmp main+85h (0BD1865h) ;无条件跳转到0BD1865h00BD185C mov eax,dword ptr [ebp-44h] ;j的值赋给eax00BD185F sub eax,1 ;eax - 100BD1862 mov dword ptr [ebp-44h],eax ;eax重新赋给j,即185C~1862三条语句实现j--00BD1865 cmp dword ptr [ebp-44h],0 ;比较j和0的大小00BD1869 jl main+0ABh (0BD188Bh) ;如果j小于0则跳转到0BD188Bh,跳出内层循环 { if (array[j] > tmp) 00BD186B mov eax,dword ptr [ebp-44h] ;j>=0则继续内层循环,把j的值赋给eax00BD186E mov ecx,dword ptr array[eax*4];ecx指向array[j] 00BD1872 cmp ecx,dword ptr [ebp-38h] ;比较array[j]和tmp的大小00BD1875 jle main+0A7h (0BD1887h) ;如果array[j]<=tmp则跳转到0BD1887h array[j + 1] = array[j];00BD1877 mov eax,dword ptr [ebp-44h] ;如果array[j]>tmp,则把j的值赋给eax00BD187A mov ecx,dword ptr [ebp-44h] ;把j的值赋给ecx00BD187D mov edx,dword ptr array[ecx*4];把array[j]赋给edx 00BD1881 mov dword ptr [ebp+eax*4-1Ch],edx;[ebp-1Ch]为array[1],[ebp-1Ch+eax*4]为array[1+j],即把array[j]赋给arrayp[j+1] else break;00BD1885 jmp main+0A9h (0BD1889h) ;无条件跳转到0BD1889h00BD1887 jmp main+0ABh (0BD188Bh) ;如果array[j]<=tmp跳转到此处,继续跳转到08D188Bh }00BD1889 jmp main+7Ch (0BD185Ch) ;无条件跳转到0BD185Ch,重复内层循环 array[j + 1] = tmp;00BD188B mov eax,dword ptr [ebp-44h] ;j<0跳转到此处/array[j]<=tmp也跳转到此处,把j的值赋给eax00BD188E mov ecx,dword ptr [ebp-38h] ;把tmp的值赋给ecx00BD1891 mov dword ptr [ebp+eax*4-1Ch],ecx ;分析同00BD1881,把ecx赋给array[j+1],即把tmp赋给array[j+1] }00BD1895 jmp main+58h (0BD1838h) ;无条件跳转到0BD1838h for (int i = 0; i < 7; i++)00BD1897 mov dword ptr [ebp-50h],0 ;外层循环结束跳转到这里,开始打印输出,给临时变量i赋初值为0,内存空间为[ebp-50h]00BD189E jmp main+0C9h (0BD18A9h) ;无条件跳转到0BD18A9h00BD18A0 mov eax,dword ptr [ebp-50h] ;00BD18A3 add eax,1 00BD18A6 mov dword ptr [ebp-50h],eax 00BD18A9 cmp dword ptr [ebp-50h],7 ;比较i和7的大小00BD18AD jge main+0F7h (0BD18D7h) ;如果i>=7则跳转到0BD18D7h,结束打印的循环 { printf("array[%d]=%d", i, array[i])00BD18AF mov eax,dword ptr [ebp-50h] ;把i的值赋给eax00BD18B2 mov ecx,dword ptr array[eax*4];把array[i]的值赋给ecx 00BD18B6 push ecx ;ecx入栈00BD18B7 mov edx,dword ptr [ebp-50h] ;把i的值赋给edx00BD18BA push edx ;edx入栈00BD18BB push offset string "array[%d]=%d" (0BD7B30h) ;与0BD7B30h的偏移量入栈??? 00BD18C0 call _printf (0BD1334h) ;调用C库的printf00BD18C5 add esp,0Ch ;esp + 12??? printf("\n");00BD18C8 push offset string "\n" (0BD7B40h) ;与0BD7B40h的偏移量入栈????00BD18CD call _printf (0BD1334h) ;调用C库中的printf00BD18D2 add esp,4 ;esp + 4 }00BD18D5 jmp main+0C0h (0BD18A0h) ;无条件跳转到0BD18A0h return 0;00BD18D7 xor eax,eax ;把eax清零}00BD18D9 push edx ;edx入栈00BD18DA mov ecx,ebp ;把ebp的值赋给ecx00BD18DC push eax ;eax入栈00BD18DD lea edx,ds:[0BD1900h] ;?????????00BD18E3 call @_RTC_CheckStackVars@8 (0BD1267h) 00BD18E8 pop eax ;弹出eax赋给eax00BD18E9 pop edx ;弹出edx赋给edx00BD18EA pop edi ;弹出edi赋给edi00BD18EB pop esi ;弹出esi赋给esi00BD18EC pop ebx ;弹出ebx赋给ebx00BD18ED add esp,114h ;esp + 114h恢复堆栈00BD18F3 cmp ebp,esp ;比较ebp和esp00BD18F5 call __RTC_CheckEsp (0BD1122h) ;???? 00BD18FA mov esp,ebp ;把ebp的值赋给esp00BD18FC pop ebp ;弹出的值给ebp 00BD18FD ret
阅读全文
0 0
- 汇编Q2: 多重循环
- 汇编多重循环练习
- 汇编—多重循环—矩阵乘法
- 多重循环
- 多重循环
- 多重循环
- 跳出多重循环
- java跳出多重循环
- python跳出多重循环
- 跳出多重for循环
- java跳出多重循环
- Java跳出多重循环
- HDU4334(多重循环)
- Java跳出多重循环
- 多重循环的优化
- 代码优化:多重循环
- iBtais 多重嵌套循环
- java跳出多重循环
- Mark Scrapy安装需要的模块
- 图连通(Kruaskal和prim)
- 习题5 5.9
- less使用小总结
- SpringBoot学习笔记二
- 汇编Q2: 多重循环
- Java编程思想笔记-六
- 顺序栈
- nginx反向代理
- 送给你们的爱
- 机房收费系统---如何引用Microsoft Excel xx.0 Object Library
- MyBatis Generator使用
- 6.7
- IO流编码与解码