汇编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