The MASM Forum Archive 2004 to 2012

General Forums => The Workshop => Topic started by: DanWebb314 on April 16, 2012, 02:57:59 AM

Title: getc and gets
Post by: 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.

'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
Title: Re: getc and gets
Post by: dedndave on April 16, 2012, 03:20:04 AM
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
Title: Re: getc and gets
Post by: dedndave on April 16, 2012, 03:29:21 AM
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
Title: Re: getc and gets
Post by: SteveAsm on April 16, 2012, 04:00:34 AM
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.
Title: Re: getc and gets
Post by: dedndave on April 16, 2012, 04:11:28 AM
                 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
Title: Re: getc and gets
Post by: MichaelW on April 16, 2012, 05:22:56 AM
Dan,

I'm assuming that you want to input from STDIN or the console. The problem with  getc (http://msdn.microsoft.com/en-us/library/5231d02a(v=vs.71).aspx) 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 (http://msdn.microsoft.com/en-us/library/2029ea5f(v=vs.71).aspx) 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 (http://msdn.microsoft.com/en-us/library/3197776x(v=vs.71).aspx) for which there is a way to limit the length of the input.
Title: Re: getc and gets
Post by: SteveAsm on April 16, 2012, 01:19:48 PM
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

Title: Re: getc and gets
Post by: zemtex on April 16, 2012, 05:39:29 PM
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.
Title: Re: getc and gets
Post by: DanWebb314 on April 16, 2012, 09:49:17 PM
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?
Title: Re: getc and gets
Post by: jj2007 on April 16, 2012, 10:20:53 PM
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
Title: Re: getc and gets
Post by: dedndave on April 16, 2012, 11:39:59 PM
        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
Title: Re: getc and gets
Post by: MichaelW on April 17, 2012, 12:28:02 AM
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 (http://msdn.microsoft.com/en-us/library/078sfkak(v=vs.71).aspx). 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

Title: Re: getc and gets
Post by: SteveAsm on April 17, 2012, 12:30:31 AM
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.
Title: Re: getc and gets
Post by: 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
Title: Re: getc and gets
Post by: SteveAsm on April 17, 2012, 02:42:17 AM
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
Title: Re: getc and gets
Post by: dedndave on April 17, 2012, 03:01:54 AM
my bad - i keep thinking this is masm32.com   :P
Title: Re: getc and gets
Post by: hutch-- on April 17, 2012, 03:18:16 AM
I confess I don't see what the big deal is about, the services requested are provided by the OS and OS only, you can access those services through the C runtime functions, the C runtime DLL or just plain roll your own variant from the API. I would not advise a person writing in assembler to use the C runtime function as it sucks in all of the overhead associated with them, MSVCRT works OK allowing that getting character input from the console is hardly a demanding application and there is nothing stopping anyone from writing their own from the API.
Title: Re: getc and gets
Post by: dedndave on April 17, 2012, 03:48:42 AM
for almost everything else, i prefer to roll my own, as you say
because of the buggish behaviour of the console, i like the msvcrt for single keys
what mucks up the works is that the user can make a mess with the right-click context menu (paste, most notably)
the msvcrt seems to handle it as well as anything

i did write this routine using the API
it seems to work fairly well
;******************************************************************************

AnyKey  PROC

;Wait for Any Console Key Press - DednDave 12-2011
;
;  This function returns when any console key is pressed (bKeyDown = 1).
;A possible drawback is that all input event records are removed from
;the console input queue until a key is pressed. In many cases, this is
;not an issue. The virtual key code, virtual scan code, TCHAR character,
;and control key state values are returned in registers.

;Call With: Nothing
;
;  Returns: EAX = TCHAR character (high word of EAX = 0)
;           ECX = control key state flags
;               Bit   Name                Meaning
;                0    RIGHT_ALT_PRESSED   Right ALT key is pressed
;                1    LEFT_ALT_PRESSED    Left ALT key is pressed
;                2    RIGHT_CTRL_PRESSED  Right CTRL key is pressed
;                3    LEFT_CTRL_PRESSED   Left CTRL key is pressed
;                4    SHIFT_PRESSED       SHIFT key is pressed
;                5    NUMLOCK_ON          NUM LOCK light is on
;                6    SCROLLLOCK_ON       SCROLL LOCK light is on
;                7    CAPSLOCK_ON         CAPS LOCK light is on
;                8    ENHANCED_KEY        Key is enhanced
;           EDX:
;           low word (DX) = virtual key code
;               high word = virtual scan code
;
;           all other registers are preserved

        push    ebx
        push    ebp
        sub     esp,(sizeof INPUT_RECORD+3) and -4
        mov     ebp,esp
        INVOKE  GetStdHandle,STD_INPUT_HANDLE
        xchg    eax,ebx
        push    ecx

AnyKy0: INVOKE  ReadConsoleInput,ebx,ebp,1,esp
        movzx   edx,word ptr [ebp].INPUT_RECORD.EventType
        cmp     edx,KEY_EVENT                             ;KEY_EVENT EQU 1
        jnz     AnyKy0

        cmp     edx,[ebp].INPUT_RECORD.KeyEvent.bKeyDown
        jnz     AnyKy0

        pop     ecx
        movzx   eax,word ptr [ebp].INPUT_RECORD.KeyEvent.UnicodeChar
        mov     edx,dword ptr [ebp].INPUT_RECORD.KeyEvent.wVirtualKeyCode
        mov     ecx,[ebp].INPUT_RECORD.KeyEvent.dwControlKeyState
        add     esp,(sizeof INPUT_RECORD+3) and -4
        pop     ebp
        pop     ebx
        ret

AnyKey  ENDP

;******************************************************************************
Title: Re: getc and gets
Post by: SteveAsm on April 17, 2012, 01:49:06 PM
Quote from: dedndave on April 17, 2012, 03:01:54 AM
my bad - ...  

No, not at all.  :clap:
I was just trying to answer his question in the same context in which he presented it.   :U

Quote
...i keep thinking this is masm32.com

I think this is the best forum around for the general discussion of x86 Assembly Language.
And, a noob probably has no knowledge of Masm32 and is wanting to learn Masm programming.  :clap:

You're the best Dave.  :U
Title: Re: getc and gets
Post by: dedndave on April 17, 2012, 06:56:50 PM
nah - plenty of guys in here top me   :P

but - i would say that if you are a newbie to asm, particularly win32 asm, the masm32 package is the best way to start out
if you want to tackle the other packages or methods, it is best if you have some experience under your belt
Title: Re: getc and gets
Post by: DanWebb314 on April 18, 2012, 04:01:09 AM
This work like a dream:

Quote from: jj2007 on April 16, 2012, 10:20:53 PM
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


It assembles without error.   What is 'esp'?  I can see that 'print esp' echos back the key you hit.

Next,  what is as simple as this but returns a string?
Title: Re: getc and gets
Post by: dedndave on April 18, 2012, 04:07:20 AM
        include \masm32\include\masm32rt.inc

        .code

start:  mov     edx,input("Enter a String: ")
        print   edx
        print   chr$(13,10)
        inkey
        exit

end start


i didn't test it, but it should work   :P
Title: Re: getc and gets
Post by: dedndave on April 18, 2012, 04:17:00 AM
sorry - i should have tested it, first
try this one...
        include \masm32\include\masm32rt.inc

        .code

start:  print   input("Enter a String: ")
        print   chr$(13,10)
        inkey
        exit

        end     start
Title: Re: getc and gets
Post by: DanWebb314 on April 18, 2012, 04:22:05 AM
OK,  I jumped to quick.  esp is the the stack pointer.  so 'print esp'  sends the character you pushed with 'push eax'.  I guess that is all I need to know about 'print exp'

Title: Re: getc and gets
Post by: DanWebb314 on April 18, 2012, 04:23:48 AM
About this code

Quote from: dedndave on April 18, 2012, 04:17:00 AM
sorry - i should have tested it, first
try this one...
        include \masm32\include\masm32rt.inc

        .code

start:  print   input("Enter a String: ")
        print   chr$(13,10)
        inkey
        exit

        end     start


I guess I will have to try it out to see where the string goes.
Title: Re: getc and gets
Post by: dedndave on April 18, 2012, 04:27:45 AM
 :bg

the "input" macro sets up the "Enter a String: " string in the .DATA section
the input buffer (where your typed characters go) may be on the stack, or it may be in the .DATA? section
you can look at the macro and see how it works
it is in the \masm32\macros\macros.asm file
search for "input macro"
Title: Re: getc and gets
Post by: dedndave on April 18, 2012, 04:32:37 AM
        getkey
        push  eax
        print esp
        pop   eax


in this code of Jochen's, ESP is the stack pointer register
the character is PUSH'ed onto the stack (followed by a 0), then it's displayed, then it's POP'ed back off the stack
Title: Re: getc and gets
Post by: DanWebb314 on April 19, 2012, 03:55:45 AM
This code show me where the inputted string goes::

    mov ebx, input(" Input number: ")
    mov eax, [ebx]


Now 'eax' has the first 4 charters of the input string.
Title: Re: getc and gets
Post by: dedndave on April 19, 2012, 11:56:25 PM
well - i tried that in EDX
maybe i am not using the right register   :lol