C/C++都是非常贴近最终汇编实现的语言,它们可以很容易地和汇编共存。通常一个函数会被编译成一段汇编代码,函数指针就是指向这段代码的地址。函数参数是通过把数据压入堆栈传递给函数的,在C++里,为了提高效率,通常会把this指针置入ECX寄存器来传入函数,因为寄存器的访问速度要优于内存。而函数在运行时,编译器产生的代码通常并不会用POP指令将传入的参数出栈,而是修改EBP的值,指向当前堆栈,然后通过对EBP的间接寻址来访问参数,这样,在多层函数调用中,使得每层函数的参数都得到保护。同样,函数用到的局部变量也会被放入堆栈中,通过EBP来读些。当函数返回时,C语言的默认做法是让调用者去处理传入的参数占据着堆栈的问题,而C++的默认做法是函数本身从堆栈中去掉这些参数。
函数的返回值一般会放入EAX寄存器中,某些情况会用到EDX。如果返回的数据过大,比如是一个类或结构,许多编译器的做法是把返回值需要的数据空间有调用者在堆栈中分配好,把这个临时变量的指针传入函数,函数把结果填入指针指向的内存。
我们自己写汇编代码时如果想调用一个C++语言函数,则在调用前,如果EAX,ECX,EDX内的数据对你的程序上下文有意义,那么请自己提前保存起来(C语言可以不保存ECX),而EBX,EDI,ESI,EBP这些寄存器的数据不会被破坏,ESP,EIP则会按约定的逻辑起变化。
函数的返回值一般会放入EAX寄存器中,某些情况会用到EDX。如果返回的数据过大,比如是一个类或结构,许多编译器的做法是把返回值需要的数据空间有调用者在堆栈中分配好,把这个临时变量的指针传入函数,函数把结果填入指针指向的内存。
我们自己写汇编代码时如果想调用一个C++语言函数,则在调用前,如果EAX,ECX,EDX内的数据对你的程序上下文有意义,那么请自己提前保存起来(C语言可以不保存ECX),而EBX,EDI,ESI,EBP这些寄存器的数据不会被破坏,ESP,EIP则会按约定的逻辑起变化。
同样如果想用汇编写一个可供C++调用的函数,那么请遵守同样的约定。你的函数如果用到EBX,ESI,EDI等寄存器,请在函数入口处保存,并在函数返回前恢复。而EAX,ECX,EDX则可以任意使用(C环境下,ECX例外,需要得到和EBX一样的保护)。