Hello,
Here is a macro to save rcx,rdx,r8 and r9 to protect them across API function calls.
include SaveRegs.inc
SaveRegs MACRO
LOCAL_rcx TEXTEQU <LOCAL _rcx:QWORD>
LOCAL_rdx TEXTEQU <LOCAL _rdx:QWORD>
LOCAL_r8 TEXTEQU <LOCAL _r8:QWORD>
LOCAL_r9 TEXTEQU <LOCAL _r9:QWORD>
LOCAL_rcx
LOCAL_rdx
LOCAL_r8
LOCAL_r9
mov _rcx,rcx
mov _rdx,rdx
mov _r8,r8
mov _r9,r9
ENDM
.data
msg db 'Hello!',0
msg2 db 'rcx,rdx,r8 and r9 are saved.',0
title db 'MsgBox',0
title2 db 'Macro test',0
.code
start:
sub rsp,8+4*8
invoke main,ADDR msg2,ADDR title2
invoke ExitProcess,0
main PROC x:QWORD,y:QWORD PARMAREA=4*SIZEOF QWORD
SaveRegs
invoke MessageBox,0,ADDR msg,ADDR title,0
; The first call to MessageBox destroys rcx,rdx,r8 and r9
invoke MessageBox,0,_rcx,_rdx,0
invoke ExitProcess,0
main ENDP
END start
Cool stuff, thanks Vortex! Works here with latest Poasm :)
Hi Quin,
Thanks for your test. This modified version where the non-volatile registers are preserved works as expected :
main PROC uses rsi rdi rbx x:QWORD,y:QWORD PARMAREA=4*SIZEOF QWORD
SaveRegs
xor rsi,rsi
mov rdi,1
mov rbx,2
invoke MessageBox,0,ADDR msg,ADDR title,0
; The first call to MessageBox destroys rcx,rdx,r8 and r9
invoke MessageBox,0,_rcx,_rdx,0
ret
main ENDP
Here is another attempt :
include SaveRegs.inc
SaveRegs MACRO
mov QWORD PTR [rbx],rcx
mov QWORD PTR [rbx+8],rdx
mov QWORD PTR [rbx+16],r8
mov QWORD PTR [rbx+24],r9
ENDM
.data
msg db 'Hello!',0
msg2 db 'rcx,rdx,r8 and r9 are saved.',0
title db 'MsgBox',0
title2 db 'Macro test',0
.data?
mainRsp dq ?
.code
start:
sub rsp,8+4*8
push rsp
pop mainRsp
invoke main,ADDR msg2,ADDR title2,10,20
invoke ExitProcess,0
main PROC uses rsi rdi rbx x:QWORD,y:QWORD,w:QWORD,z:QWORD PARMAREA=4*SIZEOF QWORD
LOCAL temp1:QWORD
mov rbx,mainRsp
SaveRegs
xor rsi,rsi
mov rdi,1
invoke MessageBox,0,ADDR msg,ADDR title,0
; The first call to MessageBox destroys rcx,rdx,r8 and r9
invoke MessageBox,0,[rbx],[rbx+8],0
ret
main ENDP
END start
Good example for using shadow place in x64
Here is how to get the stack allocated by a Poasm procedure. The task is to get the allocation from the statement add rsp,X before ret :
include RegsToShadSpace.inc
.data
msg db 'Hello!',0
msg2 db 'rcx,rdx,r8 and r9 are saved.',0
title db 'MsgBox',0
title2 db 'Macro test',0
.data?
mainRsp dq ?
.code
start PROC PARMAREA=5*SIZEOF QWORD
invoke main,ADDR msg2,ADDR title2,10,20,30
invoke ExitProcess,0
ret
start ENDP
main PROC a1:QWORD,a2:QWORD,a3:QWORD,a4:QWORD,a5:QWORD PARMAREA=4*SIZEOF QWORD
LOCAL temp1:QWORD
LOCAL temp2:QWORD
LOCAL temp3:QWORD
mov temp1,1
mov temp2,2
mov rax,-1
; How the stack release instructions are encoded?
; Example :
; add rsp, 88 ; 48: 83. C4, 58
; add rsp, 136 ; 48: 81. C4, 00000088
mov r10,OFFSET StackReservation
cmp WORD PTR [r10],08348h
jne l1
movzx rax,BYTE PTR [r10+3]
jmp l3
l1:
mov eax,DWORD PTR [r10+3]
l3:
lea rax,[rsp+rax+8]
mov temp3,rax
mov QWORD PTR [rax],a1
mov QWORD PTR [rax+8],a2
mov QWORD PTR [rax+16],a3
mov QWORD PTR [rax+24],a4
; MessageBox destroying parameters a1,a2,a3 and a4
invoke MessageBox,0,ADDR msg,ADDR title,0
; Retrieve the volatile registers from the shadow space
mov r10,temp3
invoke MessageBox,0,[r10],[r10+8],0
StackReservation:
ret
main ENDP
END start