工厂机制是UVM的关键特性之一,在讨论UVM工厂机制实现之前,我们先讨论工厂机制实现的基石:类静态函数和类静态变量。
由于UVM的实现语言SV(SystemVerilog)的底层实现不可见,我们使用C++和汇编语言进行讨论。接下来从应用层次和实现层次讨论静态变量和静态函数。
talk is cheap,show me the code。首先上一段C++代码。
//filename: hello.cpp
//#include <iostream>
#define MAX_ANIMAL_NUM 20
//#define NULL 0
#if defined(__cplusplus)
#define NULL 0
#else
#define NULL ((void *)0)
#endif
class ANIMAL
{/*{{{*/
public:
int age;
public:
static int animal_num;
static ANIMAL *self_id;
static ANIMAL* animal_list[MAX_ANIMAL_NUM];
static void record_anmimal(ANIMAL* obj) {/*{{{*/
if(animal_num==MAX_ANIMAL_NUM) return;
animal_list[animal_num-1] = obj;
return;
}/*}}}*/
void print_age(){/*{{{*/
//std::cout << "age is " << age << std::endl;
}/*}}}*/
static void print_record(){/*{{{*/
for(int i=0; i<animal_num; i++){
animal_list[i]->print_age();
}
}/*}}}*/
static ANIMAL *get(int age=0) {/*{{{*/
if(self_id==NULL) {
self_id = new ANIMAL(age);
record_anmimal(self_id);
}
return self_id;
}/*}}}*/
static void print_animal_num() {/*{{{*/
//std::cout << "animal_num is " << animal_num << std::endl;
}/*}}}*/
void set_age(int age) {/*{{{*/
this->age=age;
}/*}}}*/
public:
ANIMAL() {animal_num++;}
~ANIMAL() {animal_num--;}
ANIMAL(int age) {
this->age = age;
animal_num++;
}
};/*}}}*/
class DOG : public ANIMAL
{/*{{{*/
public:
static DOG *self_id;
static DOG *get(int age=0)
{/*{{{*/
if(self_id==NULL) {
self_id = new DOG(age);
//record_anmimal(self_id);
record_anmimal((ANIMAL*)self_id);
}
return self_id;
}/*}}}*/
public:
DOG() {}
DOG(int age):ANIMAL(age) {}
~DOG() {}
};/*}}}*/
class CAT : public ANIMAL
{/*{{{*/
public:
static CAT *self_id;
static CAT *get(int age=0)
{/*{{{*/
if(self_id==NULL) {
self_id = new CAT(age);
//record_anmimal(self_id);
record_anmimal((ANIMAL*)self_id);
}
return self_id;
}/*}}}*/
public:
CAT() {}
CAT(int age):ANIMAL(age) {}
~CAT() {}
};/*}}}*/
int ANIMAL::animal_num = 0;
ANIMAL* ANIMAL::animal_list[MAX_ANIMAL_NUM]; //NOTE: must declare it
ANIMAL* ANIMAL::self_id = ANIMAL::get(99);
DOG* DOG::self_id = DOG::get(0x5a);
CAT* CAT::self_id = CAT::get(0xa5);
const int animal_num_limit_const[3]= {999,0x5a5a,0xa5a5};
int animal_num_limit_var[3]= {999,0x5a5a,0xa5a5};
int bss_buffer[65536];
int main(int argc, char* argv[])
{/*{{{*/
ANIMAL::print_animal_num();
ANIMAL *a0 = ANIMAL::get();
//a0->set_age(2);
ANIMAL::print_animal_num();
DOG *d0 = DOG::get();
//d0->set_age(3);
ANIMAL::print_animal_num();
CAT *c0 = CAT::get();
//c0->set_age(4);
ANIMAL::print_animal_num();
ANIMAL::print_record();
delete ANIMAL::self_id;
ANIMAL::print_animal_num();
delete DOG::self_id;
ANIMAL::print_animal_num();
delete CAT::self_id;
ANIMAL::print_animal_num();
bss_buffer[0]= 3;
for(int i=0; i<argc; i++) {
bss_buffer[i] = i;
//std::cout<< i << "t:" << bss_buffer[i]<<std::endl;
}
return 0;
}/*}}}*/
由于假定了我们的读者具备基本的C++/SV知识,代码的具体内容不再此处赘述。若对本文感兴趣,可花三五小时熟悉下C++的基本知识后再阅读此文。
在C++中,类的静态变量初值若是字面常量可以直接声明并初始化,若初值非字面常量,需要在类外进行声明并初始化赋值(line93~97)。
首先从应用层次看类静态变量和类静态函数。
初值非字面常量的类静态变量是在类中使用static声明、在全局代码区初始化的数据,生命周期和作用范围和全局变量是一致的。
类静态函数在声明时区别于一般类函数的是增加了static关键词。类静态函数属于类,而不属于实例,可通过类符号或实例调用。它不可访问对象/类实例的数据,可以访问类静态变量(其他类的静态变量也可以)和全局变量。
接下来从实现角度看静态函数和静态变量。在msys2终端中使用g++ -masm=intel -S hello.cpp生成汇编语言,可以很容易看出类静态变量和类静态函数在实现上的特点。由于汇编代码由600+行,列在文章最后。
汇编代码较多,添加vim折叠标记后进行折叠,可以得到清晰的代码结构。

类ANIMAL/DOG/CAT的所有函数在;;;function definitions区域定义,包括类静态函数。从底层实现角度看,类静态函数和一般函数是没有什么分别的。
类静态变量则定义/存在于在.bss段,并且编译器生成用于初始化所有类静态变量的初始化函数,这个函数在main函数执行前执行。其中未初始化或初始化值非字面常量的全局变量也在.bss段。
.bss段和.data段(.rdata段是只读的.data段)在内存中的区域都在main执行前初始化,它们的区别在于初始化方式不同。.data段的值在编译时已确定,这些值被编译器写入可执行文件,加载可执行文件时简单的搬运数据以实现.data段内存初始化。而.bss段的值在编译时无法确定或无法简单地确定,因此编译器通常写入可执行文件的是.bss段大小等信息和初始化.bss段的代码。加载可执行文件时申请分配.bss内存,并在main执行前执行.bss段初始化函数,完成.bss段在内存中的初始化工作。
以上是C++的类静态函数和类变量在应用层面和实现层面的简要介绍。SV在静态变量初始化这方便区别于C++的地方在于是SV支持类静态变量在类中直接声明并初始化。SV的静态数据初始化应该是在第一个事件调度time-slot之前完成的。
建议读者在https://www.edaplayground.com/中使用在线的SV编译仿真器irun尝试体会下SV的静态函数和静态变量,尤其是静态变量为关联数组或队列的情况,这是UVM工厂机制的实现基石之一。
【CONTINUED:下一篇文章,我们将聊一聊OOP面向对象程度设计的设计原则和设计模式】
以下是hello.cpp对应的汇编代码,由于语言选择中没有assembly,选择了Clojure,彩色高亮显示有点怪异。
;;;filename: hello.s
.file "hello.cpp"
.intel_syntax noprefix
;;; function definitions
;;;{{{
.text
;;; ANIMAL::record_anmimal
;;;{{{
.section .text$_ZN6ANIMAL14record_anmimalEPS_,"x"
.linkonce discard
.globl _ZN6ANIMAL14record_anmimalEPS_
.def _ZN6ANIMAL14record_anmimalEPS_; .scl 2; .type 32; .endef
.seh_proc _ZN6ANIMAL14record_anmimalEPS_
_ZN6ANIMAL14record_anmimalEPS_:
.LFB0:
push rbp
.seh_pushreg rbp
mov rbp, rsp
.seh_setframe rbp, 0
.seh_endprologue
mov QWORD PTR 16[rbp], rcx
mov eax, DWORD PTR _ZN6ANIMAL10animal_numE[rip]
cmp eax, 20
je .L4
mov eax, DWORD PTR _ZN6ANIMAL10animal_numE[rip]
sub eax, 1
cdqe
lea rcx, 0[0+rax*8]
lea rdx, _ZN6ANIMAL11animal_listE[rip]
mov rax, QWORD PTR 16[rbp]
mov QWORD PTR [rcx+rdx], rax
jmp .L1
.L4:
nop
.L1:
pop rbp
ret
.seh_endproc
;;;}}}
;;; ANIMAL::print_age
;;;{{{
.section .text$_ZN6ANIMAL9print_ageEv,"x"
.linkonce discard
.align 2
.globl _ZN6ANIMAL9print_ageEv
.def _ZN6ANIMAL9print_ageEv; .scl 2; .type 32; .endef
.seh_proc _ZN6ANIMAL9print_ageEv
_ZN6ANIMAL9print_ageEv:
.LFB1:
push rbp
.seh_pushreg rbp
mov rbp, rsp
.seh_setframe rbp, 0
.seh_endprologue
mov QWORD PTR 16[rbp], rcx
nop
pop rbp
ret
.seh_endproc
;;;}}}
;;; ANIMAL::print_record
;;;{{{
.section .text$_ZN6ANIMAL12print_recordEv,"x"
.linkonce discard
.globl _ZN6ANIMAL12print_recordEv
.def _ZN6ANIMAL12print_recordEv; .scl 2; .type 32; .endef
.seh_proc _ZN6ANIMAL12print_recordEv
_ZN6ANIMAL12print_recordEv:
.LFB2:
push rbp
.seh_pushreg rbp
mov rbp, rsp
.seh_setframe rbp, 0
sub rsp, 48
.seh_stackalloc 48
.seh_endprologue
mov DWORD PTR -4[rbp], 0
.L8:
mov eax, DWORD PTR _ZN6ANIMAL10animal_numE[rip]
cmp DWORD PTR -4[rbp], eax
jge .L9
mov eax, DWORD PTR -4[rbp]
cdqe
lea rdx, 0[0+rax*8]
lea rax, _ZN6ANIMAL11animal_listE[rip]
mov rax, QWORD PTR [rdx+rax]
mov rcx, rax
call _ZN6ANIMAL9print_ageEv
add DWORD PTR -4[rbp], 1
jmp .L8
.L9:
nop
add rsp, 48
pop rbp
ret
.seh_endproc
;;;}}}
;;; ANIMAL::get
;;;{{{
.section .text$_ZN6ANIMAL3getEi,"x"
.linkonce discard
.globl _ZN6ANIMAL3getEi
.def _ZN6ANIMAL3getEi; .scl 2; .type 32; .endef
.seh_proc _ZN6ANIMAL3getEi
_ZN6ANIMAL3getEi:
.LFB3:
push rbp
.seh_pushreg rbp
push rbx
.seh_pushreg rbx
sub rsp, 40
.seh_stackalloc 40
lea rbp, 128[rsp]
.seh_setframe rbp, 128
.seh_endprologue
mov DWORD PTR -64[rbp], ecx
mov rax, QWORD PTR _ZN6ANIMAL7self_idE[rip]
test rax, rax
jne .L11
mov ecx, 4
call _Znwm
mov rbx, rax
mov edx, DWORD PTR -64[rbp]
mov rcx, rbx
call _ZN6ANIMALC1Ei
mov QWORD PTR _ZN6ANIMAL7self_idE[rip], rbx
mov rax, QWORD PTR _ZN6ANIMAL7self_idE[rip]
mov rcx, rax
call _ZN6ANIMAL14record_anmimalEPS_
.L11:
mov rax, QWORD PTR _ZN6ANIMAL7self_idE[rip]
add rsp, 40
pop rbx
pop rbp
ret
.seh_endproc
;;;}}}
;;; ANIMAL::print_animal_num
;;;{{{
.section .text$_ZN6ANIMAL16print_animal_numEv,"x"
.linkonce discard
.globl _ZN6ANIMAL16print_animal_numEv
.def _ZN6ANIMAL16print_animal_numEv; .scl 2; .type 32; .endef
.seh_proc _ZN6ANIMAL16print_animal_numEv
_ZN6ANIMAL16print_animal_numEv:
.LFB4:
push rbp
.seh_pushreg rbp
mov rbp, rsp
.seh_setframe rbp, 0
.seh_endprologue
nop
pop rbp
ret
.seh_endproc
;;;}}}
;;; ANIMAL::set_age
;;;{{{
.section .text$_ZN6ANIMALD2Ev,"x"
.linkonce discard
.align 2
.globl _ZN6ANIMALD2Ev
.def _ZN6ANIMALD2Ev; .scl 2; .type 32; .endef
.seh_proc _ZN6ANIMALD2Ev
_ZN6ANIMALD2Ev:
.LFB10:
push rbp
.seh_pushreg rbp
mov rbp, rsp
.seh_setframe rbp, 0
.seh_endprologue
mov QWORD PTR 16[rbp], rcx
mov eax, DWORD PTR _ZN6ANIMAL10animal_numE[rip]
sub eax, 1
mov DWORD PTR _ZN6ANIMAL10animal_numE[rip], eax
nop
pop rbp
ret
.seh_endproc
;;;}}}
;;; ANIMAL::ANIMAL
;;;{{{
.section .text$_ZN6ANIMALD1Ev,"x"
.linkonce discard
.align 2
.globl _ZN6ANIMALD1Ev
.def _ZN6ANIMALD1Ev; .scl 2; .type 32; .endef
.seh_proc _ZN6ANIMALD1Ev
_ZN6ANIMALD1Ev:
.LFB11:
push rbp
.seh_pushreg rbp
mov rbp, rsp
.seh_setframe rbp, 0
.seh_endprologue
mov QWORD PTR 16[rbp], rcx
mov eax, DWORD PTR _ZN6ANIMAL10animal_numE[rip]
sub eax, 1
mov DWORD PTR _ZN6ANIMAL10animal_numE[rip], eax
nop
pop rbp
ret
.seh_endproc
;;;}}}
;;; ANIMAL::~ANIMAL()
;;;{{{
.section .text$_ZN6ANIMALC2Ei,"x"
.linkonce discard
.align 2
.globl _ZN6ANIMALC2Ei
.def _ZN6ANIMALC2Ei; .scl 2; .type 32; .endef
.seh_proc _ZN6ANIMALC2Ei
_ZN6ANIMALC2Ei:
.LFB13:
push rbp
.seh_pushreg rbp
mov rbp, rsp
.seh_setframe rbp, 0
.seh_endprologue
mov QWORD PTR 16[rbp], rcx
mov DWORD PTR 24[rbp], edx
mov rax, QWORD PTR 16[rbp]
mov edx, DWORD PTR 24[rbp]
mov DWORD PTR [rax], edx
mov eax, DWORD PTR _ZN6ANIMAL10animal_numE[rip]
add eax, 1
mov DWORD PTR _ZN6ANIMAL10animal_numE[rip], eax
nop
pop rbp
ret
.seh_endproc
;;;}}}
;;; ANIMAL::ANIMAL(int age)
;;;{{{
.section .text$_ZN6ANIMALC1Ei,"x"
.linkonce discard
.align 2
.globl _ZN6ANIMALC1Ei
.def _ZN6ANIMALC1Ei; .scl 2; .type 32; .endef
.seh_proc _ZN6ANIMALC1Ei
_ZN6ANIMALC1Ei:
.LFB14:
push rbp
.seh_pushreg rbp
mov rbp, rsp
.seh_setframe rbp, 0
.seh_endprologue
mov QWORD PTR 16[rbp], rcx
mov DWORD PTR 24[rbp], edx
mov rax, QWORD PTR 16[rbp]
mov edx, DWORD PTR 24[rbp]
mov DWORD PTR [rax], edx
mov eax, DWORD PTR _ZN6ANIMAL10animal_numE[rip]
add eax, 1
mov DWORD PTR _ZN6ANIMAL10animal_numE[rip], eax
nop
pop rbp
ret
.seh_endproc
;;;}}}
;;; DOG::get
;;;{{{
.section .text$_ZN3DOG3getEi,"x"
.linkonce discard
.globl _ZN3DOG3getEi
.def _ZN3DOG3getEi; .scl 2; .type 32; .endef
.seh_proc _ZN3DOG3getEi
_ZN3DOG3getEi:
.LFB15:
push rbp
.seh_pushreg rbp
push rbx
.seh_pushreg rbx
sub rsp, 40
.seh_stackalloc 40
lea rbp, 128[rsp]
.seh_setframe rbp, 128
.seh_endprologue
mov DWORD PTR -64[rbp], ecx
mov rax, QWORD PTR _ZN3DOG7self_idE[rip]
test rax, rax
jne .L19
mov ecx, 4
call _Znwm
mov rbx, rax
mov edx, DWORD PTR -64[rbp]
mov rcx, rbx
call _ZN3DOGC1Ei
mov QWORD PTR _ZN3DOG7self_idE[rip], rbx
mov rax, QWORD PTR _ZN3DOG7self_idE[rip]
mov rcx, rax
call _ZN6ANIMAL14record_anmimalEPS_
.L19:
mov rax, QWORD PTR _ZN3DOG7self_idE[rip]
add rsp, 40
pop rbx
pop rbp
ret
.seh_endproc
;;;}}}
;;; DOG::DOG
;;;{{{
.section .text$_ZN3DOGC1Ei,"x"
.linkonce discard
.align 2
.globl _ZN3DOGC1Ei
.def _ZN3DOGC1Ei; .scl 2; .type 32; .endef
.seh_proc _ZN3DOGC1Ei
_ZN3DOGC1Ei:
.LFB21:
push rbp
.seh_pushreg rbp
mov rbp, rsp
.seh_setframe rbp, 0
sub rsp, 32
.seh_stackalloc 32
.seh_endprologue
mov QWORD PTR 16[rbp], rcx
mov DWORD PTR 24[rbp], edx
mov rax, QWORD PTR 16[rbp]
mov edx, DWORD PTR 24[rbp]
mov rcx, rax
call _ZN6ANIMALC2Ei
nop
add rsp, 32
pop rbp
ret
.seh_endproc
;;;}}}
;;; DOG::~DOG
;;;{{{
.section .text$_ZN3DOGD1Ev,"x"
.linkonce discard
.align 2
.globl _ZN3DOGD1Ev
.def _ZN3DOGD1Ev; .scl 2; .type 32; .endef
.seh_proc _ZN3DOGD1Ev
_ZN3DOGD1Ev:
.LFB24:
push rbp
.seh_pushreg rbp
mov rbp, rsp
.seh_setframe rbp, 0
sub rsp, 32
.seh_stackalloc 32
.seh_endprologue
mov QWORD PTR 16[rbp], rcx
mov rax, QWORD PTR 16[rbp]
mov rcx, rax
call _ZN6ANIMALD2Ev
nop
add rsp, 32
pop rbp
ret
.seh_endproc
;;;}}}
;;; CAT::get
;;;{{{
.section .text$_ZN3CAT3getEi,"x"
.linkonce discard
.globl _ZN3CAT3getEi
.def _ZN3CAT3getEi; .scl 2; .type 32; .endef
.seh_proc _ZN3CAT3getEi
_ZN3CAT3getEi:
.LFB25:
push rbp
.seh_pushreg rbp
push rbx
.seh_pushreg rbx
sub rsp, 40
.seh_stackalloc 40
lea rbp, 128[rsp]
.seh_setframe rbp, 128
.seh_endprologue
mov DWORD PTR -64[rbp], ecx
mov rax, QWORD PTR _ZN3CAT7self_idE[rip]
test rax, rax
jne .L24
mov ecx, 4
call _Znwm
mov rbx, rax
mov edx, DWORD PTR -64[rbp]
mov rcx, rbx
call _ZN3CATC1Ei
mov QWORD PTR _ZN3CAT7self_idE[rip], rbx
mov rax, QWORD PTR _ZN3CAT7self_idE[rip]
mov rcx, rax
call _ZN6ANIMAL14record_anmimalEPS_
.L24:
mov rax, QWORD PTR _ZN3CAT7self_idE[rip]
add rsp, 40
pop rbx
pop rbp
ret
.seh_endproc
;;;}}}
;;; CAT::CAT
;;;{{{
.section .text$_ZN3CATC1Ei,"x"
.linkonce discard
.align 2
.globl _ZN3CATC1Ei
.def _ZN3CATC1Ei; .scl 2; .type 32; .endef
.seh_proc _ZN3CATC1Ei
_ZN3CATC1Ei:
.LFB31:
push rbp
.seh_pushreg rbp
mov rbp, rsp
.seh_setframe rbp, 0
sub rsp, 32
.seh_stackalloc 32
.seh_endprologue
mov QWORD PTR 16[rbp], rcx
mov DWORD PTR 24[rbp], edx
mov rax, QWORD PTR 16[rbp]
mov edx, DWORD PTR 24[rbp]
mov rcx, rax
call _ZN6ANIMALC2Ei
nop
add rsp, 32
pop rbp
ret
.seh_endproc
;;;}}}
;;; CAT::~CAT
;;;{{{
.section .text$_ZN3CATD1Ev,"x"
.linkonce discard
.align 2
.globl _ZN3CATD1Ev
.def _ZN3CATD1Ev; .scl 2; .type 32; .endef
.seh_proc _ZN3CATD1Ev
_ZN3CATD1Ev:
.LFB34:
push rbp
.seh_pushreg rbp
mov rbp, rsp
.seh_setframe rbp, 0
sub rsp, 32
.seh_stackalloc 32
.seh_endprologue
mov QWORD PTR 16[rbp], rcx
mov rax, QWORD PTR 16[rbp]
mov rcx, rax
call _ZN6ANIMALD2Ev
nop
add rsp, 32
pop rbp
ret
.seh_endproc
;;;}}}
;;;}}}
;;; .bss, here are class static data, ANIMAL::self_id etc.
;;;{{{
.globl _ZN6ANIMAL10animal_numE
.bss
.align 4
_ZN6ANIMAL10animal_numE:
.space 4
.globl _ZN6ANIMAL11animal_listE
.align 32
_ZN6ANIMAL11animal_listE:
.space 160
.globl _ZN6ANIMAL7self_idE
.align 8
_ZN6ANIMAL7self_idE:
.space 8
.globl _ZN3DOG7self_idE
.align 8
_ZN3DOG7self_idE:
.space 8
.globl _ZN3CAT7self_idE
.align 8
_ZN3CAT7self_idE:
.space 8
;;;}}}
;;; .rdata includes global const-declared data, read only, here are animal_num_limit_const
;;;{{{
.section .rdata,"dr"
.align 8
_ZL22animal_num_limit_const:
.long 999
.long 23130
.long 42405
;;;}}}
;;; .data includes global const-declared data, read and writable, here are animal_num_limit_var
;;;{{{
.globl animal_num_limit_var
.data
.align 8
animal_num_limit_var:
.long 999
.long 23130
.long 42405
;;;}}}
;;; .bss, includes global uninit-declared data, here are bss_buffer
;;;{{{
.globl bss_buffer
.bss
.align 32
bss_buffer:
.space 262144
;;;}}}
;;; main
;;;{{{
.def __main; .scl 2; .type 32; .endef
.text
.globl main
.def main; .scl 2; .type 32; .endef
.seh_proc main
main:
.LFB35:
push rbp
.seh_pushreg rbp
push rbx
.seh_pushreg rbx
sub rsp, 72
.seh_stackalloc 72
lea rbp, 128[rsp]
.seh_setframe rbp, 128
.seh_endprologue
mov DWORD PTR -32[rbp], ecx
mov QWORD PTR -24[rbp], rdx
call __main
call _ZN6ANIMAL16print_animal_numEv
mov ecx, 0
call _ZN6ANIMAL3getEi
mov QWORD PTR -80[rbp], rax
call _ZN6ANIMAL16print_animal_numEv
mov ecx, 0
call _ZN3DOG3getEi
mov QWORD PTR -88[rbp], rax
call _ZN6ANIMAL16print_animal_numEv
mov ecx, 0
call _ZN3CAT3getEi
mov QWORD PTR -96[rbp], rax
call _ZN6ANIMAL16print_animal_numEv
call _ZN6ANIMAL12print_recordEv
mov rbx, QWORD PTR _ZN6ANIMAL7self_idE[rip]
test rbx, rbx
je .L29
mov rcx, rbx
call _ZN6ANIMALD1Ev
mov edx, 4
mov rcx, rbx
call _ZdlPvm
.L29:
call _ZN6ANIMAL16print_animal_numEv
mov rbx, QWORD PTR _ZN3DOG7self_idE[rip]
test rbx, rbx
je .L30
mov rcx, rbx
call _ZN3DOGD1Ev
mov edx, 4
mov rcx, rbx
call _ZdlPvm
.L30:
call _ZN6ANIMAL16print_animal_numEv
mov rbx, QWORD PTR _ZN3CAT7self_idE[rip]
test rbx, rbx
je .L31
mov rcx, rbx
call _ZN3CATD1Ev
mov edx, 4
mov rcx, rbx
call _ZdlPvm
.L31:
call _ZN6ANIMAL16print_animal_numEv
mov DWORD PTR bss_buffer[rip], 3
mov DWORD PTR -68[rbp], 0
.L33:
mov eax, DWORD PTR -68[rbp]
cmp eax, DWORD PTR -32[rbp]
jge .L32
mov eax, DWORD PTR -68[rbp]
cdqe
lea rcx, 0[0+rax*4]
lea rdx, bss_buffer[rip]
mov eax, DWORD PTR -68[rbp]
mov DWORD PTR [rcx+rdx], eax
add DWORD PTR -68[rbp], 1
jmp .L33
.L32:
mov eax, 0
add rsp, 72
pop rbx
pop rbp
ret
.seh_endproc
;;;}}}
;;; FUNC0: compiler-generted function for .bss init, including bss_buffer and class static data
;;;{{{
.def _Z41__static_initialization_and_destruction_0ii; .scl 3; .type 32; .endef
.seh_proc _Z41__static_initialization_and_destruction_0ii
_Z41__static_initialization_and_destruction_0ii:
.LFB36:
push rbp
.seh_pushreg rbp
mov rbp, rsp
.seh_setframe rbp, 0
sub rsp, 32
.seh_stackalloc 32
.seh_endprologue
mov DWORD PTR 16[rbp], ecx
mov DWORD PTR 24[rbp], edx
cmp DWORD PTR 16[rbp], 1
jne .L37
cmp DWORD PTR 24[rbp], 65535
jne .L37
mov ecx, 99
call _ZN6ANIMAL3getEi
mov QWORD PTR _ZN6ANIMAL7self_idE[rip], rax
mov ecx, 90
call _ZN3DOG3getEi
mov QWORD PTR _ZN3DOG7self_idE[rip], rax
mov ecx, 165
call _ZN3CAT3getEi
mov QWORD PTR _ZN3CAT7self_idE[rip], rax
.L37:
nop
add rsp, 32
pop rbp
ret
.seh_endproc
;;;}}}
;;; FUNC1: wrapper function for FUNC0
;;;{{{
.def _GLOBAL__sub_I__ZN6ANIMAL10animal_numE; .scl 3; .type 32; .endef
.seh_proc _GLOBAL__sub_I__ZN6ANIMAL10animal_numE
_GLOBAL__sub_I__ZN6ANIMAL10animal_numE:
.LFB37:
push rbp
.seh_pushreg rbp
mov rbp, rsp
.seh_setframe rbp, 0
sub rsp, 32
.seh_stackalloc 32
.seh_endprologue
mov edx, 65535
mov ecx, 1
call _Z41__static_initialization_and_destruction_0ii
nop
add rsp, 32
pop rbp
ret
.seh_endproc
;;;}}}
;;; section .ctors declares functions exectued BEFORE main, here is FUNC1
;;;{{{
.section .ctors,"w"
.align 8
.quad _GLOBAL__sub_I__ZN6ANIMAL10animal_numE
.ident "GCC: (GNU) 9.1.0"
.def __real__Znwm; .scl 2; .type 32; .endef
.def _Znwm; .scl 2; .type 32; .endef
.def _ZdlPvm; .scl 2; .type 32; .endef
;;;}}}