Analysis of the use of references and Pointers in c++ from assembly

  • 2020-04-01 21:38:55
  • OfStack

The first is the reference case of c++ source code:


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);

}

The following is the assembly code corresponding to main:

; 6    : int main() {
    push    ebp
    mov    ebp, esp
    sub    esp, 12                    ;  Reserve the stack space for the calling function 12byte To store local variables a . b, c
; 7    :     int a = 1;
    mov    DWORD PTR _a$[ebp], 1; Initialize the a _a$ for a Storage space address relative to ebp The offset of the base address 
; 8    :     int b = 2;
    mov    DWORD PTR _b$[ebp], 2; Initialize the b _b$ for b Storage space address relative to ebp The offset of the base address 
; 9    :     int c = 0;
    mov    DWORD PTR _c$[ebp], 0; First try, c _c$ for c Storage space address relative to ebp The offset of the base address 
; 10   :     add(a, b, c);
    lea    eax, DWORD PTR _c$[ebp];  To obtain c Storage space relative to ebp The offset of the base address ( namely c The offset address of the storage location ), Put in register eax In the 
    push    eax; save c Memory space offset to the stack 
    mov    ecx, DWORD PTR _b$[ebp]; will b The value in the storage space ( namely b The value of the ) Put in register ecx In the 
    push    ecx; save b The value of the storage space to the stack 
    mov    edx, DWORD PTR _a$[ebp]; will a The value in the storage space ( namely a The value of the ) Put in register edx inside 
    push    edx; save a Storage space to the stack 

    ; The above push eax push ecx push edx The original local variables are stored in the stack a . b . c Theta, except for theta c In terms of storage is c The offset address of the storage space 
    ; So, for a . b That is, to save a copy of their worth, that is, to pass the value; while c Just stored their own storage space offset address, that is, the address 
    call    ?add@@YAXHHAAH@Z            ;  call add The above statement is ready to pass arguments 
    add    esp, 12                    ;  Because I just called the function add Pass the parameters to the stack, where the stack space is freed, that is, the parameters are released 
                                ; That's why local variables and arguments are not valid after the function call, because their space is freed, right 
; 11   :     
; 12   : }
    xor    eax, eax
    mov    esp, ebp
    pop    ebp
    ret    0

The following is the assembly code corresponding to the function 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]; Take parameters a To register eax In the 
    add    eax, DWORD PTR _b$[ebp]; Take parameters b The value of and eax In the a I'm going to add up the values of theta eax In the 
    mov    ecx, DWORD PTR _c$[ebp]; Go to the c The offset address of ecx In the 
    mov    DWORD PTR [ecx], eax; will eax The results are written by ecx In the specified address cell, i.e c Storage location 
; 3    : }
    pop    ebp
    ret    0

As you can see from the above, c++ does indeed pass a copy of the value for the pass value, while for the reference, it is passed in the form of the pass value, but the value address is passed inside the compiler

The following is the case of pointer c++ source code:


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);

}

Assembly code corresponding to mian function:

; 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

The assembly code corresponding to the add function:

; 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

As you can see, a pointer is the same as the sink code for a reference, so both work the same way


Related articles: