您的位置:首页 > 编程语言

C技巧:VC函数调用的汇编代码

2014-08-07 23:57 176 查看
主要谈谈vc里面函数调用汇编成汇编代码的情形,首先针对之前的一个小程序,说说vc编译器的优化。

  例子程序:

  #include <iostream>

  using namespace std;

  int main(int argc, char* argv[])

  {

  int i=10;

  int a = i;

  cout << "i=" << a << endl;

  //下面汇编语句的作用就是改变内存中i的值,但是又不让编译器知道

  __asm

  {

  mov dword ptr [ebp-4], 20h

  }

  int b = i;

  cout << "i=" << b << endl;

  return 0;

  }

  这段代码很简洁,但汇编代码可不简洁,首先看看release模式下的汇编代码概况:

  ……

  ; 14 :

  ; 15 : //下面汇编语句的作用就是改变内存中i的值,但是又不让编译器知道

  ; 16 : __asm

  ; 17 : {

  ; 18 : mov dword ptr [ebp-4], 20h

  mov DWORD PTR [ebp-4], 32 ; 00000020H

  ; 19 : }

  ; 20 : int b = i;

  ; 21 : cout << "i=" << b << endl;

  push 10 ; 0000000aH

  push OFFSET FLAT:??_C@_02HDOK@i?$DN?$AA@ ; `string’

  push OFFSET FLAT:?cout@std@@3V?$basic_ostream@DU?$char_traits@D@std@@@1@A ; std::cout

  call ??6std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@0@AAV10@PBD@Z ; std::operator<<

  add esp, 8

  mov ecx, eax

  call ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@H@Z ; std::basic_ostream<char,std::char_traits<char> >::operator<<

  mov esi, eax

  push 10 ; 0000000aH

  mov ecx, esi

  call ?put@?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV12@D@Z ; std::basic_ostream<char,std::char_traits<char> >::put

  mov ecx, DWORD PTR [esi]

  xor edi, edi

  ……

  调用cout前面,直接一个push 10,这是函数调用前压参数的过程,压了个常数在里面,呵呵,其实i已经被修改了,但是编译器不知道,以为i仍然是10,顾做了优化,考试,大提示压参压了常量在里面。

  再看看debug模式下的汇编代码情况:

  16: __asm

  17: {

  18: mov dword ptr [ebp-4], 20h

  004017DE mov dword ptr [ebp-4],20h

  19: }

  20: int b = i;

  004017E5 mov edx,dword ptr [ebp-4]

  004017E8 mov dword ptr [ebp-0Ch],edx

  21: cout << "i=" << b << endl;

  004017EB push offset @ILT+195(std::endl) (004010c8)

  004017F0 mov eax,dword ptr [ebp-0Ch]

  004017F3 push eax

  004017F4 push offset string "i=" (0046c01c)

  004017F9 push offset std::cout (00477a10)

  004017FE call @ILT+640(std::operator<<) (00401285)

  00401803 add esp,8

  00401806 mov ecx,eax

  b = i,赋值这句成了从i的地址去取值送往b了,

  mov edx,dword ptr [ebp-4]

  mov dword ptr [ebp-0Ch],edx

  注意release版本是没有这两句的,所以现在b取值就是肯定正确的了,后面压参的时候,也把b地址指向的值压入了堆栈,呵呵,这也是之前说的为什么两个版本下运行结果不同的原因。

  把这个程序稍加修改,开始我们下面的函数调用汇编浅析:

  #include <iostream>

  using namespace std;

  int ChangNum(int, int);

  int main(int argc, char* argv[])

  {

  int i=10;

  int a = i;

  cout << "i=" << a << endl;

  //下面汇编语句的作用就是改变内存中i的值,但是又不让编译器知道

  __asm

  {

  mov dword ptr [ebp-4], 20h

  }

  int b = i;

  cout << "i=" << b << endl;

  ChangNum(50, 100);

  return 0;

  }

  int ChangNum(int nParam, int nW)

  {

  int i = 10;

  int a = i;

  cout << "i=" << a << endl;

  __asm

  {

  mov dword ptr [ebp - 4], 20h

  mov dword ptr [ebp + 12], 0h

  }

  int b = i;

  cout << "i=" << b << endl;

  return 0;

  }
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: