News:

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

Using th str$() macro

Started by allynm, July 25, 2009, 06:54:53 PM

Previous topic - Next topic

allynm

Hello everyone -

I'm trying to figure out how to write an ascii character in memory to the console using the str$() macro ---or, if that isn't appropriate, some other macro.  Please note that I'm not trying to print a string of chars, just a single char. 

What happens now is that if I use, for example,  str$(eax) I get back the ascii code for the character.  I've looked at all the online helps on macros but can't identify the appropriate one.  But this has got to be a matter of my ignorance, not a deficiency in the macros...

BTW, using crt_putchar with eax pushed on the stack works just ducky. 

Thanks,

Mark Allyn

dedndave

use chr$()
str$() converts the binary to decimal ascii
refer to \masm32\help\hlhelp.chm under "macro catagories/string macros"

jj2007

Quote from: dedndave on July 25, 2009, 07:00:56 PM
use chr$()
chr$ is a powerful macro but it won't work as chr$(al). You need another approach if the char to print is determined programmatically:

include \masm32\include\masm32rt.inc

.data? ; non-initialised variables
MyByte db ?, ?

.code
start:
mov al, 65
mov MyByte, al
print offset MyByte
getkey
exit
end start

Slugsnack

you'd probably want to make sure the character is null terminated. ie. initialise the terminator of MyByte as NULL

in masm uninitialised data tends to be initialised as null anyway actually but it's good to do it just in case. for example this is not the case in programs generated by visual studio C++

dedndave

#4
i noticed that too, Jochen
it shouldn't be hard to write such a macro, however
windows seems to lack the equiv of DOS int 21h, function 2
but, you could push the char onto the stack and do it that way
i am no good at writing macros, but here is a proc....

WChar   PROTO   :DWORD
.
.
.
        INVOKE  WChar,
                65
.
. or.....
.
        mov     al,65
        INVOKE  WChar,
                eax
.
.
.
        OPTION  PROLOGUE:NONE
        OPTION  EPILOGUE:NONE

WChar   PROC    nCharValue:DWORD

        push    ebp
        mov     ebp,esp
        INVOKE  GetStdHandle,
                STD_OUTPUT_HANDLE
        lea     edx,[ebp+8]
        push    eax
        mov     ecx,esp
        INVOKE  WriteFile,
                eax,
                edx,
                1,
                ecx,
                NULL
        leave
        ret     4

WChar   ENDP

        OPTION  PROLOGUE:PrologueDef
        OPTION  EPILOGUE:EpilogueDef

jj2007

Quote from: Slugsnack on July 25, 2009, 07:17:03 PM
you'd probably want to make sure the character is null terminated. ie. initialise the terminator of MyByte as NULL

in masm uninitialised data tends to be initialised as null anyway actually but it's good to do it just in case. for example this is not the case in programs generated by visual studio C++

I vaguely remember we had that question already some time ago. The conclusion was that uninitialised data are zeroed - therefore no need to zero them.

allynm

Hi everyone-

I coded up the snippet using jj's suggestion, including getkey, and it worked fine.  Tested the need for null termination also and the jj code works without null termination as well.  As for the macro I need to understand better what the getstrhandle and writefile windows functions do.   I need to do some reading...as usual...

Thanks to everyone for the suggestions. 

regards,
mark allyn

Slugsnack

you might find the information here useful if you are wanting to learn about console functions, etc.

http://homepages.tesco.net/J.deBoynePollard/FGA/capture-console-win32.html

hutch--


xor eax, eax
mov al, yourbyte

or

mov al, yourbyte
movzx eax, al


Ain't like console mode is speed crtical.  :bg
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

allynm

Hi everyone -

I was intrigued by Dedndave's suggestion to call GetStdHandle and the WriteFile function.  I played around with GetStdHandle function and the Std_Output_Handle.  I can't figure out how they are used.  Where is the Stdin\out\err value returned?  Is it stored on the stack?  In a register (eax?). 

I've been trying to use same call to get handles for crt_fgets and I run into the same wall of ignorance.

How is the GetStdHandle related to __p__iob?  I can make __p__iob work fine for _fgets by just using the eax value returned by the call to __p__iob.

I gotta admit I've learned a ton of MASM in the last week thanks to you folks.. 

Regards,
Mark Allyn

dedndave

GetStdHandle returns the handle in eax
http://msdn.microsoft.com/en-us/library/ms683231(VS.85).aspx

as for crt_fgets and __p__iob, those are C functions
it is like me looking at Greek or a C program - lol (same thing)
i only know a small handful of C functions (whew - good thing this is a masm forum)
if those functions require use of one of the standard handles, they probably obtain it themselves

the standard handles usually have the same values for the originating process
although, they may be aliased for child processes or threads
don't ask me to recall what they are, as i never look at them - lol

i use STD_OUTPUT_HANDLE and STD_INPUT_HANDLE all the time for console mode i/o
you also need the handles to do things like set the screen attributes, cursor position, or control the input mode

btw - Std_Output_Handle is not the same thing as STD_OUTPUT_HANDLE

dedndave

i simplified the routine a bit
also, it returns the bytes written in eax (should always be 1, of course)
when you use WriteFile for console output, the byte count is required
but, that also means there is no need for a zero string terminator

.
.
.
WChar   PROTO   :DWORD
.
.
.
        .DATA?

hStdOut dd ?
.
.
.
        .CODE
.
.
.
        INVOKE  GetStdHandle,
                STD_OUTPUT_HANDLE
        mov     hStdOut,eax
.
.
.
        INVOKE  WChar,
                65
.
. or.....
.
        mov     al,65
        INVOKE  WChar,
                eax
.
.
.
;--------------------------------------------------------------------------

        OPTION  PROLOGUE:NONE
        OPTION  EPILOGUE:NONE

WChar   PROC    nCharValue:DWORD

        lea     edx,[esp+4]
        push    eax
        mov     ecx,esp
        INVOKE  WriteFile,
                hStdOut,
                edx,
                1,
                ecx,
                NULL
        pop     eax
        ret     4

WChar   ENDP

        OPTION  PROLOGUE:PrologueDef
        OPTION  EPILOGUE:EpilogueDef

;--------------------------------------------------------------------------
.
.
.

jj2007

Quote from: jj2007 on July 25, 2009, 07:06:56 PM
chr$ is a powerful macro but it won't work as chr$(al). You need another approach if the char to print is determined programmatically

Just for fun, I wrote a new Chr$ (with uppercase C) macro and included it in the Str$ package.

Usage:

  mov ebx, "A"
  .Repeat
print Str$("\n%i", ebx)
print Chr$(" corresponds to ", ebx)
  inc ebx
  .Until ebx>"C"


Output:
65 corresponds to A
66 corresponds to B
67 corresponds to C

Chr$ accepts registers, global and local DWORD or BYTE variables

allynm

Hi everyone -

I'm trying to understand the code that Dedndave kindly sent along to me.  I have looked over the call to GetStdHandle and can't find or understand where the return value from this call is located.  I don't have any good documentation on this call.  I can't see what's going on when I rev up Ollydbg and look at the disassembly.

Thanks,

Mark A

MichaelW

The MSDN documentation for GetStdHandle is here.

QuoteI have looked over the call to GetStdHandle and can't find or understand where the return value from this call is located.

I'm not sure if this answers your question, but for 32-bit Windows 32-bit integers are returned in EAX, 64-bit integers in EDX:EAX, and floating-point values in ST(0).
eschew obfuscation