This is a simple example of a print character console routine that shows how you can use the stack align problem to your advantage.
It assumes that the caller has a 16-byte aligned RSP before the call, uses the same fastcall that win64 uses (rcx,rdx,r8,r9) and that 'stdout' has a valid handle.
pchar: push rcx ;char in CL, stack align is now 16
mov rdx,rsp ;param2 = pointer to buffer
push rcx ;chars written, stack align is now 8
mov r9,rsp ;param4 = pointer to chars written
push 0 ;param5 = lpReserved, stack align is now 16
sub rsp,20h ;spill space - 4*regs
mov rcx,stdout ;param1 = handle
mov r8,1 ;param3 = chars to write
call WriteConsoleA
add rsp,38h ;20h from spill plus those 3 pushes
ret
Change 'WriteConsoleA' to 'WriteConsoleW' and it should work for unicode too with the char in CX.
Hi sinsi, probably you know enough 64 bit Assembly to see
what is missed in this piece of code:
EXTERN ExitProcess:PROC
EXTERN printf:PROC
EXTERN _getch:PROC
INCLUDELIB kernel32.lib
INCLUDELIB user32.lib
INCLUDELIB msvcrt.lib
.DATA
msg BYTE "This is a 64 bit Assembly program",13,10,13,10
.CODE
start:
main PROC
sub rsp, 40
lea rcx, msg
call wsprintfa
call WaitKey
call ExitProcess
main ENDP
; -------------------------------------------------------------------------
; -------------------------------------------------------------------------
WaitKey PROC
; int WaitKey(void);
LOCAL dwCrLf:DWORD
LOCAL dwChar:DWORD
.DATA
szPrompt BYTE 13,10,"Press any key to exit ... ", 0
.CODE
sub rsp, 40
mov dwCrLf, 00000A0Dh
lea rcx, szPrompt
call printf
call _getch
cmp eax, 0
je again
cmp eax, 0E0h
je again
jmp @F
again:
call _getch
@@:
add rsp, 40
ret
WaitKey ENDP
;-----------------------------------------------------------
END
because ML64 says:
Microsoft (R) Macro Assembler (x64) Version 10.00.30319.0
Copyright (C) Microsoft Corporation. All rights reserved
Assembling: c:\x64\c2.asm
c:\x64\c2.asm(27) : error A2006:undefined symbol : wsprintfA
How should I tell ML64 to look for this function?
Do you see other errors that can prevent the program to assemble
or to run on a 64 bit machine/OS ?
Edit: with printf it works, but if I'd like to store the variable into a buffer
with wsprintfa, how should I call it?
Thanks
Frank
You don't declare wsprintfA anywhere.
Do you know this function only formats a string, it doesn't print it to the console.
Quote from: sinsi on September 06, 2010, 12:16:02 PM
You don't declare wsprintfA anywhere.
Do you know this function only formats a string, it doesn't print it to the console.
Yes sinsi, I know it, I was just trying some instructions.
How do I declare it?
EXTERN wsprintfA:PROC ?
In this way it assembles without error but the program freezes.
It is an example of Greg, a first draft, that I'm trying to make working,
But I don't fully understand it, and probably something else should be
corrected. ::)
The full listing, with the corrections done so far is:
;-----------------------------------------------------------------------
; ClearBuffer example in x64 bit MASM written by Greg L.
; Compile with ML64
;-----------------------------------------------------------------------
EXTERN ExitProcess:PROC
EXTERN printf:PROC
EXTERN _getch:PROC
EXTERN wsprintfA:PROC
INCLUDELIB kernel32.lib
INCLUDELIB user32.lib
INCLUDELIB msvcrt.lib
.DATA
msg BYTE "Clearing done",13,10,13,10
.DATA?
;buf2clear CHAR_INFO 2000 DUP(<>) ; SIZEOF CHAR_INFO = 4
align 8
buf2clear db 8000 DUP(?)
.CODE
start:
main PROC
sub rsp, 40
lea rcx, buf2clear
mov rdx, 1000 ; (SIZEOF buf2clear) / 8
call ClearBufferQw
lea rcx, msg
call wsprintfA
call WaitKey
xor ecx, ecx
call ExitProcess
main ENDP
; -------------------------------------------------------------------------
ClearBufferQw PROC
; int ClearBuffer(char* AddrBuffer, int count);
push rdi
mov rdi, rcx
mov rcx, rdx
mov rax, 2020202020202020h
rep stosq
pop rdi
ret
ClearBufferQw ENDP
; -------------------------------------------------------------------------
WaitKey PROC
; int WaitKey(void);
LOCAL dwCrLf:DWORD
LOCAL dwChar:DWORD
.DATA
szPrompt BYTE 13,10,"Press any key to exit ... ", 0
.CODE
sub rsp, 40
mov dwCrLf, 00000A0Dh
lea rcx, szPrompt
call printf
call _getch
cmp eax, 0
je again
cmp eax, 0E0h
je again
jmp @F
again:
call _getch
@@:
mov dwChar, eax
lea rcx, dwCrLf
call printf
mov eax, dwChar
add rsp, 40
ret
WaitKey ENDP
;-----------------------------------------------------------
END
Quote from: frktons on September 06, 2010, 12:30:17 PM
Yes sinsi, I know it, I was just trying some instructions.
How do I declare it?
EXTERN wsprintfA:PROC ?
In this way it assembles without error but the program freezes.
It is an example of Greg, a first draft, that I'm trying to make working,
But I don't fully understand it, and probably something else should be
corrected. ::)
wsprintf is declared in user32.inc.... you should be including this with:
include \masm32\include\user32.inc
includelib \masm32\lib\user32.lib
Quote from: oex on September 06, 2010, 01:03:15 PM
wsprintf is declared in user32.inc.... you should be including this with:
include \masm32\include\user32.inc
includelib \masm32\lib\user32.lib
I doubt whether this is a good advice - AFAIR the user32.inc prototypes are not compatible with 64-bit
From a technical point of view, the error is that wsprintfA needs at least
two arguments, first comes the buffer, then the "format string". However, judging from a less technical view I guess that using wsprintfA is a silly idea in this context. Why not simply using printf instead?
Sorry I didnt notice this was 64 bit :/
Frank,
Yes, use printf instead, I was converting from some other code and missed changing that wsprintfA to printf.
I'll get set up to assemble with ml64 soon.