I want to convert the following C++ program in MASM (The goal is to open an existing file, write a string into it and at the end read the file) :
void __cdecl _tmain(int argc, TCHAR *argv[])
{
HANDLE hFile;
/////////////////////////////////////////////////////////////////////////////////
if ((hFile = CreateFile(TEXT("C:\\Users\\Bloodsucker94\\Desktop\\TestFile.txt"),
GENERIC_WRITE | GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL)) == INVALID_HANDLE_VALUE)
_tprintf(TEXT("CreateFile() failed code %d\n"), GetLastError());
/////////////////////////////////////////////////////////////////////////////////
char DataBuffer[1024] = "aaa";
DWORD dwBytesToWrite = (DWORD)strlen(DataBuffer);
DWORD dwBytesWritten = 0;
//_tprintf(TEXT("CreateFile() HFILE=%d\n"), hFile);
if (WriteFile(hFile, DataBuffer, dwBytesToWrite, &dwBytesWritten, NULL) == FALSE)
_tprintf(TEXT("WriteFile() failed code %d\n"), GetLastError());
//_tprintf(TEXT("WriteFile() HFILE=%d\n"), hFile);
/////////////////////////////////////////////////////////////////////////////////
SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
char ReadBuffer[4096] = {0};
DWORD dwBytesRead;
if (FALSE == ReadFile(hFile, ReadBuffer, 4096, &dwBytesRead, NULL))
_tprintf(TEXT("ReadFile() failed code %d\n"), GetLastError());
printf("|%s|", ReadBuffer);
getchar();
CloseHandle(hFile);
}
The ASM code :
.386
.model flat, stdcall
option casemap :none
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\masm32.inc
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\masm32.lib
include \masm32\include\msvcrt.inc
includelib \masm32\lib\msvcrt.lib
.data
FileName BYTE "HelloWorld.txt", 0
BufferToWrite BYTE "Hell yeaahhhhhh!!!!", 0
ErrorCreateMsgFormat BYTE "CreateFile() failed with code %d", 0
ErrorReadMsgFormat BYTE "ReadFile() failed with code %d", 0
ErrorWriteMsgFormat BYTE "WriteFile() failed with code %d", 0
CheckFormat BYTE "hFile=%d", 0
CheckSize BYTE "size=%d", 0
CheckPtr BYTE "EAX_ADDR=Ox%08X", 0
OutputFormat BYTE "output=%s", 0
.data?
hFile HANDLE ?
hFileCopy HANDLE ?
FileSize DWORD ?
hMem LPVOID ?
BytesRead LPDWORD ?
ErrorCode DWORD ?
RetRead BOOL ?
RetWrite BOOL ?
NumberOfBytesToWrite DWORD ?
NumberOfBytesWritten DWORD ?
BufferToWriteSize DWORD ?
.code
start:
invoke lstrlen, ADDR BufferToWrite
mov BufferToWriteSize, eax
;-----------------------------CREATE-------------------------------
invoke CreateFile, ADDR FileName, \
GENERIC_WRITE + GENERIC_READ, \
0, \
NULL, \
OPEN_EXISTING, \
FILE_ATTRIBUTE_NORMAL, \
NULL
mov hFile, eax
.IF hFile == INVALID_HANDLE_VALUE
invoke GetLastError
mov ErrorCode, eax
invoke crt_printf, ADDR ErrorCreateMsgFormat, \
ErrorCode
jmp _quit
.ENDIF
invoke crt_printf, ADDR CheckFormat, \
hFile
;---------------------------WRITE---------------------------------
invoke WriteFile, hFile, \
ADDR BufferToWrite, \
BufferToWriteSize, \
ADDR NumberOfBytesWritten, \
NULL
mov RetWrite, eax
.IF RetWrite == FALSE
invoke GetLastError
mov ErrorCode, eax
invoke crt_printf, ADDR ErrorWriteMsgFormat, \
ErrorCode
jmp _quit
.ENDIF
invoke crt_printf, ADDR CheckFormat, \
hFile
;--------------------------READ----------------------------------
invoke GetFileSize, eax, \ ;problem start here
NULL
mov FileSize, eax
inc eax
invoke crt_printf, ADDR CheckSize, \
FileSize
invoke GlobalAlloc, GMEM_FIXED, \
eax
mov hMem, eax
add eax, FileSize
mov BYTE PTR [eax], 0
invoke ReadFile, hFile, \
hMem, \
FileSize, \
ADDR BytesRead, \
NULL
mov RetRead, eax
.IF RetRead == FALSE
invoke GetLastError
mov ErrorCode, eax
invoke crt_printf, ADDR ErrorReadMsgFormat, \
ErrorCode
jmp _quit
.ENDIF
invoke crt_printf, ADDR CheckFormat, \
hFile
invoke crt_printf, ADDR OutputFormat, \
hMem
invoke CloseHandle, hFile
invoke GlobalFree, hMem
_quit:
invoke ExitProcess, 0
end start
The problem is EAX register not contain the CreateFile return value (hFile). It's normal because it contains at the point of the execution the value of the WriteFile function. I didn't find any solution to conserve the initial value of eax returned by CreatefILE function and use it again after the WriteFile function call. I can't do this :
mov FileSize, hFile
I just want to save the first value of eax. I tried to save it into another register but it does not work. Does anyone can help me ?
Eiher:
.data
savedValue DWORD ?
.code
…
// save to a variable
mov savedValue, eax
…
// restore from a variable
mov eax, savedValue
…
or:
.code
…
// save to stack
push eax
…
// restore from stack
pop eax
…
Sorry for any syntax errors. It's been a long a time since the last common use case for direct assembly use.