Basic user input - winapi

I'm working on learning some Assembly Language (x86 Irvine.32 windows7) and had a question about how to input from a user. The book I have doesn't go over it too in depth. I would like to prompt the user:
myfirst BYTE "Welcome! This program calculates the sum of a list of numbers.", 0dh, 0ah, 0dh, 0ah ; greeting
BYTE "How many integers will be added? : "
then the user will input X. How do I read what the user inputs and put it into a variable?
is it as simple as:
INVOKE ReadConsole, SomeVairable
Where SomeVairable is defined up in .data as a byte?
edit:
INCLUDE Irvine32.inc
BufSize = 80
.data
buffer BYTE BufSize DUP(?)
stdInHandle HANDLE ?
bytesRead DWORD ?
myfirst BYTE "Welcome! This program calculates the sum of a list of numbers.", 0dh, 0ah, 0dh, 0ah ; greeting
BYTE "How many integers will be added? : "
mysecond BYTE "Please enter the "
.code
main PROC
mov edx, OFFSET myfirst ;move the location of myfirst into edx
call WriteString
; Get handle to standard input
INVOKE GetStdHandle, STD_INPUT_HANDLE
mov stdInHandle,eax
; Wait for user input
INVOKE ReadConsole, stdInHandle, ADDR buffer,
BufSize, ADDR bytesRead, 0
exit
main ENDP
END main

No, it's not (at least usually) that simple.
What the user enters will be read as a string, not a number. You'll typically have to read the string (which will usually be more than one byte long), then convert it to an integer. You may want to verify that all the characters in the string are digits before you do the conversion, or you may want to combine conversion with verification.
Looking specifically at the ReadConsole call, there are two things to keep in mind. First, you need to retrieve a handle to the console, normally with GetStdHandle. Then, you need to supply ReadConsole with all of the half dozen or so parameters it expects.`

Related

Assembly - Readings strings with scanf in loop only reads one string

I need to read a bunch of strings from command line in assembly, however only one call to scanf seems to take place. I'm pretty sure the problem is related to the scanf format. If I replace what I've currently got with a simple "%s" it works fine, thing is I have to read whole lines including spaces, so "%s" won't do. "%[^c]s" should keep reading characters until it encounters c, but there's 2 problems with this:
I actually have to input the characters \ and n for the scanning to stop.
As I said, it only reads one string. After that, all the prompts for the remaining strings get instantly printed at the program ends.
I've seen that people usually suggest using fread, however I'm not really sure how to access stdin in assembly.
Here's my code:
bits 32
global start
extern exit, scanf, printf
import exit msvcrt.dll
import scanf msvcrt.dll
import printf msvcrt.dll
segment data use32 class=data
msg DB "Enter a value for n", 13, 10, 0
s_msg DB "Enter a string", 13, 10, 0
n_format DB "%d", 0
s_format DB "%[^\n]s", 0
segment bss use32 class=bss
n DD 0
s RESB 1000
segment code use32 class=code
start:
push dword msg
call [printf]
add ESP, 4 * 1
push dword n
push dword n_format
call [scanf]
add ESP, 4 * 2
mov ECX, [n]
read_strings:
pushad
push dword s_msg
call [printf]
add ESP, 4 * 1
push dword s
push dword s_format
call [scanf]
add ESP, 4 * 2
popad
loop read_strings
push dword 0
call [exit]

8086 ALP String Display

I have written a code for 8086 microprocessor for taking string from keyboard and displaying it as follows
Title Get the string from keyboard and display it
.model small
.stack 100h
.data
str1 db 'Enter String ','$'
str2 db 50 dup('$')
str3 db 0dh, 0ah, '$'
.code
main proc
mov ax,#data
mov ds,ax
mov ah,09h ; for displaying Enter String
lea dx,str1
int 21h
mov ah,0ah ; for taking i/p from keyboard
lea dx,str2
int 21h
mov ah,09h ; for displaying in new line
lea dx,str3
int 21h
mov ah,09h ; for displaying what you have entered
lea dx,str2+2
int 21h
int 21h
mov ah,4ch
int 21h
main endp
end main
I don't understand why we have to give effective address of the string as str+2 to print the inputted string back ? If simply lea dx, str2 is used no string is displayed.
Thanks in advance.
The first byte at STR2 should contain the maximum number of characters to read. The second byte should contain the number of characters already present. Because you initialized STR2 with 50 '$' characters and the ASCII value of '$' is 36 you effectively asked DOS to allow an input of 36 characters that are already there!
Better code str2 db 50,0,50 dup (0)
At the conclusion of this 'Buffered STDIN Input' the second byte will contain the number of characters that were read. I hope you see now why you need lea dx,str2+2. That's the address where the characters are.
Please note that with a first byte of 50 input is limited to 49 characters as DOS appends a terminating '$' character (Not included in the second byte).

Windows Assembly (x86) Read from Stdin and output to Stdout

I recently figured out how to write to stdout in assembly but am now having trouble reading from stdin, and outputting what I read back to stdout. This is the code I have so far:
.386
.model flat, stdcall
WriteFile PROTO STDCALL:DWORD, :PTR, :DWORD, :PTR DWORD, :PTR OVERLAPPED
ReadFile PROTO STDCALL:DWORD, :PTR, :DWORD, :PTR DWORD, :PTR OVERLAPPED
GetStdHandle PROTO STDCALL:DWORD
.data
.data?
input DW ?
input_size DD ?
read DD ?
.code
main:
INVOKE GetStdHandle, -10
INVOKE ReadFile, eax, OFFSET input, input_size, read, 0
INVOKE GetStdHandle, -11
INVOKE WriteFile, eax, OFFSET input, OFFSET input_size, read, 0
RET
END main
I'm pretty sure I'm reading it wrong. I am pretty sure that input_size and read are not behaving as expected (if I replace input_size with a number it displays a space number times) which is contributing to my problem (when I enter my input and hit return it simply displays nothing).
I have fumbled around with this for quite some time and would appreciate any help. (I am doing this just to learn this is not homework).
My question essentialy is what am I doing wrong?
You are allocating only two bytes for the input buffer:
input DW ?
Your input size is zero, causing ReadFile to read a maximum of 0 bytes:
input_size DD ?
nNumberOfBytesToRead should be passed as a value and not a pointer. And you want to write as many bytes as were input in the Readfile:
INVOKE WriteFile, eax, OFFSET input, OFFSET input_size, read, 0
INVOKE WriteFile, eax, OFFSET input, read, read, 0

Assembly and Win32API input output

I am trying to figure this out but am stumped a bit. What I am trying to do is to use the ReadConsole/WriteConsole functions from the win32 lib and got it to work a degree but just not there. I am having trouble getting the second write console working correctly. I don't think I am sending the buffer to the variable right. I must be missing something here and I dont know what it is.
Here is what I have so far
TITLE MASM Template (main.asm)
; Description:
;
; Revision date:
INCLUDE Irvine32.inc
BufSize = 80
.data
endl EQU <0dh,0ah> ; end of line sequence
;variable holders
firstN db ?
fNSize db ($-firstN)
;messages for getting input
fName LABEL BYTE
BYTE "Enter your first name", endl
fNameSize DWORD ($-fName)
;output handlers
consoleHandle HANDLE 0 ; handle to standard output device
bytesWritten DWORD ? ; number of bytes written
;input handlers
buffer BYTE BufSize DUP(?)
stdInHandle HANDLE ?
bytesRead DWORD ?
.code
main PROC
; Get the console output handle:
INVOKE GetStdHandle, STD_OUTPUT_HANDLE
mov consoleHandle,eax
; Write a string to the console:
INVOKE WriteConsole,
consoleHandle, ; console output handle
ADDR fName, ; string pointer
fNameSize, ; string length
ADDR bytesWritten, ; returns num bytes written
0 ; not used
; Get handle to standard input
INVOKE GetStdHandle, STD_INPUT_HANDLE
mov stdInHandle,eax
; Wait for user input
INVOKE ReadConsole, stdInHandle, ADDR buffer,
BufSize, ADDR bytesRead, 0
;cheack to see if read consol worked
mov esi, OFFSET buffer
mov ecx, bytesRead
mov ebx, TYPE buffer
call DumpMem
;move the input into the variable
mov firstN, TYPE buffer
; Write a string to the console:
INVOKE WriteConsole,
consoleHandle, ; console output handle
ADDR firstN, ; string pointer
fNSize, ; string length
ADDR bytesWritten, ; returns num bytes written
0 ; not used
INVOKE ExitProcess,0
main ENDP
END main
Thanks for any help :)
firstN and fNSize are each a single byte and that's not what you want. Simply do this for the second WriteConsole call:
INVOKE WriteConsole,
consoleHandle, ; console output handle
ADDR buffer, ; string pointer
bytesRead, ; string length
ADDR bytesWritten, ; returns num bytes written
0 ; not used

MASM32 Assembly - Reading a number from Console

Sorry if this question is really simple, but I tried all that I know and coudn't figure it out.
I'm trying to make a simple procedure which takes a string and a Count from the console and print the string number of times specified by the Count.
Everything is fine, but when I mov the Count to eax for a loop, the value get's messed up and I end up with an infinite loop of print.
I tried to change the Count to DWORD with atodw, but didn't work.
here's the code :
PrintString PROTO :DWORD, :DWORD
.data
String db 100 DUP(0)
Count db 10 DUP(0)
.code
start:
;1- get user input
invoke StdIn, addr String, 99
invoke StdIn, addr Count, 10
;2- Remove the CRLF from count
invoke StripLF, addr Count
;3- Convert the count to DWORD
invoke atodw, addr InputCount
mov Counter, eax
;4- Call the Printer function
invoke Printer, addr String, addr Count
Printer PROC StringToPrint:DWORD, count:DWORD
mov eax,count ;;;;;; This is the problem I think
Looppp:
push eax
invoke StdOut, StringToPrint
pop eax
dec eax
jnz Looppp
ret
Printer endp
You’re passing addr Count – the address of the string – as the second argument to Printer. But it expects an integer, so you want to pass Counter instead.
Since you’re using a language without type checking, adopting a naming convention such as Hungarian notation for your identifiers could help you see and avoid this kind of problem. With the variables here named strCount and dwCount, for example, it would be more obvious that you were using the wrong one.
As an aside, eax must eventually reach zero so your printing loop won’t be infinite – just rather longer than you intended…

Resources