News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

A pchar ml64 example

Started by sinsi, September 06, 2010, 11:22:08 AM

Previous topic - Next topic

sinsi

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.
Light travels faster than sound, that's why some people seem bright until you hear them.

frktons

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


Mind is like a parachute. You know what to do in order to use it :-)

sinsi

You don't declare wsprintfA anywhere.
Do you know this function only formats a string, it doesn't print it to the console.
Light travels faster than sound, that's why some people seem bright until you hear them.

frktons

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


Mind is like a parachute. You know what to do in order to use it :-)

oex

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
We are all of us insane, just to varying degrees and intelligently balanced through networking

http://www.hereford.tv

japheth

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?

oex

Sorry I didnt notice this was 64 bit :/
We are all of us insane, just to varying degrees and intelligently balanced through networking

http://www.hereford.tv

GregL

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.