C技巧:VC函數調用的彙編代碼

來源:互聯網
上載者:User
主要談談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;

  }


相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.