Arkdasm has proven a very useful toy.
From a procedure coded as follows.
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
msgloop proc
setstack
LOCAL msg :MSG
LOCAL64 _rsi ; allocate QWORD
LOCAL64 _rdi ; allocate QWORD
mov _rsi, rsi ; preserve rsi
mov _rdi, rdi ; preserve rdi
xor rsi, rsi ; zero rsi
lea rdi, msg ; load rdi with structure address
jmp get_msg ; jump into loop
lpstart:
void(TranslateMessage,rdi)
void(DispatchMessage,rdi)
get_msg:
test rax, function(GetMessage,rdi,rsi,rsi,rsi)
jnz lpstart
mov rdi, _rdi ; restore rdi
mov rsi, _rsi ; restore rsi
ret
msgloop endp
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
This is the disassembly of the separate message loop proc I have been testing. It shows how the stack frame is created using ENTER and LEAVE. You will note that the above procedure has a simple MACRO "setstack" that writes a QWORD local at the start of the procedure. It occurs at no additional cost in terms of mnemonics and effectively automates procedures without having to mess around with direct stack adjustments.
; --------------------------------------------------------------------------
; sub_1400011f0
; --------------------------------------------------------------------------
sub_1400011f0 proc
enter 0x70, 0x0
mov qword ptr [0x140003046], rsi
mov qword ptr [0x14000304e], rdi
xor rsi, rsi
lea rdi, [rbp-0x38]
jmp 0x14000121d
0x14000120b:
mov rcx, rdi
call qword ptr [TranslateMessage]
mov rcx, rdi
call qword ptr [DispatchMessageA]
0x14000121d:
mov rcx, rdi
mov rdx, rsi
mov r8, rsi
mov r9, rsi
call qword ptr [GetMessageA]
test rax, rax
jne 0x14000120b
mov rdi, qword ptr [0x14000304e]
mov rsi, qword ptr [0x140003046]
leave
ret
sub_1400011f0 endp
It would appear that ML64 is not as crude or toothless as some of our friends would have us believe. :P