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
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
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
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.
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
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.
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
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.
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?
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
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
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
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.
:bg
i keep telling you, Steve...
it's in msvcrt.inc and msvcrt.lib, which are included in masm32rt.inc
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
my bad - i keep thinking this is masm32.com :P
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.
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
;******************************************************************************
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
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
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?
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
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
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'
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.
: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"
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
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.
well - i tried that in EDX
maybe i am not using the right register :lol