The MASM Forum Archive 2004 to 2012

Project Support Forums => 64 Bit Assembler => Topic started by: sinsi on September 06, 2010, 11:22:08 AM

Title: A pchar ml64 example
Post by: sinsi on September 06, 2010, 11:22:08 AM
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.
Title: Re: A pchar ml64 example
Post by: frktons on September 06, 2010, 12:11:24 PM
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


Title: Re: A pchar ml64 example
Post by: 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.
Title: Re: A pchar ml64 example
Post by: frktons on September 06, 2010, 12:30:17 PM
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


Title: Re: A pchar ml64 example
Post by: oex on September 06, 2010, 01:03:15 PM
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
Title: Re: A pchar ml64 example
Post by: japheth on September 06, 2010, 03:15:27 PM
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?
Title: Re: A pchar ml64 example
Post by: oex on September 06, 2010, 03:18:09 PM
Sorry I didnt notice this was 64 bit :/
Title: Re: A pchar ml64 example
Post by: GregL on September 06, 2010, 07:36:03 PM
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.