从汇编看C++函数传入对象以及返回对象

测试代码structpass.cpp
struct Vertex
{
        int x, y, z;
};
Vertex getVertex(Vertex a)
{
        a.x = 111;
        a.z = 222;
        return a;
}
int main() {
        Vertex t;
        t.x = 1;
        t.y = 2;
        t.z = 3;
        Vertex y = getVertex(t);
        y.x = 7;
        y.y = 8;
        y.z = 9;
        t.x = 11;
        t.y = 21;
        t.z = 31;
        return 0;
}

这段代码在gcc下生成汇编,g++ -o structpass.s -fverbose-asm -S -O0 -g structpass.cpp, 得到汇编代码如下。

汇编代码
_Z9getVertex6Vertex:
.LFB0:
        .file 1 "structpass.cpp"
        .loc 1 6 1
        .cfi_startproc
        endbr64
        pushq   %rbp    #
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        movq    %rsp, %rbp      #,
        .cfi_def_cfa_register 6
        movq    %rdi, %rdx      # a, tmp83
        movl    %esi, %eax      # a, tmp84
        movq    %rdx, -32(%rbp) # tmp83, a
        movl    %eax, -24(%rbp) # tmp84, a
# structpass.cpp:7:     a.x = 111;
        .loc 1 7 6
        movl    $111, -32(%rbp) #, a.x
# structpass.cpp:8:     a.z = 222;
        .loc 1 8 6
        movl    $222, -24(%rbp) #, a.z
# structpass.cpp:9:         return a;
        .loc 1 9 16
        movq    -32(%rbp), %rax # a, tmp85
        movq    %rax, -12(%rbp) # tmp85, D.2351
        movl    -24(%rbp), %eax # a, tmp86
        movl    %eax, -4(%rbp)  # tmp86, D.2351
        movq    -12(%rbp), %rax # D.2351, tmp87
        movl    -4(%rbp), %ecx  # D.2351, tmp88
        movq    %rcx, %rdx      # tmp88,
# structpass.cpp:10: }
        .loc 1 10 1
        popq    %rbp    #
        .cfi_def_cfa 7, 8
        ret
        .cfi_endproc

main:
        endbr64
        pushq   %rbp    #
        movq    %rsp, %rbp      #,
        subq    $32, %rsp       #,
# structpass.cpp:11: int main() {
        movq    %fs:40, %rax    # MEM[(<address-space-1> long unsigned int *)40B], tmp93
        movq    %rax, -8(%rbp)  # tmp93, D.2358
        xorl    %eax, %eax      # tmp93
# structpass.cpp:13:         t.x = 1;
        movl    $1, -32(%rbp)   #, t.x
# structpass.cpp:14:         t.y = 2;
        movl    $2, -28(%rbp)   #, t.y
# structpass.cpp:15:         t.z = 3;
        movl    $3, -24(%rbp)   #, t.z
# structpass.cpp:16:         Vertex y = getVertex(t);
        movq    -32(%rbp), %rdx # t, tmp84
        movl    -24(%rbp), %eax # t, tmp85
        movq    %rdx, %rdi      # tmp84,
        movl    %eax, %esi      # tmp85,
        call    _Z9getVertex6Vertex     #
        movq    %rax, -20(%rbp) # tmp86, y
        movl    -12(%rbp), %eax # y, tmp89
        andl    $0, %eax        #, tmp90
        orl     %edx, %eax      # tmp88, tmp91
        movl    %eax, -12(%rbp) # tmp91, y
# structpass.cpp:17:         y.x = 7;
        movl    $7, -20(%rbp)   #, y.x
# structpass.cpp:18:         y.y = 8;
        movl    $8, -16(%rbp)   #, y.y
# structpass.cpp:19:         y.z = 9;
        movl    $9, -12(%rbp)   #, y.z
# structpass.cpp:20:         t.x = 11;
        movl    $11, -32(%rbp)  #, t.x
# structpass.cpp:21:         t.y = 21;
        movl    $21, -28(%rbp)  #, t.y
# structpass.cpp:22:         t.z = 31;
        movl    $31, -24(%rbp)  #, t.z
# structpass.cpp:23:         return 0;
        movl    $0, %eax        #, _12
# structpass.cpp:24: }
        movq    -8(%rbp), %rcx  # D.2358, tmp94
        xorq    %fs:40, %rcx    # MEM[(<address-space-1> long unsigned int *)40B], tmp94
        je      .L5     #,
        call    __stack_chk_fail@PLT    #
.L5:
        leave
        .cfi_def_cfa 7, 8
        ret
        .cfi_endproc

结论1. 当一个函数传入一个对象或者struct的时候,会先在这个函数的[rbp, rsp]之间生成一个临时存放的stack空间, 把传入对象一模一样的copy到这个stack空间中]
	movq    %rdx, -32(%rbp) # tmp83, a
	movl    %eax, -24(%rbp) # tmp84, a
    a.x = 111;
    movl    $111, -32(%rbp) #, a.x
    a.z = 222;
    movl    $222, -24(%rbp) #, a.z

结论2. 返回的对象并不是结论一中copy的对象,而是重新在[rbp, rsp]分配另外的stack空间,一模一样的复制到这个空间中,再把这个stack的地址传到调用函数。

结论3.调用函数在自己的stack中,通过传回来的寄存器,rax or rdx之类的,一模一样的复制到stack空间中。
call _Z9getVertex6Vertex #
movq %rax, -20(%rbp) # tmp86, y
movl -12(%rbp), %eax # y, tmp89
andl $0, %eax #, tmp90
orl %edx, %eax # tmp88, tmp91
movl %eax, -12(%rbp) # tmp91, y

posted @ 2022-09-23 00:15  哇哩顾得  阅读(87)  评论(0编辑  收藏  举报