Simple demo on how to emulate CALL and RET instructions semantics. JMP is RIP-relative.
;<<<<<<<<<<<<<<<<<<<<<
; CALL and RET emulations
; nasm -f win64 prog.asm
; gcc -m64 prog.obj -o prog.exe
;>>>>>>>>>>>>>>>>>>>>>
global main
extern printf
section .data
msg: db 'Hello World',0ah,0
section .text
main:
sub rsp,8 ;alignment
;CALL semantics
push $+7 ;5 bytes +
jmp tester ;2 bytes
add rsp,8 ;balancing
;RET semantics
add rsp,8
jmp qword[rsp-8]
tester:
sub rsp,40 ;align + shadow
mov rcx,msg
call printf
add rsp,48 ;balancing + RET
jmp qword[rsp-8]