Mercurial > pub > dyncall > dyncall
view doc/disas_examples/x64.win.disas @ 468:79b95db3d68f
- added (only partly annotated) x64/win64 disas examples
author | Tassilo Philipp |
---|---|
date | Sun, 06 Feb 2022 17:22:59 +0100 |
parents | c0390dc85a07 |
children | 75cb8f79d725 |
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 in first call 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 ; 00000138H mov BYTE PTR x$[rsp], 76 ; 0000004cH lea rax, QWORD PTR x$[rsp+1] mov rdi, rax xor eax, eax mov ecx, 219 ; 000000dbH 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 ; 00000138H pop rdi pop rsi ret 0 nonleaf_call ENDP a$ = 64 $T1 = 80 main PROC push rsi push rdi sub rsp, 104 ; 00000068H 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 ; 00000068H 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 ; vim: ft=asm