創建項目
創建新項⽬
運⾏了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;
}
- 在 VC(Windows 的 Visual C++)裏,寫 C 時可以直接插一小段彙編,只要前面加
_asm就行,就像這樣:
_asm {
mov eax, 1
}
但這是微軟自己加的“小灶”,C 語言標準里根本沒有。
- 換到 Linux,用 gcc 編譯時,就得換另一種寫法,比如:
asm("movl $1, %eax");
寫法不一樣,語法也不一樣。
- 如果你在 C 文件裏到處塞彙編,就像在一篇英文小説裏突然冒出整頁日文——換台電腦、換個編譯器,甚至換個 CPU(比如從電腦 x86 到手機 ARM),這段日文就沒人看得懂,程序直接罷工。這就是“把可移植性弄壞了”。
- 那是不是彙編就不能學?不是!只是別把它撒得滿項目都是。想練手,可以專門開一個小文件或小程序,在裏面寫幾行彙編,看看寄存器怎麼動、內存怎麼變,既滿足好奇心,又不用擔心以後換平台要大改。
一句話總結:
把彙編當“調味料”,偶爾嚐個鮮可以;當“主食”拌進整個項目,以後換鍋(平台)就糊了。
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”,沒有任何的改變。
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
}
代碼改成這個現在我們在這裏下個斷點
注意這裏要改成x86
點擊f5運行,會看到a=220,然後彙編的將值複製到寄存器eax中,然後將eax寄存器的值又複製到了n。
再點擊繼續,就會看到輸出了n,值為220.