欢迎光临!
若无相欠,怎会相见

反汇编学习-C语言实例解析精粹-实例4比较实数大小

序言

之前出差了两周,出门在外感觉比在这边更累,最重要的是心累,精神疲惫,所以也没什么心思写博文。

趁着现在有时间,写上一篇,本次环境是 VS6.0,主要是 VS2017转换后的汇编代码有很多我根本看不懂,只能用VS6.0试一下,学习也是需要循序渐进的。

C代码

/*
输入两个浮点数,输出其中较大的数
*/
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main()
{
    float x, y, c;
    printf("Please Input x and y: ");
    scanf("%f %f", &x, &y);
    c = x > y ? x : y;              //进行比较,如果x大于y,c等于x,否则等与y
    printf("MAX Of (%f %f) is %f\n", x, y, c);

    getchar();   // 打印完暂停
    getchar();
    return 0;
}

VS6.0的代码没什么不同,就是把宏定义#define _CRT_SECURE_NO_WARNINGS 给去掉了。

接下来是转换后的汇编代码

汇编代码

我把两种代码都复制出来,以便后面学习:

VS 6.0

--- c:\documents and settings\administrator\桌面\projects\c\no.4.c  -----------------------------------------------------------------------------------
1:    /*
2:    输入两个浮点数,输出其中较大的数
3:    */
4:    //#define _CRT_SECURE_NO_WARNINGS
5:    #include <stdio.h>
6:
7:    int main()
8:    {
00401010   push        ebp       // 老套路
00401011   mov         ebp,esp
00401013   sub         esp,58h
00401016   push        ebx
00401017   push        esi
00401018   push        edi
00401019   lea         edi,[ebp-58h]
0040101C   mov         ecx,16h
00401021   mov         eax,0CCCCCCCCh
00401026   rep stos    dword ptr [edi]
9:        float x, y, c;
10:       printf("Please Input x and y: ");
00401028   push        offset string "Please Input x and y: " (00426040)
0040102D   call        printf (00401510)
00401032   add         esp,4
11:       scanf("%f %f", &x, &y);
00401035   lea         eax,[ebp-8]
00401038   push        eax
00401039   lea         ecx,[ebp-4]
0040103C   push        ecx
0040103D   push        offset string "%f %f" (00426038)
00401042   call        scanf (004014b0)
00401047   add         esp,0Ch
12:       c = x > y ? x : y;              //进行比较,如果x大于y,c等于x,否则等与y
0040104A   fld         dword ptr [ebp-4]
0040104D   fcomp       dword ptr [ebp-8]
00401050   fnstsw      ax
00401052   test        ah,41h            // 比较
00401055   jne         main+4Fh (0040105f)
00401057   mov         edx,dword ptr [ebp-4]
0040105A   mov         dword ptr [ebp-10h],edx
0040105D   jmp         main+55h (00401065)
0040105F   mov         eax,dword ptr [ebp-8]
00401062   mov         dword ptr [ebp-10h],eax
00401065   mov         ecx,dword ptr [ebp-10h]
00401068   mov         dword ptr [ebp-0Ch],ecx
13:       printf("MAX Of (%f %f) is %f\n", x, y, c);
0040106B   fld         dword ptr [ebp-0Ch]      // 这部分的是浮点运算,命令见下方
0040106E   sub         esp,8
00401071   fstp        qword ptr [esp]
00401074   fld         dword ptr [ebp-8]
00401077   sub         esp,8
0040107A   fstp        qword ptr [esp]
0040107D   fld         dword ptr [ebp-4]
00401080   sub         esp,8
00401083   fstp        qword ptr [esp]
00401086   push        offset string "MAX Of \xa3\xa8%f %f\xa3\xa9 is %f\n" (0042601c)
0040108B   call        printf (00401510)
00401090   add         esp,1Ch
14:
15:       getchar();   // 打印完暂停
00401093   mov         edx,dword ptr [__iob+4 (00428a34)]
00401099   sub         edx,1
0040109C   mov         dword ptr [__iob+4 (00428a34)],edx
004010A2   cmp         dword ptr [__iob+4 (00428a34)],0
004010A9   jl          main+0BDh (004010cd)
004010AB   mov         eax,[__iob (00428a30)]
004010B0   movsx       ecx,byte ptr [eax]
004010B3   and         ecx,0FFh
004010B9   mov         dword ptr [ebp-14h],ecx
004010BC   mov         edx,dword ptr [__iob (00428a30)]
004010C2   add         edx,1
004010C5   mov         dword ptr [__iob (00428a30)],edx
004010CB   jmp         main+0CDh (004010dd)
004010CD   push        offset __iob (00428a30)
004010D2   call        _filbuf (00401180)
004010D7   add         esp,4
004010DA   mov         dword ptr [ebp-14h],eax
16:       getchar();
004010DD   mov         eax,[__iob+4 (00428a34)]
004010E2   sub         eax,1
004010E5   mov         [__iob+4 (00428a34)],eax
004010EA   cmp         dword ptr [__iob+4 (00428a34)],0
004010F1   jl          main+104h (00401114)
004010F3   mov         ecx,dword ptr [__iob (00428a30)]
004010F9   movsx       edx,byte ptr [ecx]
004010FC   and         edx,0FFh
00401102   mov         dword ptr [ebp-18h],edx
00401105   mov         eax,[__iob (00428a30)]
0040110A   add         eax,1
0040110D   mov         [__iob (00428a30)],eax
00401112   jmp         main+114h (00401124)
00401114   push        offset __iob (00428a30)
00401119   call        _filbuf (00401180)
0040111E   add         esp,4
00401121   mov         dword ptr [ebp-18h],eax
17:       return 0;
00401124   xor         eax,eax
18:   }
00401126   pop         edi
00401127   pop         esi
00401128   pop         ebx
00401129   add         esp,58h
0040112C   cmp         ebp,esp
0040112E   call        __chkesp (00401640)
00401133   mov         esp,ebp
00401135   pop         ebp
00401136   ret

很简单的汇编代码,看着C代码大概就能猜出来了,VS2017转换后的代码就比较复杂了

--- e:\projects\c\project1\project1\no4.c.cpp ----------------------------------
     1: /*
     2: 输入两个浮点数,输出其中较大的数
     3: */
     4: #define _CRT_SECURE_NO_WARNINGS
     5: #include <stdio.h>
     6: 
     7: int main()
     8: {
002E1920 55                   push        ebp  
002E1921 8B EC                mov         ebp,esp  
002E1923 81 EC EC 00 00 00    sub         esp,0ECh  
002E1929 53                   push        ebx  
002E192A 56                   push        esi  
002E192B 57                   push        edi  
002E192C 8D BD 14 FF FF FF    lea         edi,[ebp-0ECh]  
002E1932 B9 3B 00 00 00       mov         ecx,3Bh  
002E1937 B8 CC CC CC CC       mov         eax,0CCCCCCCCh  
002E193C F3 AB                rep stos    dword ptr es:[edi]  
002E193E A1 04 A0 2E 00       mov         eax,dword ptr [__security_cookie (02EA004h)]  
002E1943 33 C5                xor         eax,ebp  
002E1945 89 45 FC             mov         dword ptr [ebp-4],eax  
002E1948 B9 03 C0 2E 00       mov         ecx,offset _3B9F8790_no4@c@cpp (02EC003h)  
002E194D E8 C5 F8 FF FF       call        @__CheckForDebuggerJustMyCode@4 (02E1217h)  
     9:     float x, y, c;
    10:     printf("Please Input x and y: ");
002E1952 68 30 7B 2E 00       push        offset string "Please Input x and y: " (02E7B30h)  
002E1957 E8 EF F6 FF FF       call        _printf (02E104Bh)  
002E195C 83 C4 04             add         esp,4  
    11:     scanf("%f %f", &x, &y);
002E195F 8D 45 E8             lea         eax,[y]  
002E1962 50                   push        eax  
002E1963 8D 4D F4             lea         ecx,[x]  
002E1966 51                   push        ecx  
002E1967 68 4C 7B 2E 00       push        offset string "%f %f" (02E7B4Ch)  
002E196C E8 2F F7 FF FF       call        _scanf (02E10A0h)  
002E1971 83 C4 0C             add         esp,0Ch  
    12:     c = x > y ? x : y;              //进行比较,如果x大于y,c等于x,否则等与y
002E1974 F3 0F 10 45 F4       movss       xmm0,dword ptr [x]  
002E1979 0F 2F 45 E8          comiss      xmm0,dword ptr [y]  
002E197D 76 0F                jbe         main+6Eh (02E198Eh)  
002E197F F3 0F 10 45 F4       movss       xmm0,dword ptr [x]  
002E1984 F3 0F 11 85 14 FF FF FF movss       dword ptr [ebp-0ECh],xmm0  
002E198C EB 0D                jmp         main+7Bh (02E199Bh)  
002E198E F3 0F 10 45 E8       movss       xmm0,dword ptr [y]  
002E1993 F3 0F 11 85 14 FF FF FF movss       dword ptr [ebp-0ECh],xmm0  
002E199B F3 0F 10 85 14 FF FF FF movss       xmm0,dword ptr [ebp-0ECh]  
002E19A3 F3 0F 11 45 DC       movss       dword ptr [c],xmm0  
    13:     printf("MAX Of (%f %f) is %f\n", x, y, c);
002E19A8 F3 0F 5A 45 DC       cvtss2sd    xmm0,dword ptr [c]  
002E19AD 83 EC 08             sub         esp,8  
002E19B0 F2 0F 11 04 24       movsd       mmword ptr [esp],xmm0  
002E19B5 F3 0F 5A 45 E8       cvtss2sd    xmm0,dword ptr [y]  
002E19BA 83 EC 08             sub         esp,8  
    13:     printf("MAX Of (%f %f) is %f\n", x, y, c);
002E19BD F2 0F 11 04 24       movsd       mmword ptr [esp],xmm0  
002E19C2 F3 0F 5A 45 F4       cvtss2sd    xmm0,dword ptr [x]  
002E19C7 83 EC 08             sub         esp,8  
002E19CA F2 0F 11 04 24       movsd       mmword ptr [esp],xmm0  
002E19CF 68 54 7B 2E 00       push        offset string "MAX Of \xa3\xa8%f %f\xa3\xa9 is %f\n" (02E7B54h)  
002E19D4 E8 72 F6 FF FF       call        _printf (02E104Bh)  
002E19D9 83 C4 1C             add         esp,1Ch  
    14: 
    15:     getchar();   // 打印完暂停
002E19DC 8B F4                mov         esi,esp  
002E19DE FF 15 70 B1 2E 00    call        dword ptr [__imp__getchar (02EB170h)]  
002E19E4 3B F4                cmp         esi,esp  
002E19E6 E8 36 F8 FF FF       call        __RTC_CheckEsp (02E1221h)  
    16:     getchar();
002E19EB 8B F4                mov         esi,esp  
002E19ED FF 15 70 B1 2E 00    call        dword ptr [__imp__getchar (02EB170h)]  
002E19F3 3B F4                cmp         esi,esp  
002E19F5 E8 27 F8 FF FF       call        __RTC_CheckEsp (02E1221h)  
    17:     return 0;
002E19FA 33 C0                xor         eax,eax  
    18: }
002E19FC 52                   push        edx  
002E19FD 8B CD                mov         ecx,ebp  
002E19FF 50                   push        eax  
002E1A00 8D 15 2C 1A 2E 00    lea         edx,ds:[2E1A2Ch]  
002E1A06 E8 3E F8 FF FF       call        @_RTC_CheckStackVars@8 (02E1249h)  
002E1A0B 58                   pop         eax  
002E1A0C 5A                   pop         edx  
002E1A0D 5F                   pop         edi  
002E1A0E 5E                   pop         esi  
002E1A0F 5B                   pop         ebx  
002E1A10 8B 4D FC             mov         ecx,dword ptr [ebp-4]  
002E1A13 33 CD                xor         ecx,ebp  
002E1A15 E8 D0 F7 FF FF       call        @__security_check_cookie@4 (02E11EAh)  
002E1A1A 81 C4 EC 00 00 00    add         esp,0ECh  
002E1A20 3B EC                cmp         ebp,esp  
002E1A22 E8 FA F7 FF FF       call        __RTC_CheckEsp (02E1221h)  
002E1A27 8B E5                mov         esp,ebp  
002E1A29 5D                   pop         ebp  
002E1A2A C3                   ret  
002E1A2B 90                   nop  
002E1A2C 02 00                add         al,byte ptr [eax]  
002E1A2E 00 00                add         byte ptr [eax],al  
002E1A30 34 1A                xor         al,1Ah  
002E1A32 2E 00 F4             add         ah,dh  
002E1A35 ??                   ?? ?? 
002E1A36 ??                   ?? ?? 
002E1A37 FF 04 00             inc         dword ptr [eax+eax]  
002E1A3A 00 00                add         byte ptr [eax],al  
002E1A3C 4E                   dec         esi  
002E1A3D 1A 2E                sbb         ch,byte ptr [esi]  
002E1A3F 00 E8                add         al,ch  
002E1A41 ??                   ?? ?? 
002E1A42 ??                   ?? ?? 
002E1A43 FF 04 00             inc         dword ptr [eax+eax]  
002E1A46 00 00                add         byte ptr [eax],al  
002E1A48 4C                   dec         esp  
002E1A49 1A 2E                sbb         ch,byte ptr [esi]  
002E1A4B 00 79 00             add         byte ptr [ecx],bh  
002E1A4E 78 00                js          _main+130h (02E1A50h)

我看到的时候,很懵逼,只能转到虚拟机用VS6.0编译了。

汇编指令

指令 指令格式 含义
fld FLD source
  • FLD是Intel的指令集协处理器的汇编指令,FLD 指令用于把浮点数字传送入和传送出FPU寄存器
  • 格式中source可以为32 ,64或者80位整数值.为了区分这两种长度,GNU汇编器使用FLDS加载单精度浮点数,FLDL加载双精度浮点数,类似FST用于获取FPU寄存器堆栈中顶部的值, 并且把这个值放到内存位置中, 对于单精度使用FSTS, 对于双精度使用FSTL
fcomp fcomp source
  • 浮点比较
  • 出栈
fnstsw FNSTSW source
  • 将 FPU 状态字的当前值存储到目标位置。目标操作数可以是双字节的内存位置或 AX 寄存器。在存储状态字之前,FSTSW 指令检查并处理未决的无掩码浮点异常,FNSTSW 指令则不会。
  • FNSTSW AX 形式的指令主要用于条件分支 [参见]
fstp FSTP source
  • FSTP 指令先执行同 FST 指令相同的操作,然后弹出寄存器堆栈。为了弹出寄存器堆栈,处理器将 ST(0) 寄存器标记为空,并使堆栈指针 (TOP) 递增 1。FSTP 指令还可以按扩展的实数格式在内存中存储值。[参加]
jne jne 地址
  • 一个条件转移指令。当ZF=0,转至地址处执行。

结语

天色已晚,学到这里,后面继续~

如有错误,敬请指出,感谢指正!              — 2019-06-04  22:58:50         于苏州

赞(1) 打赏
转载请注明:飘零博客 » 反汇编学习-C语言实例解析精粹-实例4比较实数大小
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

欢迎光临