Reputation: 5080
I'm trying to learn how to invoke operating system functions in assembly and have gotten an example worked out that will create and then close a file (deleting it file on close). While researching the usage of ExitProcess
I came across some example that clean up the stack and some that don't; even more confusing is that things seem to work with or without a clean up step...
What is the proper way to handle the stack in this situation?
extern CloseHandle : proc
extern CreateFileA : proc
extern ExitProcess : proc
include FileAccess.inc
include FileDisposition.inc
include FileFlag.inc
include FileShare.inc
.data
filePath byte "C:\Temp\test123.txt",0
.code
Main PROC
sub rsp, 48h ; align with 16 while simultaneously making room on the stack for the "home space" and any parameters
lea rcx, filePath ; put address of file name into parameter slot 0
mov rdx, FILE_ACCESS_READ ; put access mode into parameter slot 1
mov r8, FILE_SHARE_READ ; put share mode into parameter slot 2
xor r9, r9 ; put security attributes into parameter slot 3
mov qword ptr [((rsp + 48h) - 28h)], FILE_DISPOSITION_CREATE ; put disposition into parameter slot 4
mov qword ptr [((rsp + 48h) - 20h)], FILE_FLAG_DELETE_ON_CLOSE ; put flags into parameter slot 5
mov qword ptr [((rsp + 48h) - 18h)], 0 ; put template handle into parameter slot 6
call CreateFileA ; create file handle
mov rcx, rax ; move file handle into parameter slot 0
call CloseHandle ; close file handle
add rsp, 48h ; free all space that was reserved on the stack
xor ecx, ecx ; set return value to zero
call ExitProcess
Main ENDP
END
Upvotes: 2
Views: 1389
Reputation: 33804
the ExitProcess
usual function (windows api) and must be called with common calling convention for x64. in particular stack must be maintained 16-byte aligned
so call ExitProcess
like any other api. the add rsp, 48h
instruction before call ExitProcess
is wrong
also some general notes:
the imported api always called indirect - if you want call SomeApi
- declare variable (code for x64)
extern __imp_SomeApi : QWORD
and call
call __imp_SomeApi
if we declare
extern SomeApi : proc
and do
call SomeApi
the linker create stub
SomeApi:
jmp qword ptr __imp_SomeApi
so better direct use __imp_SomeApi
form.
also always much better use W instead A api form. so all code can look like
FILE_FLAG_DELETE_ON_CLOSE = 04000000h
CREATE_ALWAYS = 2
FILE_SHARE_READ = 1
GENERIC_READ = 080000000h
INVALID_HANDLE_VALUE = -1
extern __imp_ExitProcess : QWORD
extern __imp_CreateFileW : QWORD
extern __imp_CloseHandle : QWORD
WSTRING macro text
FORC arg, text
DW '&arg'
ENDM
DW 0
endm
.const
ALIGN 2
filePath: WSTRING <C:\Temp\test123.txt>
.code
Main proc
sub rsp, 48h
mov qword ptr [rsp + 30h], 0
mov qword ptr [rsp + 28h], FILE_FLAG_DELETE_ON_CLOSE
mov qword ptr [rsp + 20h], CREATE_ALWAYS
xor r9, r9
mov r8, FILE_SHARE_READ
mov rdx, GENERIC_READ
lea rcx, filePath
call __imp_CreateFileW
cmp rax, INVALID_HANDLE_VALUE
je @@0
mov rcx, rax
call __imp_CloseHandle
@@0:
xor ecx, ecx
call __imp_ExitProcess
add rsp, 48h
ret
Main endp
end
Upvotes: 4