extern MessageBoxA:proc
includelib user32.lib
NULL EQU 0
MB_OK EQU 0
.const
msg BYTE "Hello x64 world!",0 ;0 means msg end with '\0'
wintitle BYTE "App",0
.CODE
main PROC
mov rcx,NULL ;arg1 hWnd
mov rdx,offset msg ;arg2 lpText
mov r8,offset wintitle ;arg3 lpCaption
mov r9d,MB_OK ;arg4 uType
sub rsp,28h
;sub rsp,08h ;8h 8 bytes for padding to 16 bytes alignment
call MessageBoxA ;push "xor" instruction addr for returning anchor
xor ecx,ecx ;clear ecx
;add rsp,08h ;restore rsp.
add rsp,28h
ret ;pop rip
main ENDP
END
;64位CPU规定,发起函数调用时,执行子函数第一条指令时栈顶地址需要对齐到16字节,而执行call指令时,会自动向栈中压入后一条指令的地址,8字节,如果在call之前,rsp已经是16的整数倍,则进入子函数后,rsp就因为偏移了8变得无法被16整除,所以需要人为地在call指令执行前对rsp偏移8字节,函数调用结束后,再人为地复位。
;在子函数内部,rcx, rdx, r8, r9 可能还有其他用处,此时一般会先将他们挪到栈上:mov [rsp+8],rcx mov [rsp+10] rdx mov [rsp+18] r8 mov [rsp+20] r9, 如果提前没有预留好空间,则会内存越界,发生崩溃(有的函数如果没有把rcx,rdx,r8,r9做其他用途,就不会崩溃)。因此惯例做法是在call之前额外预留20h的空间,call之后人为复位。
;综上,总是预先留足28h的空间。
; complie command: ml64.exe /Cp /c progx.asm
; link command: link.exe /MACHINE:x64 /ENTRY:main progx.obj
masm 64位CPU汇编指令基础
于 2023-09-09 14:25:50 首次发布