thiscall呼び出し規約:
#include "foo.hpp" foo::foo(int x) { this->x = x; } int foo::bar(int a, int b, int c, int d, int e) { return a + b + c + d + e + this->x; } int foo::baz(int argn, ...) { va_list ap; int r = this->x; va_start(ap, argn); for (int i = 0; i < argn; i++, va_arg(ap, int)) { r += *(int*)ap; } va_end(ap); return r; }
#include <cstdarg> #ifndef FOO_HPP #define FOO_HPP class foo { protected: int x; public: foo(int x); int bar(int a, int b, int c, int d, int e); int baz(int argn, ...); }; #endif /* FOO_HPP */
#include <iostream> #include "foo.hpp" using namespace std; int main(int argc, char *argv[]) { foo *f; f = new foo(10); int r = f->bar(1, 2, 3, 4, 5); cout << "foo::bar() = " << r << endl; r = f->baz(3, 10, 20, 30); cout << "foo::baz() = " << r << endl; return 0; }
コンパイル&リンク&実行
> cl /c /Od /FAs foo.cpp > cl /c /Od /FAs /EHsc main.cpp > cl main.obj foo.obj > main.exe foo::bar() = 25 foo::baz() = 70
(...) PUBLIC ??0foo@@QAE@H@Z ; foo::foo ; Function compile flags: /Odtp ; File c:\in_vitro\c\cc_thiscall\foo.cpp _TEXT SEGMENT _this$ = -4 ; size = 4 _x$ = 8 ; size = 4 ??0foo@@QAE@H@Z PROC ; foo::foo ; _this$ = ecx ; 3 : foo::foo(int x) { this->x = x; } push ebp mov ebp, esp push ecx mov DWORD PTR _this$[ebp], ecx mov eax, DWORD PTR _this$[ebp] mov ecx, DWORD PTR _x$[ebp] mov DWORD PTR [eax], ecx mov eax, DWORD PTR _this$[ebp] mov esp, ebp pop ebp ret 4 ??0foo@@QAE@H@Z ENDP ; foo::foo _TEXT ENDS PUBLIC ?bar@foo@@QAEHHHHHH@Z ; foo::bar ; Function compile flags: /Odtp _TEXT SEGMENT _this$ = -4 ; size = 4 _a$ = 8 ; size = 4 _b$ = 12 ; size = 4 _c$ = 16 ; size = 4 _d$ = 20 ; size = 4 _e$ = 24 ; size = 4 ?bar@foo@@QAEHHHHHH@Z PROC ; foo::bar ; _this$ = ecx ; 5 : int foo::bar(int a, int b, int c, int d, int e) { push ebp mov ebp, esp push ecx mov DWORD PTR _this$[ebp], ecx ; 6 : return a + b + c + d + e + this->x; mov eax, DWORD PTR _a$[ebp] add eax, DWORD PTR _b$[ebp] add eax, DWORD PTR _c$[ebp] add eax, DWORD PTR _d$[ebp] add eax, DWORD PTR _e$[ebp] mov ecx, DWORD PTR _this$[ebp] add eax, DWORD PTR [ecx] ; 7 : } mov esp, ebp pop ebp ret 20 ; 00000014H ?bar@foo@@QAEHHHHHH@Z ENDP ; foo::bar _TEXT ENDS PUBLIC ?baz@foo@@QAAHHZZ ; foo::baz ; Function compile flags: /Odtp _TEXT SEGMENT _i$2881 = -12 ; size = 4 _ap$ = -8 ; size = 4 _r$ = -4 ; size = 4 _this$ = 8 ; size = 4 _argn$ = 12 ; size = 4 ?baz@foo@@QAAHHZZ PROC ; foo::baz ; 8 : int foo::baz(int argn, ...) { push ebp mov ebp, esp sub esp, 12 ; 0000000cH ; 9 : va_list ap; ; 10 : int r = this->x; mov eax, DWORD PTR _this$[ebp] mov ecx, DWORD PTR [eax] mov DWORD PTR _r$[ebp], ecx ; 11 : va_start(ap, argn); lea edx, DWORD PTR _argn$[ebp+4] mov DWORD PTR _ap$[ebp], edx ; 12 : for (int i = 0; i < argn; i++, va_arg(ap, int)) { mov DWORD PTR _i$2881[ebp], 0 jmp SHORT $LN3@baz $LN2@baz: mov eax, DWORD PTR _i$2881[ebp] add eax, 1 mov DWORD PTR _i$2881[ebp], eax mov ecx, DWORD PTR _ap$[ebp] add ecx, 4 mov DWORD PTR _ap$[ebp], ecx $LN3@baz: mov edx, DWORD PTR _i$2881[ebp] cmp edx, DWORD PTR _argn$[ebp] jge SHORT $LN1@baz ; 13 : r += *(int*)ap; mov eax, DWORD PTR _ap$[ebp] mov ecx, DWORD PTR _r$[ebp] add ecx, DWORD PTR [eax] mov DWORD PTR _r$[ebp], ecx ; 14 : } jmp SHORT $LN2@baz $LN1@baz: ; 15 : va_end(ap); mov DWORD PTR _ap$[ebp], 0 ; 16 : return r; mov eax, DWORD PTR _r$[ebp] ; 17 : } mov esp, ebp pop ebp ret 0 ?baz@foo@@QAAHHZZ ENDP ; foo::baz _TEXT ENDS (...)
; 11 : int r = f->bar(1, 2, 3, 4, 5); push 5 push 4 push 3 push 2 push 1 mov ecx, DWORD PTR _f$[ebp] call ?bar@foo@@QAEHHHHHH@Z ; foo::bar mov DWORD PTR _r$[ebp], eax
; 15 : r = f->baz(3, 10, 20, 30); push 30 ; 0000001eH push 20 ; 00000014H push 10 ; 0000000aH push 3 mov eax, DWORD PTR _f$[ebp] push eax call ?baz@foo@@QAAHHZZ ; foo::baz add esp, 20 ; 00000014H mov DWORD PTR _r$[ebp], eax