News:

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

getc and gets

Started by DanWebb314, April 16, 2012, 02:57:59 AM

Previous topic - Next topic

DanWebb314

How do I use
      getc
      gets


do I need to use an include?
I tried them both and they get an error.

'gets' needs a buffer 128 byte or more in length.
Could you please include a short example program to show how to use each

Thank you
Dan

dedndave

start off with
        INCLUDE    \masm32\include\masm32rt.inc
that has all the preamble stuff for your program
have a look at that file so you don't duplicate lines in your own code

then, you should be able to use them as
crt_gets
crt_getc

dedndave

if you don't have some reason for using the crt functions,
the masm32 package has macros and functions to get line input from the console
the "input" macro is described in masm32\help\hlhelp.chm
it uses the "StdIn" function, as well as "StdOut"
the code for these functions is in masm32\m32lib
the macros appear in \masm32\macros\macros.asm

we do use crt__getch and crt__kbhit for single character input
but, it can be done with the API, as well
the console is an imperfect world   :P
those 2 crt functions are fairly stable - probably moreso than the API methods

SteveAsm

Quote from: DanWebb314 on April 16, 2012, 02:57:59 AM
How do I use
      getc
      gets

do I need to use an include?
I tried them both and they get an error.

Both getc and gets are C library functions.
To use them, you include the standard C header and the C library.
Like so:    (untested:)

                 include \masm32\include\stdio.inc
;...and...
                 includelib \masm32\lib\crtdll.lib


Quote
'gets' needs a buffer 128 byte or more in length.

(Untested)

.data?
        StringBffr        db        128    dup(?)
.code
    invoke gets, addr StringBffr



That's basically it.

dedndave

                 include \masm32\include\stdio.inc
;...and...
                 includelib \masm32\lib\crtdll.lib


in the masm32 package, they are in msvcrt.inc/lib
which are covered in masm32rt.inc

MichaelW

#5
Dan,

I'm assuming that you want to input from STDIN or the console. The problem with getc is that it reads the character from a stream. In C it's easy enough to use it to input from STDIN:

    int ch;
    ch = getc(stdin);

But behind the functionality is a bunch of compiler-generated code that I can't see any easy way to duplicate in assembly:

mov eax, DWORD PTR __iob+4
sub eax, 1
mov DWORD PTR __iob+4, eax
js SHORT $L74397
mov ecx, DWORD PTR __iob
movsx edx, BYTE PTR [ecx]
and edx, 255 ; 000000ffH
mov DWORD PTR tv71[ebp], edx
mov eax, DWORD PTR __iob
add eax, 1
mov DWORD PTR __iob, eax
jmp SHORT $L74398
$L74397:
push OFFSET FLAT:__iob
call __filbuf
add esp, 4
mov DWORD PTR tv71[ebp], eax
$L74398:
mov ecx, DWORD PTR tv71[ebp]
mov DWORD PTR _ch$[ebp], ecx


A better choice would be getchar, which gets the character from STDIN.

And while gets is easy enough to use, a potential problem with it is that there is no way to limit the length of the input to avoid overflowing the buffer. A better choice might be _cgets for which there is a way to limit the length of the input.
eschew obfuscation

SteveAsm

Dan,

Quote from: MichaelW
And while gets is easy enough to use, a potential problem with it is that there is no way to limit the length of the input to avoid overflowing the buffer.
A better choice might be _cgets for which there is a way to limit the length of the input.

Even tho' my example answers your question, as to how you use gets, what MichaelW points out is no small issue.
It can mean the difference between crashing your program or not.
A buffer overflow is a very bad thing to have happen, as valid data will be corrupted, at the very least.

You can use gets if you create a means for never exceeding the buffer size.
Something like:

{pseudo code}
  count = 1
  BufferSize = 128 bytes

  myBuffer  db  BufferSize  dup(?)

  while count < BufferSize
      call gets, addressof myBuffer
      increment count
  wend
  ...continue


zemtex

Buffer overflows should only happen in controlled manners, when you know and have planned for it. Otherwise, there shouldn't even be a reason to argue why it should never happen, because it is a very bad thing indeed. And if you allow it to happen it gets worse.
I have been puzzling with lego bricks all my life. I know how to do this. When Peter, at age 6 is competing with me, I find it extremely neccessary to show him that I can puzzle bricks better than him, because he is so damn talented that all that is called rational has gone haywire.

DanWebb314

getchar is what I would like to use.

I tried:
   include \masm32\include\stdio.inc
   includelib \masm32\lib\crtdll.lib


Masm32 does not like the first line.

What is the best and easiest way to get a character from the console?
And what do I need to include to get it to work?

jj2007

include \masm32\include\masm32rt.inc

.code
start: print "press Return to exit", 13, 10
.Repeat
getkey
push eax
print esp
pop eax
.Until eax==13
exit

end start

dedndave

        push    eax
        print   esp
        pop     eax


:bg

the "ret_key" function, which is used in the "getkey" macro, doesn't handle extended keystrokes
also - i think it samples the keyboard once every millisecond - you'd have to be a 10,000 WPM typist to go that fast   :P
so, i wrote my own...
        .XCREF
        .NOLIST
        INCLUDE \masm32\include\masm32rt.inc
        .LIST

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

        .CODE

;*************************************************************************

_main   PROC

        print   chr$('Press Esc to Exit'),13,10
        jmp short kloop2

kloop1: INVOKE  Sleep,40

kloop2: call    InKyb
        jz      kloop1

        push    eax
        cmp     ah,0
        jz      kloop3

        push    2020h
        jmp short kloop4

kloop3: mov     ah,20h
        push    eax

kloop4: print   esp
        pop     edx
        pop     eax
        push    eax
        print   right$(uhex$(eax),4),13,10
        pop     eax
        cmp     eax,1Bh
        jnz     kloop2

        exit

_main   ENDP

;*************************************************************************

InKyb   PROC

;Polled Keyboard Input - DednDave 8, 2010
;
;This function returns a keystroke in EAX if there is one in the buffer.
;If the buffer is empty, the function returns immediately.
;
;If the keyboard buffer is empty, AH = 0, AL = 0, ZF = 1.
;If the stroke is a regular key, AH = 0, AL = key char, ZF = 0.
;If the stroke is an extended key, AH = extended key, AL = E0h, ZF = 0.
;If the stroke is a function key, AH = function key, AL = 0, ZF = 0.
;
;ECX, EDX are not preserved.

        call    crt__kbhit
        or      eax,eax
        jz      InKyb1

        call    crt__getch
        and     eax,0FFh
        jz      InKyb0

        cmp     al,0E0h
        jnz     InKyb1

InKyb0: push    eax
        call    crt__getch
        pop     edx
        shl     eax,8
        or      eax,edx

InKyb1: retn

InKyb   ENDP

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

        END     _main


as i recall, this program will handle a 250 WPM typist who likes to hit arrow and function keys   :lol

MichaelW

Quote from: DanWebb314 on April 16, 2012, 09:49:17 PM
getchar is what I would like to use.

What is the best and easiest way to get a character from the console?

It turns out that getchar does not work as I assumed. Although it returns only the first character, it reads and echoes characters until you press the Enter key -- not very useful IMO. I think Dave has the right idea, using _getch. If you need code that will wait for a character, you can just call _getch or _getche, depending on whether or not you want the character echoed to the console. In case it's not obvious, you should build this as a console app:

;==============================================================================
include \masm32\include\masm32rt.inc
;==============================================================================
.data
.code
;==============================================================================
start:
;==============================================================================

    invoke crt_getchar
    printf("%c\n\n", eax)

    invoke crt__getch
    printf("%c\n\n", eax)
    invoke crt__getche
    printf("%c\n\n", eax)

    inkey
    exit
;==============================================================================
end start

eschew obfuscation

SteveAsm

Quote from: DanWebb314 on April 16, 2012, 09:49:17 PM
   include \masm32\include\stdio.inc
   includelib \masm32\lib\crtdll.lib


Masm32 does not like the first line.

My bad,
you need to use:
   include \masm32\include\windows.inc

as well.
Actually, it's Masm, not Masm32.

dedndave

 :bg

i keep telling you, Steve...
it's in msvcrt.inc and msvcrt.lib, which are included in masm32rt.inc

SteveAsm

Quote from: dedndave on April 17, 2012, 01:48:48 AM
:bg

i keep telling you, Steve...
it's in msvcrt.inc and msvcrt.lib, which are included in masm32rt.inc

Yes dave,
but, you assume that everyone wants to use MASM32 macros and utilities.
Some of us do prefer to use the API and C Library.  :U