diff doc/disas_examples/x86.fastcall_ms.disas @ 530:585dcb68f55d

- more doc and disas examples for x86 fastcall and non-trivial aggregates
author Tassilo Philipp
date Sat, 16 Apr 2022 12:10:02 +0200
parents 79e76734bb5c
children
line wrap: on
line diff
--- a/doc/disas_examples/x86.fastcall_ms.disas	Thu Apr 14 21:18:02 2022 +0200
+++ b/doc/disas_examples/x86.fastcall_ms.disas	Sat Apr 16 12:10:02 2022 +0200
@@ -184,5 +184,221 @@
 
 
 
+; ---------- C++ trivial and non-trivial aggrs passed to C funcs ---------->
+;
+; struct Trivial { int a; };
+; struct NonTrivial {
+;         int a;
+;         NonTrivial() : a(0) {}
+;         NonTrivial(const NonTrivial& rhs) : a(rhs.a) { }
+; };
+;
+; extern "C" {
+; 
+;     void f1(struct Trivial s)    { }
+;     void f2(struct NonTrivial s) { }
+; 
+;     void f()
+;     {
+;         struct Trivial t;
+;         struct NonTrivial n;
+;         int a=1;
+;         a += 123;
+;         f1(t);
+;         a -= 123;
+;         f2(n);
+;         a -= 12;
+;     }
+; }
+
+
+
+; output from godbolt compiler explorer w/ msvc 19.31 (/Gr for fastcall)
+
+_this$ = -4
+NonTrivial::NonTrivial(void) PROC
+        push    ebp
+        mov     ebp, esp
+        push    ecx
+        mov     DWORD PTR _this$[ebp], ecx
+        mov     eax, DWORD PTR _this$[ebp]
+        mov     DWORD PTR [eax], 0
+        mov     eax, DWORD PTR _this$[ebp]
+        mov     esp, ebp
+        pop     ebp
+        ret     0
+NonTrivial::NonTrivial(void) ENDP
+
+_this$ = -4
+_rhs$ = 8
+NonTrivial::NonTrivial(NonTrivial const &) PROC
+        push    ebp
+        mov     ebp, esp
+        push    ecx
+        mov     DWORD PTR _this$[ebp], ecx
+        mov     eax, DWORD PTR _this$[ebp]
+        mov     ecx, DWORD PTR _rhs$[ebp]
+        mov     edx, DWORD PTR [ecx]
+        mov     DWORD PTR [eax], edx
+        mov     eax, DWORD PTR _this$[ebp]
+        mov     esp, ebp
+        pop     ebp
+        ret     4
+NonTrivial::NonTrivial(NonTrivial const &) ENDP
+
+_s$ = 8
+@f1@4   PROC
+        push    ebp
+        mov     ebp, esp
+        pop     ebp
+        ret     4
+@f1@4   ENDP
+
+_s$ = 8
+@f2@4   PROC
+        push    ebp
+        mov     ebp, esp
+        pop     ebp
+        ret     4
+@f2@4   ENDP
+
+_t$ = -12
+_n$ = -8
+_a$ = -4
+@f@0    PROC
+        push    ebp                                        ;
+        mov     ebp, esp                                   ;
+        sub     esp, 12                                    ;
+        lea     ecx, DWORD PTR _n$[ebp]                    ;
+        call    NonTrivial::NonTrivial(void)               ;
+        mov     DWORD PTR _a$[ebp], 1                      ;
+        mov     eax, DWORD PTR _a$[ebp]                    ;
+        add     eax, 123                                   ;
+        mov     DWORD PTR _a$[ebp], eax                    ;
+        mov     ecx, DWORD PTR _t$[ebp]                    ;
+        push    ecx                                        ;
+        call    @f1@4                                      ;
+        mov     edx, DWORD PTR _a$[ebp]                    ;
+        sub     edx, 123                                   ;
+        mov     DWORD PTR _a$[ebp], edx                    ;
+        push    ecx                                        ;
+        mov     ecx, esp                                   ;
+        lea     eax, DWORD PTR _n$[ebp]                    ;
+        push    eax                                        ;
+        call    NonTrivial::NonTrivial(NonTrivial const &) ;
+        call    @f2@4                                      ;
+        mov     ecx, DWORD PTR _a$[ebp]                    ;
+        sub     ecx, 12                                    ;
+        mov     DWORD PTR _a$[ebp], ecx                    ;
+        mov     esp, ebp                                   ;
+        pop     ebp                                        ;
+        ret     0                                          ;
+@f@0    ENDP
+
+
+
+; ---------- C++ trivial and non-trivial aggrs as return values ---------->
+;
+; struct Trivial { int a; };
+; struct NonTrivial {
+;         int a;
+;         NonTrivial() : a(0) {}
+;         NonTrivial(const NonTrivial& rhs) : a(rhs.a) { }
+; };
+; 
+; extern "C" {
+;     struct Trivial    f1() { return Trivial(); }
+; }
+; 
+;     struct NonTrivial f2() { return NonTrivial(); }
+; 
+; extern "C" {
+;     void f()
+;     {
+;         int a=1;
+;         a += 123;
+;         struct Trivial t = f1();
+;         a -= 123;
+;         struct NonTrivial n = f2();
+;         a -= 12;
+;     }
+; }
+
+
+
+; output from godbolt compiler explorer w/ msvc 19.31 (/Gr for fastcall)
+
+_this$ = -4
+NonTrivial::NonTrivial(void) PROC
+        push    ebp
+        mov     ebp, esp
+        push    ecx
+        mov     DWORD PTR _this$[ebp], ecx
+        mov     eax, DWORD PTR _this$[ebp]
+        mov     DWORD PTR [eax], 0
+        mov     eax, DWORD PTR _this$[ebp]
+        mov     esp, ebp
+        pop     ebp
+        ret     0
+NonTrivial::NonTrivial(void) ENDP
+
+$T1 = -4
+@f1@0   PROC
+        push    ebp
+        mov     ebp, esp
+        push    ecx
+        xor     eax, eax
+        mov     DWORD PTR $T1[ebp], eax
+        mov     eax, DWORD PTR $T1[ebp]
+        mov     esp, ebp
+        pop     ebp
+        ret     0
+@f1@0   ENDP
+
+___$ReturnUdt$ = -4
+NonTrivial f2(void) PROC
+        push    ebp                                ;
+        mov     ebp, esp                           ;
+        push    ecx                                ; ptr to hidden retval space as first arg (fastcall, in ecx)
+        mov     DWORD PTR ___$ReturnUdt$[ebp], ecx ; |
+        mov     ecx, DWORD PTR ___$ReturnUdt$[ebp] ; | a bit pointless
+        call    NonTrivial::NonTrivial(void)       ;
+        mov     eax, DWORD PTR ___$ReturnUdt$[ebp] ; return passed-in ptr ptr to hidden retval space in eax
+        mov     esp, ebp                           ;
+        pop     ebp                                ;
+        ret     0                                  ;
+NonTrivial f2(void) ENDP
+
+_n$ = -16
+_t$ = -12
+$T1 = -8
+_a$ = -4
+@f@0    PROC
+        push    ebp                     ;
+        mov     ebp, esp                ;
+        sub     esp, 16                 ;
+        mov     DWORD PTR _a$[ebp], 1   ; a = 1
+        mov     eax, DWORD PTR _a$[ebp] ; |
+        add     eax, 123                ; | a += 123
+        mov     DWORD PTR _a$[ebp], eax ; |
+        call    @f1@0                   ; call f1()
+        mov     DWORD PTR $T1[ebp], eax ; retval (trivial struct <= 32bits, returned via eax)
+        mov     ecx, DWORD PTR $T1[ebp] ; | copy of retval from stack to stack
+        mov     DWORD PTR _t$[ebp], ecx ; /
+        mov     edx, DWORD PTR _a$[ebp] ; \
+        sub     edx, 123                ; | a -= 123
+        mov     DWORD PTR _a$[ebp], edx ; |
+        lea     ecx, DWORD PTR _n$[ebp] ; hidden first arg: ptr to space for (non-trivial) retval
+        call    NonTrivial f2(void)     ; call f2()
+        mov     eax, DWORD PTR _a$[ebp] ; |
+        sub     eax, 12                 ; | a -= 12
+        mov     DWORD PTR _a$[ebp], eax ; |
+        mov     esp, ebp                ;
+        pop     ebp                     ;
+        ret     0                       ;
+@f@0    ENDP
+
+
+
 ; vim: ft=asm