News:

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

How do I pass eax to StdOut?

Started by rotten, April 26, 2009, 03:10:16 PM

Previous topic - Next topic

rotten

I have a procedure to print a multidigit nbr,
I don't want to have to pass in the Acc since it makes no sense really but I don't get how to pass a register to StdOut.
Also where is StdOut defined? I can't find a good reference and/or tutorial for masm32.


printnbr proc Acc : sdword
   mov ebx, 10 ; Divide by this
   xor ecx, ecx ; digit-counter
pushloop:
   xor edx, edx ;
   div ebx ; quotient in eax, remainder in edx
   push edx ; store it for later
   inc ecx
   cmp eax, 0
   jnz pushloop
poploop:
   pop eax ; get digit back
   add al, '0' ; convert to character
   mov Acc, eax
   push ecx ; StdOut modifies ecx so save it to pop it back 2 rows down.
   invoke StdOut, addr Acc
   pop ecx
   loop poploop
   ret
printnbr endp

mitchi

invoke StdOut, eax
or invoke StdOut, [eax]

Depends on what you need.

rotten

I have tried both eax and [eax] and both assembles and links fine but crashes at runtime.



; #########################################################################

   .386
   .model flat, stdcall
   option casemap :none

; #########################################################################

   include \masm32\include\windows.inc
   include \masm32\include\user32.inc
   include \masm32\include\kernel32.inc
   include \masm32\include\masm32.inc

   includelib \masm32\lib\user32.lib
   includelib \masm32\lib\kernel32.lib
   includelib \masm32\lib\masm32.lib

   includelib \masm32\libs\math\math.lib

; #########################################################################

fac PROTO N : DWORD
fib PROTO N : DWORD
   
.data
    S db "Result is: ", 0
    N sdword 5
    Acc sdword 0
    ;IntArray        dword 8 dup (?)

.code
start:

;; invoke fac, 5
;; invoke fib, 12
mov eax, 10
   
utoa:
   mov ebx, 10 ; we'll divide by this
   xor ecx, ecx ; use as digit-counter
pushloop:
   xor edx, edx ;
   div ebx ; quotient in eax, remainder in edx
   push edx ; store it for later
   inc ecx
   cmp eax, 0
   jnz pushloop
poploop:
   pop eax ; get digit back
   add al, '0' ; convert to character
   ;; mov Acc, eax
   push ecx
   invoke StdOut, [eax] ;; addr Acc
   pop ecx
   loop poploop
   ret

;; mov Acc, 1
;; add Acc, 48
;; invoke StdOut, addr Acc
;; invoke StdOut, addr Acc
   
invoke ExitProcess, 0
   
end start


Jimg

StdOut is a routine in masm32lib.  It looks like-
StdOut proc lpszText:DWORD

    LOCAL hOutPut  :DWORD
    LOCAL bWritten :DWORD
    LOCAL sl       :DWORD

    invoke GetStdHandle,STD_OUTPUT_HANDLE
    mov hOutPut, eax

    invoke StrLen,lpszText
    mov sl, eax

    invoke WriteFile,hOutPut,lpszText,sl,ADDR bWritten,NULL

    mov eax, bWritten
    ret

StdOut endp

It is designed to print one or more characters to the standard output console.
This routine and most all the routines that write to output expect the address of a string, so you can't just pass the character in eax.
You could define a local variable rather than adding a proc parameter, store the character in that, and call StdOut with the address of the local variable.
eg.
printnbr proc
   local Acc
   mov ebx, 10 ; Divide by this
   . etc

does the same thing.

You could make a modified StdOut that would accept a character in eax and use that instead, eg.
StdOutx proc inchar

    LOCAL hOutPut  :DWORD
    LOCAL bWritten :DWORD
       
    invoke GetStdHandle,STD_OUTPUT_HANDLE
    mov hOutPut, eax
    invoke WriteFile,hOutPut,addr inchar,1,ADDR bWritten,NULL
    mov eax, bWritten
    ret

StdOutx endp

printnbr proc
   mov ebx, 10 ; Divide by this
   xor ecx, ecx ; digit-counter
pushloop:
   xor edx, edx ;
   div ebx ; quotient in eax, remainder in edx
   push edx ; store it for later
   inc ecx
   cmp eax, 0
   jnz pushloop
poploop:
   pop eax ; get digit back
   add al, '0' ; convert to character
   push ecx ; StdOut modifies ecx so save it to pop it back 2 rows down.
   invoke StdOutx, eax
   pop ecx
   loop poploop
   ret
printnbr endp

I notice you didn't save ebx as is standard practice.
You could use esi rather than ecx and you would not have to worry about StdOut changing it-
e.g. printnbr proc uses ebx esi

I don't know of any windows api that takes one character as input and prints it to the console, but there is probably one hidden somewhere.


Vortex

QuoteAlso where is StdOut defined? I can't find a good reference and/or tutorial for masm32.

StdOut is a member of masm32.lib and here is where you can find the source code of this function :

\masm32\m32lib\stdout.asm

MASM32 Library Reference :

\masm32\help

MichaelW

rotten,

StdOut expects a pointer to a zero-terminated string. Your code works OK for this because the three most-significant bytes of the remainder will always be zero, and dwords are stored in memory with the least-significant byte at the lowest address (so in other words, the converted character will be followed in memory by a zero byte). You could avoid using Acc with something like this:

poploop:
   pop eax ; get digit back
   add al, '0' ; convert to character
   ;mov Acc, eax
   push ecx ; StdOut modifies ecx so save it to pop it back 2 rows down.
   ;invoke StdOut, addr Acc
   push eax                   ; put eax on stack
   invoke StdOut, esp         ; esp always points to last value pushed
   pop eax                    ; remove pushed value from stack
   pop ecx
   loop poploop


But IMO your current method is better because it's easier to understand.
eschew obfuscation