With so little information available, this stuff comes by experiment but surprisingly enough the old form of procedure declaration partially works in that it will accept a sequence of arguments with the data size specified as it was done in Win32. The difference is the first 4 arguments are left blank, args 5 onwards are stored on the stack and occur in the right location in RBP. If you copy the 4 registers rcx, rdx, r8 and r9 into the first 4 arguments everything works correctly. Below is a WndProc example that works fine.
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
WndProc proc hWin:QWORD,uMsg:QWORD,wParam:QWORD,lParam:QWORD
mov QWORD PTR [rbp+10h], rcx
mov QWORD PTR [rbp+18h], rdx
mov QWORD PTR [rbp+20h], r8
mov QWORD PTR [rbp+28h], r9
.switch uMsg
.case WM_COMMAND
.switch wParam
.case 1000
void(SendMessage,hWin,WM_SYSCOMMAND,SC_CLOSE,NULL)
.case 10000
fn MessageBox, \
hWin, \
"Example with icon, menu and manifest.", \
"About ML64 Example", \
MB_OK
.endsw
.case WM_CLOSE
fn MessageBox, \
hWin, \
"Sending the WM_DESTROY message.", \
"WM_CLOSE here", \
MB_OK
void(SendMessage,hWin,WM_DESTROY,0,0)
.case WM_DESTROY
void(PostQuitMessage,NULL)
.endsw
void(DefWindowProc,hWin,uMsg,wParam,lParam)
ret
WndProc endp
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
It's hard stuff. What helped me a lot was to ask GCC for help, see below 8)
#include <stdio.h>
#include <windows.h>
int main() {
float f=111.111;
double d=222.222;
char* wfjj="This is a test string for output";
// OPT_Susy Console ; put an x for seeing output to the right, no x for use with _getch()
printf("args:\n%i\t%f\t%f\t%i\t%f\n", 0x111, f, d, 0x444, 555.555); // GCC
return MessageBox(0, "printf succeeded?", "Hi Jochen:", MB_YESNO | MB_ICONINFORMATION);
}
#if 0
40152F | 90 | nop
401530 | 48 83 EC 38 | sub rsp, 38
401534 | E8 E7 0B 00 00 | call tmp.40 | ?? sets a global dword flag
401539 | F2 0F 10 0D 07 2B 00 00 | movsd xmm1, qword ptr ds:[404038] | d 222
401541 | F2 0F 10 05 07 2B 00 00 | movsd xmm0, qword ptr ds:[404040] | f 111
401549 | C7 44 24 20 44 04 00 00 | mov dword ptr ss:[rsp+20], 444 | 5th arg
xxxxxx | F2 0F 10 25 F7 2A 00 00 | movsd xmm4, qword ptr ds:[404048] | 555.555
xxxxxx | F2 0F 11 64 24 28 | movsd qword ptr ss:[rsp+28], xmm4 | 6th arg
401551 | 66 0F 28 D9 | movapd xmm3, xmm1
401555 | 66 49 0F 7E C9 | movq r9, xmm1
40155A | 66 0F 28 D0 | movapd xmm2, xmm0
40155E | 66 49 0F 7E C0 | movq r8, xmm0
401563 | BA 11 01 00 00 | mov edx, 111
401568 | 48 8D 0D 91 2A 00 00 | lea rcx, qword ptr ds:[404000] | 404000:"args:\n%i\t%f\t%f\t%i\n"
40156F | E8 C4 15 00 00 | call <tmp.printf>
401574 | 41 B9 44 00 00 00 | mov r9d, 44
40157A | 4C 8D 05 AA 2A 00 00 | lea r8, qword ptr ds:[40402B]
401581 | 48 8D 15 AE 2A 00 00 | lea rdx, qword ptr ds:[404036]
401588 | B9 00 00 00 00 | mov ecx, 0
40158D | FF 15 2D 6E 00 00 | call qword ptr ds:[<&MessageBoxA>]
401593 | 48 83 C4 38 | add rsp, 38
401597 | C3 | ret
402120 | 8B 05 1A 52 00 00 | mov eax, dword ptr ds:[407340] |
402126 | 85 C0 | test eax, eax |
402128 | 74 06 | je tmp.402130 |
40212A | F3 C3 | ret |
#endif
How does this go?
mov hWin, rcx ;instead of mov QWORD PTR [rbp+10h], rcx
Might as well use the name.
Its so you can use the same 4 lines of code in any multi-argument procedure. Names change where the address does not.