創建項目

C語言和彙編學習環境_下劃線

創建新項⽬

C語言和彙編學習環境_#include_02

C語言和彙編學習環境_下劃線_03

運⾏了hello

內聯彙編

#include <iostream>
 int main()
 {
    int a = 0, n;
    _asm {
        mov eax,a
        mov n,eax
    }
    std::cout << "Hello World!\n"<<n;
 }
 #include <iostream>
 int main()
 {
    int a = 220, n;
    _asm {
        mov eax,a
        mov n,eax
    }
    std::cout << "Hello World!\n"<<n;
 }
 

C語言和彙編學習環境_#include_04

  1. 在 VC(Windows 的 Visual C++)裏,寫 C 時可以直接插一小段彙編,只要前面加 _asm 就行,就像這樣:
_asm {
       mov eax, 1
   }

但這是微軟自己加的“小灶”,C 語言標準里根本沒有。

  1. 換到 Linux,用 gcc 編譯時,就得換另一種寫法,比如:
asm("movl $1, %eax");

寫法不一樣,語法也不一樣。

  1. 如果你在 C 文件裏到處塞彙編,就像在一篇英文小説裏突然冒出整頁日文——換台電腦、換個編譯器,甚至換個 CPU(比如從電腦 x86 到手機 ARM),這段日文就沒人看得懂,程序直接罷工。這就是“把可移植性弄壞了”。
  2. 那是不是彙編就不能學?不是!只是別把它撒得滿項目都是。想練手,可以專門開一個小文件或小程序,在裏面寫幾行彙編,看看寄存器怎麼動、內存怎麼變,既滿足好奇心,又不用擔心以後換平台要大改。

一句話總結:

把彙編當“調味料”,偶爾嚐個鮮可以;當“主食”拌進整個項目,以後換鍋(平台)就糊了。

asm 2 .cpp

#include <stdio.h>
 #include <iostream>
 #include <tchar.h> 
int _tmain(int argc, _TCHAR* argv[])
 {
    int a = 0, b;
    b = a;
   
    std::cout << "Hello World!\n"<<b;
    return 0;
 }

  

將這個代碼替換到原本的int_tmain,實質運行的話,會發現還是輸出“hello word”,沒有任何的改變。

C語言和彙編學習環境_下劃線_05

   6: int _tmain(int argc, _TCHAR* argv[])
     7: {
 01002470  push        ebp  
01002471  mov         ebp,esp  
01002473  sub         esp,0D8h  
01002479  push        ebx  
0100247A  push        esi  
0100247B  push        edi  
0100247C  lea         edi,[ebp-18h]  
0100247F  mov         ecx,6  
01002484  mov         eax,0CCCCCCCCh  
01002489  rep stos    dword ptr es:[edi]  
0100248B  mov         ecx,offset _86296E04_asm02@cpp (0100E067h)  
01002490  call        @__CheckForDebuggerJustMyCode@4 (01001370h)  
     8:     int a = 0, b;
 01002495  mov         dword ptr [a],0  
     9:     b = a;
 0100249C  mov         eax,dword ptr [a]  
0100249F  mov         dword ptr [b],eax  
    10:    
    11:     std::cout << "Hello World!\n"<<b;
 010024A2  mov         esi,esp  
010024A4  mov         eax,dword ptr [b]  
010024A7  push        eax  
010024A8  push        offset string "Hello World!\n" (01009B30h)  
010024AD  mov         ecx,dword ptr [__imp_std::cout (0100D0C8h)]  
010024B3  push        ecx  
010024B4  call        std::operator<<<std::char_traits<char> > (0100119Fh) 
 
010024B9  add         esp,8  
010024BC  mov         ecx,eax  
010024BE  call        dword ptr 
[__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< 
(0100D0D0h)]  
010024C4  cmp         esi,esp  
010024C6  call        __RTC_CheckEsp (01001285h)  
    12:     return 0;
 010024CB  xor         eax,eax  
    13: }
 010024CD  pop         edi  
010024CE  pop         esi  
010024CF  pop         ebx  
0100
#include <iostream>
using namespace std;

int main()
{
    int a = 220;
    int n = 0;                 // 1. 初始化,避免未定義值

    __asm {                    // 2. 雙下劃線 __asm ,單下劃線 _asm 也能過,但雙下劃線是官方寫法
        mov eax, a            //    直接把 C 變量名寫進來,MSVC 會自動替換成地址
        mov n, eax
    }

    cout << "Hello World!\n" << n << endl;
    return 0;                  // 3. main 返回 int
}

C語言和彙編學習環境_ios_06

代碼改成這個現在我們在這裏下個斷點

C語言和彙編學習環境_#include_07

注意這裏要改成x86

C語言和彙編學習環境_#include_08

點擊f5運行,會看到a=220,然後彙編的將值複製到寄存器eax中,然後將eax寄存器的值又複製到了n。

C語言和彙編學習環境_下劃線_09

再點擊繼續,就會看到輸出了n,值為220.