Mercurial > pub > dyncall > dyncall
view doc/disas_examples/x64.win.disas @ 619:c754150fe87f
- x64 win disas example fix and addition
author | Tassilo Philipp |
---|---|
date | Mon, 03 Oct 2022 13:49:19 +0200 |
parents | fc614cb865c6 |
children |
line wrap: on
line source
; void leaf_call(int b, int c, int d, int e, int f, int g, int h) ; { ; } ; ; void nonleaf_call(int a, int b, int c, int d, int e, int f, int g, int h) ; { ; /* use some local data */ ; char x[10] = { 'L' }; ; leaf_call(b, c, d, e, f, g, h); ; } ; ; int main() ; { ; nonleaf_call(0, 1, 2, 3, 4, 5, 6, 7); ; return 0; ; } ; output from godbolt compiler explorer w/ msvc 19.0 leaf_call PROC mov DWORD PTR [rsp+32], r9d mov DWORD PTR [rsp+24], r8d mov DWORD PTR [rsp+16], edx mov DWORD PTR [rsp+8], ecx ret 0 leaf_call ENDP x$ = 64 b$ = 104 c$ = 112 d$ = 120 e$ = 128 f$ = 136 g$ = 144 h$ = 152 nonleaf_call PROC mov DWORD PTR [rsp+32], r9d ; | | mov DWORD PTR [rsp+24], r8d ; | | mov DWORD PTR [rsp+16], edx ; | | spill mov DWORD PTR [rsp+8], ecx ; | | push rdi ; | sub rsp, 80 ; | prolog mov BYTE PTR x$[rsp], 76 ; 'L' -> local area (of local array's space) lea rax, QWORD PTR x$[rsp+1] ; | mov rdi, rax ; | xor eax, eax ; | zero-init rest of local array's space mov ecx, 9 ; | rep stosb ; | mov eax, DWORD PTR h$[rsp] ; arg 6 (fetched from caller's frame param area), and ... mov DWORD PTR [rsp+48], eax ; ... "pushed" onto stack mov eax, DWORD PTR g$[rsp] ; arg 5 (fetched from caller's frame param area), and ... mov DWORD PTR [rsp+40], eax ; ... "pushed" onto stack mov eax, DWORD PTR f$[rsp] ; arg 4 (fetched from caller's frame param area), and ... mov DWORD PTR [rsp+32], eax ; ... "pushed" onto stack mov r9d, DWORD PTR e$[rsp] ; arg 3 mov r8d, DWORD PTR d$[rsp] ; arg 2 mov edx, DWORD PTR c$[rsp] ; arg 1 mov ecx, DWORD PTR b$[rsp] ; arg 0 call leaf_call ; push return addr and call add rsp, 80 ; | pop rdi ; | epilog ret 0 ; | nonleaf_call ENDP main PROC sub rsp, 72 ; prolog mov DWORD PTR [rsp+56], 7 ; "push" arg 7 onto stack mov DWORD PTR [rsp+48], 6 ; "push" arg 6 onto stack mov DWORD PTR [rsp+40], 5 ; "push" arg 5 onto stack mov DWORD PTR [rsp+32], 4 ; "push" arg 4 onto stack mov r9d, 3 ; arg 3 mov r8d, 2 ; arg 2 mov edx, 1 ; arg 1 xor ecx, ecx ; arg 0 call nonleaf_call ; push return addr and call xor eax, eax ; return value add rsp, 72 ; | ret 0 ; | epilog main ENDP ; ---------- structs by value, struct never in reg or on reg arg boundary ----------> ; ; struct A { int i, j; long long l; }; ; ; void leaf_call(int b, int c, int d, int e, struct A f, int g, int h) ; { ; } ; ; void nonleaf_call(int a, int b, int c, int d, int e, struct A f, int g, int h) ; { ; /* use some local data */ ; char x[220] = { 'L' }; ; leaf_call(b, c, d, e, f, g, h); ; } ; ; int main() ; { ; struct A a = {5, 6, 7ll}; ; nonleaf_call(0, 1, 2, 3, 4, a, 8, 9); ; return 0; ; } ; output from godbolt compiler explorer w/ msvc 19.0 leaf_call PROC mov DWORD PTR [rsp+32], r9d mov DWORD PTR [rsp+24], r8d mov DWORD PTR [rsp+16], edx mov DWORD PTR [rsp+8], ecx ret 0 leaf_call ENDP $T1 = 64 x$ = 80 b$ = 344 c$ = 352 d$ = 360 e$ = 368 f$ = 376 g$ = 384 h$ = 392 nonleaf_call PROC mov DWORD PTR [rsp+32], r9d mov DWORD PTR [rsp+24], r8d mov DWORD PTR [rsp+16], edx mov DWORD PTR [rsp+8], ecx push rsi push rdi sub rsp, 312 mov BYTE PTR x$[rsp], 76 lea rax, QWORD PTR x$[rsp+1] mov rdi, rax xor eax, eax mov ecx, 219 rep stosb lea rax, QWORD PTR $T1[rsp] mov rdi, rax mov rsi, QWORD PTR f$[rsp] mov ecx, 16 rep movsb mov eax, DWORD PTR h$[rsp] mov DWORD PTR [rsp+48], eax mov eax, DWORD PTR g$[rsp] mov DWORD PTR [rsp+40], eax lea rax, QWORD PTR $T1[rsp] mov QWORD PTR [rsp+32], rax mov r9d, DWORD PTR e$[rsp] mov r8d, DWORD PTR d$[rsp] mov edx, DWORD PTR c$[rsp] mov ecx, DWORD PTR b$[rsp] call leaf_call add rsp, 312 pop rdi pop rsi ret 0 nonleaf_call ENDP a$ = 64 $T1 = 80 main PROC push rsi push rdi sub rsp, 104 mov DWORD PTR a$[rsp], 5 mov DWORD PTR a$[rsp+4], 6 mov QWORD PTR a$[rsp+8], 7 lea rax, QWORD PTR $T1[rsp] lea rcx, QWORD PTR a$[rsp] mov rdi, rax mov rsi, rcx mov ecx, 16 rep movsb mov DWORD PTR [rsp+56], 9 mov DWORD PTR [rsp+48], 8 lea rax, QWORD PTR $T1[rsp] mov QWORD PTR [rsp+40], rax mov DWORD PTR [rsp+32], 4 mov r9d, 3 mov r8d, 2 mov edx, 1 xor ecx, ecx call nonleaf_call xor eax, eax add rsp, 104 pop rdi pop rsi ret 0 main ENDP ; ---------- structs by value, complex example (multiple structs, partly passed via regs) ----------> ; ; struct A { int i, j; float f; }; ; struct B { double d; long long l; }; ; ; void leaf_call(int b, struct A c, struct B d, int e, int f, struct A g, struct B h, int i, int j) ; { ; } ; ; void nonleaf_call(int a, int b, struct A c, struct B d, int e, int f, struct A g, struct B h, int i, int j) ; { ; /* use some local data */ ; char x[220] = { 'L' }; ; leaf_call(b, c, d, e, f, g, h, i, j); ; } ; ; int main() ; { ; struct A a = {2, 3, 4.f}; ; struct B b = {5., 6ll}; ; struct A c = {9, 10, 11.f}; ; struct B d = {12., 13ll}; ; nonleaf_call(0, 1, a, b, 7, 8, c, d, 14, 15); ; return 0; ; } ; output from godbolt compiler explorer w/ msvc 19.0 __real@41300000 DD 041300000r ; | __real@40800000 DD 040800000r ; | __real@4028000000000000 DQ 04028000000000000r ; | fp data __real@4014000000000000 DQ 04014000000000000r ; | leaf_call PROC mov DWORD PTR [rsp+32], r9d mov QWORD PTR [rsp+24], r8 mov QWORD PTR [rsp+16], rdx mov DWORD PTR [rsp+8], ecx ret 0 leaf_call ENDP $T1 = 80 $T2 = 96 $T3 = 112 $T4 = 128 x$ = 144 b$ = 408 c$ = 416 d$ = 424 e$ = 432 f$ = 440 g$ = 448 h$ = 456 i$ = 464 j$ = 472 nonleaf_call PROC mov QWORD PTR [rsp+32], r9 mov QWORD PTR [rsp+24], r8 mov DWORD PTR [rsp+16], edx mov DWORD PTR [rsp+8], ecx push rsi push rdi sub rsp, 376 mov BYTE PTR x$[rsp], 76 lea rax, QWORD PTR x$[rsp+1] mov rdi, rax xor eax, eax mov ecx, 219 rep stosb lea rax, QWORD PTR $T3[rsp] mov rdi, rax mov rsi, QWORD PTR h$[rsp] mov ecx, 16 rep movsb lea rax, QWORD PTR $T1[rsp] mov rdi, rax mov rsi, QWORD PTR g$[rsp] mov ecx, 12 rep movsb lea rax, QWORD PTR $T4[rsp] mov rdi, rax mov rsi, QWORD PTR d$[rsp] mov ecx, 16 rep movsb lea rax, QWORD PTR $T2[rsp] mov rdi, rax mov rsi, QWORD PTR c$[rsp] mov ecx, 12 rep movsb mov eax, DWORD PTR j$[rsp] mov DWORD PTR [rsp+64], eax mov eax, DWORD PTR i$[rsp] mov DWORD PTR [rsp+56], eax lea rax, QWORD PTR $T3[rsp] mov QWORD PTR [rsp+48], rax lea rax, QWORD PTR $T1[rsp] mov QWORD PTR [rsp+40], rax mov eax, DWORD PTR f$[rsp] mov DWORD PTR [rsp+32], eax mov r9d, DWORD PTR e$[rsp] lea r8, QWORD PTR $T4[rsp] lea rdx, QWORD PTR $T2[rsp] mov ecx, DWORD PTR b$[rsp] call leaf_call add rsp, 376 pop rdi pop rsi ret 0 nonleaf_call ENDP c$ = 80 a$ = 96 $T1 = 112 $T2 = 128 d$ = 144 b$ = 160 $T3 = 176 $T4 = 192 main PROC push rsi push rdi sub rsp, 216 mov DWORD PTR a$[rsp], 2 mov DWORD PTR a$[rsp+4], 3 movss xmm0, DWORD PTR __real@40800000 movss DWORD PTR a$[rsp+8], xmm0 movsd xmm0, QWORD PTR __real@4014000000000000 movsd QWORD PTR b$[rsp], xmm0 mov QWORD PTR b$[rsp+8], 6 mov DWORD PTR c$[rsp], 9 mov DWORD PTR c$[rsp+4], 10 movss xmm0, DWORD PTR __real@41300000 movss DWORD PTR c$[rsp+8], xmm0 movsd xmm0, QWORD PTR __real@4028000000000000 movsd QWORD PTR d$[rsp], xmm0 mov QWORD PTR d$[rsp+8], 13 lea rax, QWORD PTR $T3[rsp] lea rcx, QWORD PTR d$[rsp] mov rdi, rax mov rsi, rcx mov ecx, 16 rep movsb lea rax, QWORD PTR $T1[rsp] lea rcx, QWORD PTR c$[rsp] mov rdi, rax mov rsi, rcx mov ecx, 12 rep movsb lea rax, QWORD PTR $T4[rsp] lea rcx, QWORD PTR b$[rsp] mov rdi, rax mov rsi, rcx mov ecx, 16 rep movsb lea rax, QWORD PTR $T2[rsp] lea rcx, QWORD PTR a$[rsp] mov rdi, rax mov rsi, rcx mov ecx, 12 rep movsb mov DWORD PTR [rsp+72], 15 mov DWORD PTR [rsp+64], 14 lea rax, QWORD PTR $T3[rsp] mov QWORD PTR [rsp+56], rax lea rax, QWORD PTR $T1[rsp] mov QWORD PTR [rsp+48], rax mov DWORD PTR [rsp+40], 8 mov DWORD PTR [rsp+32], 7 lea r9, QWORD PTR $T4[rsp] lea r8, QWORD PTR $T2[rsp] mov edx, 1 xor ecx, ecx call nonleaf_call xor eax, eax add rsp, 216 pop rdi pop rsi ret 0 main ENDP ; ---------- returning tiny struct by value (passes via regs) ----------> ; ; struct A { unsigned char a; }; ; ; struct A call(unsigned char c) ; { ; struct A r = {c}; ; return r; ; } ; ; int main() ; { ; struct A a = call(123); ; return 0; ; } ; output from godbolt compiler explorer w/ msvc 19.0 r$ = 0 c$ = 32 call PROC mov BYTE PTR [rsp+8], cl ; | spill sub rsp, 24 ; | prolog movzx eax, BYTE PTR c$[rsp] ; in arg 0 (fetched from spill area) -> eax, then ... mov BYTE PTR r$[rsp], al ; ... -> struct in local area (top of stack, as leaf call and thus no reserved spill area) movzx eax, BYTE PTR r$[rsp] ; reget same value into eax to return (small) struct via reg (a bit pointless to refetch) add rsp, 24 ; | ret 0 ; | epilog call ENDP a$ = 32 main PROC sub rsp, 56 ; prolog mov cl, 123 ; arg 0 call call ; push return addr and call mov BYTE PTR a$[rsp], al ; write struct data to local area (123) xor eax, eax ; return value add rsp, 56 ; | ret 0 ; | epilog main ENDP ; ---------- 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.0 ; ... snip, removed code of ctor and copy ctor ... f1 PROC mov DWORD PTR [rsp+8], ecx ret 0 f1 ENDP f2 PROC mov QWORD PTR [rsp+8], rcx ret 0 f2 ENDP a$ = 32 n$ = 36 t$ = 40 $T1 = 44 $T2 = 48 f PROC $LN3: sub rsp, 72 ; prolog lea rcx, QWORD PTR n$[rsp] ; \ this ptr (NULL) call NonTrivial::NonTrivial(void) ; | NonTrivial::NonTrivial() / ctor mov DWORD PTR a$[rsp], 1 ; a = 1 mov eax, DWORD PTR a$[rsp] ; | add eax, 123 ; | a += 123 mov DWORD PTR a$[rsp], eax ; / mov ecx, DWORD PTR t$[rsp] ; f1 arg 0 (struct Trivial), via reg as small struct call f1 ; call f1(struct Trivial) mov eax, DWORD PTR a$[rsp] ; | sub eax, 123 ; | a -= 123 mov DWORD PTR a$[rsp], eax ; / lea rax, QWORD PTR $T1[rsp] ; @@@ unsure mov QWORD PTR $T2[rsp], rax ; ... @@@ lea rdx, QWORD PTR n$[rsp] ; \ ptr to dest of copy of n mov rcx, QWORD PTR $T2[rsp] ; | copy n ptr to n call NonTrivial::NonTrivial(NonTrivial const &) ; / NonTrivial::NonTrivial(const NonTrivial&) / copy ctor mov rcx, rax ; f2 arg 0 (ptr to copy of struct NonTrivial), via ptr as non-trivial call f2 ; call f2(struct NonTrivial) mov eax, DWORD PTR a$[rsp] ; | sub eax, 12 ; | a -= 12 mov DWORD PTR a$[rsp], eax ; / add rsp, 72 ; \ ret 0 ; | epilog f 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.0 ; ... snip, removed code of ctor and copy ctor ... $T1 = 0 f1 PROC $LN3: push rdi sub rsp, 16 lea rax, QWORD PTR $T1[rsp] mov rdi, rax xor eax, eax mov ecx, 4 rep stosb mov eax, DWORD PTR $T1[rsp] add rsp, 16 pop rdi ret 0 f1 ENDP __$ReturnUdt$ = 48 NonTrivial f2(void) PROC $LN3: mov QWORD PTR [rsp+8], rcx sub rsp, 40 mov rcx, QWORD PTR __$ReturnUdt$[rsp] call NonTrivial::NonTrivial(void) mov rax, QWORD PTR __$ReturnUdt$[rsp] add rsp, 40 ret 0 NonTrivial f2(void) ENDP a$ = 32 $T1 = 36 t$ = 40 n$ = 44 f PROC $LN3: sub rsp, 56 ; prolog mov DWORD PTR a$[rsp], 1 ; a = 1 mov eax, DWORD PTR a$[rsp] ; | add eax, 123 ; | a += 123 mov DWORD PTR a$[rsp], eax ; | call f1 ; call f1() mov DWORD PTR $T1[rsp], eax ; mov eax, DWORD PTR $T1[rsp] ; mov DWORD PTR t$[rsp], eax ; mov eax, DWORD PTR a$[rsp] ; | sub eax, 123 ; | a -= 123 mov DWORD PTR a$[rsp], eax ; | lea rcx, QWORD PTR n$[rsp] ; ptr to space to hold non-triv retval call NonTrivial f2(void) ; call f2() mov eax, DWORD PTR a$[rsp] ; | sub eax, 12 ; | a -= 12 mov DWORD PTR a$[rsp], eax ; / add rsp, 56 ; \ epilog ret 0 ; | f ENDP ; ---------- structs by value, struct passed as vararg ----------> ; ; #include <stdlib.h> ; #include <stdarg.h> ; ; struct A { int i, j; long long l; }; ; ; void leaf_call(int b, int c, int d, int e, ...) ; { ; } ; ; void nonleaf_call(int a, int b, int c, ...) ; { ; int d, e, g, h; ; struct A f; ; va_list ap; ; va_start(ap, c); ; d = va_arg(ap, int); ; e = va_arg(ap, int); ; f = va_arg(ap, struct A); ; g = va_arg(ap, int); ; h = va_arg(ap, int); ; /* use some local data */ ; *(char*)alloca(220) = 'L'; ; leaf_call(b, c, d, e, f, g, h); ; va_end(ap); ; } ; ; int main() ; { ; nonleaf_call(0, 1, 2, 3, 4, (struct A){5, 6, 7ll}, 8, 9); ; return 0; ; } ; output from godbolt compiler explorer w/ msvc 19.0 leaf_call PROC mov DWORD PTR [rsp+32], r9d ; mov DWORD PTR [rsp+24], r8d ; mov DWORD PTR [rsp+16], edx ; mov DWORD PTR [rsp+8], ecx ; ret 0 ; leaf_call ENDP ap$ = 64 h$ = 72 g$ = 76 e$ = 80 d$ = 84 $T1 = 96 f$ = 112 __$ArrayPad$ = 128 b$ = 184 c$ = 192 nonleaf_call PROC $LN3: mov DWORD PTR [rsp+24], r8d ; mov DWORD PTR [rsp+16], edx ; mov DWORD PTR [rsp+8], ecx ; mov QWORD PTR [rsp+32], r9 ; push rsi ; push rdi ; sub rsp, 152 ; mov rax, QWORD PTR __security_cookie ; xor rax, rsp ; mov QWORD PTR __$ArrayPad$[rsp], rax ; lea rax, QWORD PTR c$[rsp+8] ; mov QWORD PTR ap$[rsp], rax ; mov rax, QWORD PTR ap$[rsp] ; add rax, 8 ; mov QWORD PTR ap$[rsp], rax ; mov rax, QWORD PTR ap$[rsp] ; mov eax, DWORD PTR [rax-8] ; mov DWORD PTR d$[rsp], eax ; mov rax, QWORD PTR ap$[rsp] ; add rax, 8 ; mov QWORD PTR ap$[rsp], rax ; mov rax, QWORD PTR ap$[rsp] ; mov eax, DWORD PTR [rax-8] ; mov DWORD PTR e$[rsp], eax ; mov rax, QWORD PTR ap$[rsp] ; add rax, 8 ; mov QWORD PTR ap$[rsp], rax ; mov rax, QWORD PTR ap$[rsp] ; mov rax, QWORD PTR [rax-8] ; lea rcx, QWORD PTR f$[rsp] ; mov rdi, rcx ; mov rsi, rax ; mov ecx, 16 ; rep movsb ; mov rax, QWORD PTR ap$[rsp] ; add rax, 8 ; mov QWORD PTR ap$[rsp], rax ; mov rax, QWORD PTR ap$[rsp] ; mov eax, DWORD PTR [rax-8] ; mov DWORD PTR g$[rsp], eax ; mov rax, QWORD PTR ap$[rsp] ; add rax, 8 ; mov QWORD PTR ap$[rsp], rax ; mov rax, QWORD PTR ap$[rsp] ; mov eax, DWORD PTR [rax-8] ; mov DWORD PTR h$[rsp], eax ; mov ecx, 220 ; call alloca ; cdqe ; mov BYTE PTR [rax], 76 ; lea rax, QWORD PTR $T1[rsp] ; lea rcx, QWORD PTR f$[rsp] ; mov rdi, rax ; mov rsi, rcx ; mov ecx, 16 ; rep movsb ; mov eax, DWORD PTR h$[rsp] ; mov DWORD PTR [rsp+48], eax ; mov eax, DWORD PTR g$[rsp] ; mov DWORD PTR [rsp+40], eax ; lea rax, QWORD PTR $T1[rsp] ; mov QWORD PTR [rsp+32], rax ; mov r9d, DWORD PTR e$[rsp] ; mov r8d, DWORD PTR d$[rsp] ; mov edx, DWORD PTR c$[rsp] ; mov ecx, DWORD PTR b$[rsp] ; call leaf_call ; mov QWORD PTR ap$[rsp], 0 ; mov rcx, QWORD PTR __$ArrayPad$[rsp] ; xor rcx, rsp ; call __security_check_cookie ; add rsp, 152 ; pop rdi ; pop rsi ; ret 0 ; nonleaf_call ENDP $T1 = 64 $S1$ = 80 __$ArrayPad$ = 96 main PROC $LN3: push rsi ; push rdi ; sub rsp, 120 ; mov rax, QWORD PTR __security_cookie ; xor rax, rsp ; mov QWORD PTR __$ArrayPad$[rsp], rax ; mov DWORD PTR $S1$[rsp], 5 ; mov DWORD PTR $S1$[rsp+4], 6 ; mov QWORD PTR $S1$[rsp+8], 7 ; lea rax, QWORD PTR $T1[rsp] ; lea rcx, QWORD PTR $S1$[rsp] ; mov rdi, rax ; mov rsi, rcx ; mov ecx, 16 ; rep movsb ; mov DWORD PTR [rsp+56], 9 ; mov DWORD PTR [rsp+48], 8 ; lea rax, QWORD PTR $T1[rsp] ; mov QWORD PTR [rsp+40], rax ; mov DWORD PTR [rsp+32], 4 ; mov r9d, 3 ; mov r8d, 2 ; mov edx, 1 ; xor ecx, ecx ; call nonleaf_call ; xor eax, eax ; mov rcx, QWORD PTR __$ArrayPad$[rsp] ; xor rcx, rsp ; call __security_check_cookie ; add rsp, 120 ; pop rdi ; pop rsi ; ret 0 ; main ENDP ; vim: ft=asm