Visual Stdudio简单for循环汇编代码分析

    xiaoxiao2021-12-01  46

         由于工作中偶尔需要逆向过程或者逆向调试,这时就需要看汇编代码,才发现原来很多指令都有些遗忘了,同时看到很多汇编语句段也会比较陌生。其实工作时间越久,更体会到基础的重要性。很多时候,如果要要深刻理解高级语言的运行,通过调试分析生成的汇编指令可能效果更好,更不容易遗忘。

        这里通过查看Visual Studio 2008生成的汇编语句,来一步步熟悉汇编指令。

        首先是C++中的简单for循环。

         for(int i=0;i<30;i++)      {           printf("kkk\r\n");      }

          在Debug模式下编译调试:

    for(int i=0;i<30;i++) 009F16FE mov dword ptr [i],0 ; 初始化 i = 0 009F1705 jmp main+30h (9F1710h) ; 无条件跳转 标记为label-1 009F1707 mov eax,dword ptr [i] ; label-3 009F170A add eax,1 ; i++ 009F170D mov dword ptr [i],eax 009F1710 cmp dword ptr [i],1Eh ; label-1 009F1714 jge main+4Fh (9F172Fh) ; 大于或等于 30 跳转 标记为label-2 { printf("kkk\r\n"); 009F1716 mov esi,esp ;保存栈顶指针 009F1718 push offset string "kkk\r\n" (9F58E8h) ;字符串指针入栈 009F171D call dword ptr [__imp__printf (9F82F8h)] ;调用printf函数 009F1723 add esp,4 ;参数退栈 009F1726 cmp esi,esp ;比较栈顶指针,用于判断是否有堆栈溢出或破坏 009F1728 call @ILT+325(__RTC_CheckEsp) (9F114Ah) } 009F172D jmp main+27h (9F1707h) ; 无条件跳转 标记为label-3 009F172F mov esi,esp ; label-2 已退出for循环

          在Realease模式下编译调试:

    for(int i=0;i<30;i++) 00121001 mov esi,dword ptr [__imp__printf (1220A0h)] ; printf 函数指针入栈 00121007 push edi 00121008 mov edi,1Eh ;初始化为30 0012100D lea ecx,[ecx] { printf("kkk\r\n"); 00121010 push offset string "kkk\r\n" (122104h) ;字符串指针入栈 label-1 00121015 call esi 00121017 add esp,4 ;参数退栈 0012101A sub edi,1 ;edi 减1 0012101D jne main+10h (121010h) ;ZF=1,即edi为0,则退出循环,否则跳转 标记为label-1 } printf("size = %d\n",sizeof(KDPC1)); 0012101F push 20h

          如上,通过分析debug和release模式下生成的汇编指令。可以知道:

         (1)同样对应for语言。debug汇编指令基本是按照c、c++代码的顺序进行翻译,便于调试和单步跟踪。realease汇编指令则进行了很大程度上的优化,不仅仅是指令级别的优化,甚至于代码流程上的优化。

          (2)C++中的默认函数调用方式,也是调用方负责清理堆栈的。对应于add         esp,4 。

          (3)Debug模式下,Vistual Studio可以配置执行相关的运行时刻检测,比如上面的 call        @ILT+325(__RTC_CheckEsp) (9F114Ah) 。

    转载请注明原文地址: https://ju.6miu.com/read-679342.html

    最新回复(0)