04-匯編指令、引用和Const

《C++文章匯總》
上一篇介紹了引用和匯編《03-Reference、匯編》,本文介紹匯編其他指令、引用和Const。

1.x64匯編要點總結

?mov dest, src
將src的內容賦值給dest,類似于dest = src
?[ 地址值 ]
中括號[ ]里面放的都是內存地址
?word是2字節,dword是4字節(double word),qword是8字節(quad word) ?call 函數地址
調用函數
?lea dest, [ 地址值 ]
將地址值賦值給dest,類似于dest = 地址值
?ret 其實內部也包含jump功能
函數返回
?xor op1, op2
將op1和op2異或的結果賦值給op1,類似于op1 = op1 ^ op2
?add op1, op2
類似于op1 = op1 + op2
?sub op1, op2
類似于op1 = op1 - op2
?inc op
自增,類似于op = op + 1
?dec op
自減,類似于op = op – 1
?jmp 內存地址
跳轉到某個內存地址去執行代碼 ?j開頭的一般都是跳轉,大多數是帶條件的跳轉,一般跟test、cmp等指令配合使用
? 權威參考:Intel白皮書 ?https://software.intel.com/en-us/articles/intel-sdm

函數的返回值放在eax中


圖片.png

2.Jump Condition Code

01、 JE, JZ 結果為零則跳轉(相等時跳轉) ZF=1
equal zero
02、 JNE, JNZ 結果不為零則跳轉(不相等時跳轉) ZF=0
not equal not zero
03、 JS 結果為負則跳轉 SF=1
sign(有符號\有負號)
04、 JNS 結果為非負則跳轉 SF=0
not sign(無符號\無負號)
05、 JP, JPE 結果中1的個數為偶數則跳轉 PF=1
parity even
06、 JNP, JPO 結果中1的個數為偶數則跳轉 PF=0
parity odd
07、 JO 結果溢出了則跳轉 OF=1
overflow
08、 JNO 結果沒有溢出則跳轉 OF=0
not overflow
09、 JB, JNAE 小于則跳轉 (無符號數) CF=1
below not above equal <
10、 JNB, JAE 大于等于則跳轉 (無符號數) CF=0
not below above equal >=
11、 JBE, JNA 小于等于則跳轉 (無符號數) CF=1 or ZF=1
below equal not above <=
12、 JNBE, JA 大于則跳轉(無符號數) CF=0 and ZF=0
not below equal above >
13、 JL, JNGE 小于則跳轉 (有符號數) SF≠ OF
little not great equal <
14、 JNL, JGE 大于等于則跳轉 (有符號數) SF=OF
not little great equal >=
15、 JLE, JNG 小于等于則跳轉 (有符號數) ZF=1 or SF≠ OF
little equal not great <=
16、 JNLE, JG 大于則跳轉(有符號數) ZF=0 and SF=OF
not little equal great >

CPU架構決定無法mov 內存到內存,要通過寄存器來進行運算中轉
mov帶單位,取數據,取多少個字節,lea不帶單位,lea賦值內存地址,指針牽扯到取地址值,標記是lea eax,[ebp-0Ch],不能寫成mov eax ebp-0Ch,mov指令不能做運算,但可以

sub ebp,0CH//會改掉ebp的值
mov eax,ebp

指針變量賦值

//int age = 3;
//ebp-0Ch是age的地址值
008519C2 mov dword ptr [ebp-0Ch],3

//eax == ebp-0Ch,存放著age的地址值
008519C9 lea eax,[ebp-0Ch]
//ebp-18h是指針變量p的地址值
//將age的地址值存放到指針變量p所在的存儲空間
//int *p = &age;
008519CC mov dword ptr [ebp-18h],eax

//*p = 5
//將age的地址值存放到eax
008519CF mov eax,dword ptr [ebp-18h]
//age = 5
008519D2 mov dword ptr [eax],5

指針變量的地址值,另外一個變量的地址值賦值給指針變量去存儲
lea eax,[ebp-0Ch]
mov dword ptr [ebp-18h],eax
如下圖:引用的內存匯編和指針變量一模一樣


image

3.引用

A.結構體引用

#include <iostream>
using namespace std;
struct Date {
    int year;
    int month;
    int day;
};
int main(int argc, const char * argv[]) {
    Date d = {2011,1,5};
    Date &ref = d;
    ref.year = 2014;
    
    getchar();
    return 0;
}

B.指針引用

int main(int argc, const char * argv[]) {
    int age = 10;
    int *p = &age;
    int *&ref = p;
    *ref = 30;
    int height = 30;
    ref = &height;
    
    getchar();
    return 0;
}

C.數組引用

int main(int argc, const char * argv[]) {
    int array[] = {1,2,3};
    int (&arr)[3] = array;
    
    int *p;
    //指針數組
    int *a[3] = {p,p,p};
    //數組指針:指向數組的指針
    int (*ar)[3] = &array;
    
    getchar();
    return 0;
}

不存在引用的引用,指向引用的指針,引用數組

D.常引用(Const Reference)

? 引用可以被const修飾,這樣就無法通過引用修改數據了,可以稱為常引用

int main(int argc, const char * argv[]) {
    int age = 10;
    const int &ref = age;
    const int *p = &age;
//    ref = 30;
//    *p = 30;
    cout << ref << endl;
    cout << *p << endl;
    getchar();
    return 0;
}
//輸出
10
10

? const、指針、引用

int main(int argc, const char * argv[]) {
    int height = 20;
    int age = 10;
    
    //ref1不能修改指向,但是可以通過ref1間接修改指向的變量的值
//    int& const ref1 = age;const可以直接去掉,引用本來就不能修改指向
//    ref1 = 30;不報錯
    //ref2不能修改指向,不可以通過ref2間接修改指向的變量的值
    int const &ref2 = age;
//    ref2 = 30;報錯
    
    //p1不能修改指向,可以利用p1間接修改指向的變量
    int * const p1 = &age;
    *p1 = 40;
    
    //p2可以修改指向,不可以利用p2間接修改指向的變量
    int const *p2 = &age;
//    *p2 = 50;報錯
    p2 = &height;
    
    getchar();
    return 0;
}

const必須寫在&符號的左邊,才能算是常引用
? const引用的特點
可以指向臨時數據(常量、表達式、函數返回值等)
可以指向不同類型的數據
作為函數參數時(此規則也適用于const指針)
? 可以接受const和非const實參(非const引用,只能接受非const實參)
? 可以跟非const引用構成重載

int func(){
    return 8;
}
int sum(int &v1,int &v2){
    cout << "sum(int &v1,int &v2)" << endl;
    return v1 + v2;
}
int sum(const int &v1,const int &v2){
    cout << "sum(const int &v1,const int &v2)" << endl;
    return v1 + v2;
}

int main(int argc, const char * argv[]) {
    //非const實參
    int c = 10;
    int d = 20;
    sum(c, d);
    
    //const實參
    const int e = 10;
    const int f = 20;
    sum(e, f);
    
    sum(10, 20);
    
    int a = 1;
    int b = 2;
    const int &ref = 30;
    const int &ref0 = a + b;
    const int &ref1 = func();
    
    int age = 10;
    const double &ref3 = age;
    
    getchar();
    return 0;
}
//輸出
sum(int &v1,int &v2)
sum(const int &v1,const int &v2)
sum(const int &v1,const int &v2)

? 當常引用指向了不同類型的數據時,會產生臨時變量,即引用指向的并不是初始化時的那個變量

I.常引用ref指向了相同類型數據

int main() {
    int age = 10;
    const int &ref = age;
    age = 30;
    cout << "age is " << age << endl;
    cout << "ref is " << ref << endl;
    getchar();
    return 0;
}
//輸出
age is 30
ref is 30

查看匯編,age的值變為了30,ref的值也變為了30

//int age = 10;
mov dword ptr [ebp-0Ch],0Ah
//age的內存地址給到eax
lea eax,[ebp-0Ch]
//[ebp-18h]這段內存空間存放age的內存空間[ebp-0Ch]
mov dword ptr [ebp-18h],eax
//30賦值給[ebp-0Ch]內存地址
mov dword ptr [ebp-0Ch],1Eh

II.常應用ref指向了不同類型數據

#include <iostream>
using namespace std;

int main() {
    /*
    int age = 10;
    const int &ref = age;
    age = 30;
    cout << "age is " << age << endl;
    cout << "ref is " << ref << endl;
     */
    int age = 10;
    const long &ref = age;
    age = 30;
    cout << "age is " << age << endl;
    cout << "ref is " << ref << endl;
    getchar();
    return 0;
}
//輸出
age is 30
ref is 10

查看匯編,age的值變為了30,而引用ref沒有變,在一塊新的內存空間中存儲

//int age = 10;
mov dword ptr [ebp-0Ch],0Ah
//將10取出來給eax
mov eax,dword ptr [ebp-0Ch]
//將eax給到[ebp-24h]這段內存空間,相當于temp
mov dword ptr [ebp-24h],eax
//將[ebp-24h]這段內存空間 temp給到ecx
lea ecx,[ebp-24h]
//將ecx里面的內存地址的值取出來給到[ebp-18h]
mov dword ptr [ebp-18h],ecx
//將30給到[ebp-0Ch],age就變化了,ref沒有變化
mov dword ptr [ebp-0Ch],1Eh

E.不同的編程語言轉成的匯編是一樣的嗎?

Java,C++,OC,Swift寫代碼--->匯編機器碼取決于CPU架構(X86,ARM)。

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 匯編與機器代碼一一對應,但是匯編代碼卻與高級語言不是一一對應的。 上述為兩串代碼所對應的機器代碼和匯編語言,從其中...
    空城難入_d569閱讀 146評論 0 0
  • 1 內存訪問指令 1.1 LDR:字數據讀取指令 指令語法格式: LDR Rd, <地址>LDR指令用于從地...
    城市的風10閱讀 1,764評論 0 0
  • struct和class的區別 1、struct的默認成員權限是public2、class的默認成員權限是priv...
    zhouluyao閱讀 2,032評論 0 2
  • 1.c++發展史 c++20.。。。。不斷更新 2.cin、cout c++中常使用cin、cout進行控制臺的輸...
    無涯之涯閱讀 246評論 0 0
  • 《C++文章匯總》[http://www.lxweimin.com/p/bbd842438420]上一篇文章介紹了...
    一畝三分甜閱讀 504評論 0 0