从汇编看C++类的实现(2)

本文主要从汇编的角度,看C++的类是如何实现的。

1.假设有如下Cpp文件

点击查看代码
//file:fraction.h
class fraction {
        public:
                fraction();
                int public_int;
                int getprivate();
                void setpub();
        private:
                int private_int;
};

//file:fraction.cpp
#include "fraction.h"
fraction::fraction(){
    private_int = 0;
    public_int = 0;
}
void fraction::setpub(){
    public_int = 1;
}
int fraction::getprivate(){
    return private_int;
}

//file:main.cpp
#include "fraction.h"
fraction::fraction(){
    private_int = 0;
    public_int = 0;
}
void fraction::setpub(){
    public_int = 1;
}
int fraction::getprivate(){
    return private_int;
}

1.通过GCC命令生成汇编文件

gcc -o fraction.s -fverbose-asm -S -O0 -g fraction.cpp
gcc -o main.s -fverbose-asm -S -O0 -g main.cpp

点击查看代码
##file:main.s
main:
        endbr64
        pushq   %rbp    #
        movq    %rsp, %rbp      #,
        subq    $32, %rsp       #,
# main.cpp:2: int main() {
        movq    %fs:40, %rax    # MEM[(<address-space-1> long unsigned int *)40B], tmp89
        movq    %rax, -8(%rbp)  # tmp89, D.2357
        xorl    %eax, %eax      # tmp89
# main.cpp:3:   fraction a;
        leaq    -16(%rbp), %rax #, tmp85
        movq    %rax, %rdi      # tmp85,
        call    _ZN8fractionC1Ev@PLT    #
# main.cpp:4:   a.setpub();
        leaq    -16(%rbp), %rax #, tmp86
        movq    %rax, %rdi      # tmp86,
        call    _ZN8fraction6setpubEv@PLT       #
# main.cpp:5:   int b = a.getprivate();
        leaq    -16(%rbp), %rax #, tmp87
        movq    %rax, %rdi      # tmp87,
        call    _ZN8fraction10getprivateEv@PLT  #
        movl    %eax, -20(%rbp) # _6, b
# main.cpp:6:   return 0;
        movl    $0, %eax        #, _8
# main.cpp:7: }
        movq    -8(%rbp), %rdx  # D.2357, tmp90
        xorq    %fs:40, %rdx    # MEM[(<address-space-1> long unsigned int *)40B], tmp90
        je      .L3     #,
        call    __stack_chk_fail@PLT    #
        leave
        ret

## file:fraction.s
_ZN8fractionC2Ev:
        endbr64
        pushq   %rbp    #
        movq    %rsp, %rbp      #,
        movq    %rdi, -8(%rbp)  # this, this
# fraction.cpp:3:     private_int = 0;
        movq    -8(%rbp), %rax  # this, tmp82
        movl    $0, 4(%rax)     #, this_2(D)->private_int
# fraction.cpp:4:     public_int = 0;
        movq    -8(%rbp), %rax  # this, tmp83
        movl    $0, (%rax)      #, this_2(D)->public_int
# fraction.cpp:5: }
        nop
        popq    %rbp    #
        ret

_ZN8fraction6setpubEv:
        endbr64
        pushq   %rbp    #
        movq    %rsp, %rbp      #,
        movq    %rdi, -8(%rbp)  # this, this
# fraction.cpp:7:     public_int = 1;
        movq    -8(%rbp), %rax  # this, tmp82
        movl    $1, (%rax)      #, this_2(D)->public_int
# fraction.cpp:8: }
        nop
        popq    %rbp    #
        ret


_ZN8fraction10getprivateEv:
        endbr64
        pushq   %rbp    #
        movq    %rsp, %rbp      #,
        movq    %rdi, -8(%rbp)  # this, this
# fraction.cpp:10:     return private_int;
        movq    -8(%rbp), %rax  # this, tmp84
        movl    4(%rax), %eax   # this_2(D)->private_int, _3
# fraction.cpp:11: }
        popq    %rbp    #
        ret

1.1.从生成的汇编代码,CPP的constructr函数只是把对象的指针传入其中,并且调用了constrctor函数而已。如下所示

fraction a;

    leaq    -16(%rbp), %rax #, tmp85
    movq    %rax, %rdi      # tmp85,
    call    _ZN8fractionC1Ev@PLT    #

1.2.从生成的汇编代码,一般的Cpp类的函数调用只是,把对象的指针作为第一个参数传入其中,并且调用对应的cpp函数而已。如下所示

main.cpp:4: a.setpub();

    leaq    -16(%rbp), %rax #, tmp86
    movq    %rax, %rdi      # tmp86,
    call    _ZN8fraction6setpubEv@PLT       #

main.cpp:5: int b = a.getprivate();

    leaq    -16(%rbp), %rax #, tmp87
    movq    %rax, %rdi      # tmp87,
    call    _ZN8fraction10getprivateEv@PLT  #
    movl    %eax, -20(%rbp) # _6, b

Summary

CPP的类的函数调用本质上只是普通的C语言的方法调用,唯一的区别就是每一个函数的第一个参数会传入对象的所在地址的。 并且CPP类的函数的命名在汇编的层面上有自己的规则(比如_ZN8fractionC1Ev@PLT这个函数是类的constrctor的)。

Reference

[1] https://bob.cs.sonoma.edu/IntroCompOrg-x64/bookch13.html#x34-15600013

posted @ 2022-08-21 22:08  哇哩顾得  阅读(92)  评论(0编辑  收藏  举报