This one seems to work well, be easy to use and so far, reliable so I will probably add it to the main macro file.
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
include \masm32\include64\masm64rt.inc
sav MACRO reg
IFNDEF aligned_reg_data
initreg
ENDIF
mov reg_®, reg
ENDM
rst MACRO reg
mov reg, reg_®
ENDM
initreg MACRO
aligned_reg_data equ 0
.data?
align 8
reg_rax dq ?
reg_rbx dq ?
reg_rcx dq ?
reg_rdx dq ?
reg_r8 dq ?
reg_r9 dq ?
reg_r10 dq ?
reg_r11 dq ?
reg_r12 dq ?
reg_r13 dq ?
reg_r14 dq ?
reg_r15 dq ?
reg_rsi dq ?
reg_rdi dq ?
reg_rbp dq ?
reg_rsp dq ?
.code
ENDM
.code
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
entry_point proc
conout str$(r12),lf ; register content before proc call
conout str$(r13),lf
conout str$(r14),lf
conout str$(r15),lf
call tryit
conout str$(r15),lf ; register content after proc call
conout str$(r14),lf
conout str$(r13),lf
conout str$(r12),lf
waitkey
.exit
entry_point endp
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
NOSTACKFRAME
tryit proc
sav r12 ; save the register contents
sav r13
sav r14
sav r15
mov r12, 12345678 ; modify the registers
mov r13, 12345678
mov r14, 12345678
mov r15, 12345678
rst r12 ; restore the register contents
rst r13
rst r14
rst r15
ret
tryit endp
STACKFRAME
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
end
Seems like this might be a good place to use vararg