国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > C++ > 正文

從匯編看c++中引用與指針的使用分析

2020-01-26 16:17:50
字體:
來源:轉載
供稿:網友

首先是引用情形下的c++源碼:

復制代碼 代碼如下:

void add(int a, int b, int&c) {
    c = a + b;
}


int main() {
    int a = 1;
    int b = 2;
    int c = 0;
    add(a, b, c);

}


下面是main對應的匯編碼:
復制代碼 代碼如下:

; 6    : int main() {

    push    ebp
    mov    ebp, esp
    sub    esp, 12                    ; 為該調用函數的棧空間預留12byte,用來存儲局部變量a,b, c

; 7    :     int a = 1;

    mov    DWORD PTR _a$[ebp], 1;初始化a _a$為a存儲空間地址相對于ebp基址的偏移量

; 8    :     int b = 2;

    mov    DWORD PTR _b$[ebp], 2;初始化b _b$為b存儲空間地址相對于ebp基址的偏移量

; 9    :     int c = 0;

    mov    DWORD PTR _c$[ebp], 0;初試化c _c$為c存儲空間地址相對于ebp基址的偏移量

; 10   :     add(a, b, c);
    lea    eax, DWORD PTR _c$[ebp]; 獲取c存儲空間相對于ebp基址的偏移量(即c存儲單元的偏移地址),放在寄存器eax中
    push    eax;保存c存儲空間的偏移量到堆棧中
    mov    ecx, DWORD PTR _b$[ebp];將b存儲空間里面的值(即b的值)放在寄存器ecx中
    push    ecx;保存b存儲空間的值到堆棧中
    mov    edx, DWORD PTR _a$[ebp];將a存儲空間里面的值(即a的值)放在寄存器edx里面
    push    edx;保存a存儲空間的到堆棧

    ;上面push eax push ecx push edx在棧里面存儲了原來局部變量a,b,c的值,只不過對于c來說,存儲的是c存儲空間的偏移地址
    ;因此,對于a,b來說,也就是將他們的值得一份拷貝存了起來,也就是傳值;而c只是存儲了自己存儲空間的偏移地址,也就是傳地址
    call    ?add@@YAXHHAAH@Z            ; 調用add函數,上面的語句已經為傳遞參數做好了準備
    add    esp, 12                    ; 由于剛才為調用函數add傳遞參數進行了壓棧,這里釋放??臻g,即釋放參數
                                ;這就是為什么函數調用完成后局部變量和參數無效的原因,因為他們的空間被釋放了

; 11   :    
; 12   : }

    xor    eax, eax
    mov    esp, ebp
    pop    ebp
    ret    0


下面是函數add對應的匯編碼:
復制代碼 代碼如下:

; 1    : void add(int a, int b, int&c) {

    push    ebp
    mov    ebp, esp

; 2    :     c = a + b;

    mov    eax, DWORD PTR _a$[ebp];取參數a的值到寄存器eax中
    add    eax, DWORD PTR _b$[ebp];取參數b的值與eax中a的值相加,結果放到eax中
    mov    ecx, DWORD PTR _c$[ebp];去c的偏移地址放到寄存器ecx中
    mov    DWORD PTR [ecx], eax;將eax中的結果寫到由ecx指定的地址單元中去,即c所在存儲單元

; 3    : }

    pop    ebp
    ret    0


從上面可以看到,對于傳值,c++確實傳的是一份值拷貝,而對于引用,雖然是傳值的形式,但是其實編譯器內部傳遞的是值得地址

下面是指針的情形的c++源碼:

復制代碼 代碼如下:

void add(int a, int b, int* c) {
    *c = a + b;
}


int main() {
    int a = 1;
    int b = 2;
    int c = 0;
    add(a, b, &c);

}


mian函數對應的匯編碼:
復制代碼 代碼如下:

; 6    : int main() {

    push    ebp
    mov    ebp, esp
    sub    esp, 12                    ;

; 7    :     int a = 1;

    mov    DWORD PTR _a$[ebp], 1

; 8    :     int b = 2;

    mov    DWORD PTR _b$[ebp], 2

; 9    :     int c = 0;

    mov    DWORD PTR _c$[ebp], 0

; 10   :     add(a, b, &c);

    lea    eax, DWORD PTR _c$[ebp]
    push    eax
    mov    ecx, DWORD PTR _b$[ebp]
    push    ecx
    mov    edx, DWORD PTR _a$[ebp]
    push    edx
    call    ?add@@YAXHHPAH@Z            ; add
    add    esp, 12                    ;
; 11   :    
; 12   : }

    xor    eax, eax
    mov    esp, ebp
    pop    ebp
    ret    0


add函數對應的匯編碼:
復制代碼 代碼如下:

; 1    : void add(int a, int b, int* c) {

    push    ebp
    mov    ebp, esp

; 2    :     *c = a + b;

    mov    eax, DWORD PTR _a$[ebp]
    add    eax, DWORD PTR _b$[ebp]
    mov    ecx, DWORD PTR _c$[ebp]
    mov    DWORD PTR [ecx], eax

; 3    : }

    pop    ebp
    ret    0


可以看到,指針和引用的匯編碼一樣,因此兩者的作用也一樣

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 舞钢市| 明溪县| 车致| 珲春市| 奇台县| 饶阳县| 乌兰浩特市| 无锡市| 拜城县| 枣阳市| 建水县| 洛川县| 蒙山县| 田阳县| 扎赉特旗| 太和县| 大丰市| 湄潭县| 临沭县| 深州市| 兴国县| 阿瓦提县| 瑞金市| 江陵县| 聊城市| 新余市| 溆浦县| 高青县| 博爱县| 绥宁县| 双峰县| 山东省| 永年县| 电白县| 保康县| 临沧市| 保德县| 保德县| 吉林省| 饶阳县| 宾川县|