News:

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

How to get user input

Started by Elvenmonk, November 18, 2011, 05:37:01 AM

Previous topic - Next topic

Elvenmonk

Hi I'm currently in an assembly class and before we were using inline MASM assembly in Visual Studios with C/C++. However, our professor recently made it so we can't use Visual Studios anymore for input and output. I've gotten output to work I just can't figure out how to do input.

hutch--

This is how to do Standard Input using the Windows API functions.


; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

    .386
    .model flat, stdcall
    option casemap :none   ; case sensitive

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

    .code

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

StdIn proc lpszBuffer:DWORD,bLen:DWORD

    LOCAL hInput :DWORD
    LOCAL bRead  :DWORD

    invoke GetStdHandle,STD_INPUT_HANDLE
    mov hInput, eax

    invoke SetConsoleMode,hInput,ENABLE_LINE_INPUT or \
                                 ENABLE_ECHO_INPUT or \
                                 ENABLE_PROCESSED_INPUT

    invoke ReadFile,hInput,lpszBuffer,bLen,ADDR bRead,NULL

  ; -------------------------------
  ; strip the CR LF from the result
  ; -------------------------------
    mov edx, lpszBuffer
    sub edx, 1
  @@:
    add edx, 1
    cmp BYTE PTR [edx], 0
    je @F
    cmp BYTE PTR [edx], 13
    jne @B
    mov BYTE PTR [edx], 0
  @@:

    mov eax, bRead
    sub eax, 2

    ret

StdIn endp

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

dedndave

hi Elvan
start by installing the masm32 package
read the installation page, then install it   :U
from there, you can learn basics from the library and examples

here is the code from stdin.asm....
; #########################################################################

   .386
   .model flat, stdcall
   option casemap :none   ; case sensitive

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

   .code

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

StdIn proc lpszBuffer:DWORD,bLen:DWORD

   LOCAL hInput :DWORD
   LOCAL bRead  :DWORD

   invoke GetStdHandle,STD_INPUT_HANDLE
   mov hInput, eax

   invoke SetConsoleMode,hInput,ENABLE_LINE_INPUT or \
                                ENABLE_ECHO_INPUT or \
                                ENABLE_PROCESSED_INPUT

   invoke ReadFile,hInput,lpszBuffer,bLen,ADDR bRead,NULL

   mov eax, bRead

   ret

StdIn endp

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

end


as you can see, it is treated as a file stream

Elvenmonk

I tried to run the first code and I got these errors:
(17) error A2006:undefined symbol : STD_INPUT_HANDLE
(17) error A2114: INVOKE argument type mismatch : argument : 1
(20) error A2006: undefined symbol : ENABLE_LINE_INPUT
(20) error A2114: INVOKE argument type mismatch : argument : 2
(24) error A2006:undefined symbol : NULL
(24) error A2114: INVOKE argument type mismatch : argument : 5
(46) error A2088 END directive required at end of file

Also, I don't know how different the MASM y'all have here is but we're to use the ml.exe and linker.exe from VS 2010. Since that's what my TA and prof will be using the grade my work I can't install or change anything.
Along with this, I don't really understand much of what is being done. My professor does a bad job of explaining assembly. All I understand is basic commands, I guess is the word, like: jmp,mov,sub,add,jne,jg, and etc.

And the second code you gave me I got these errors too.

NoCforMe

Undefined symbol errors mean, well, that the symbol (STD_INPUT_HANDLE in this case) isn't defined, which usually means that a file which contains the definition isn't being INCLUDEDd or can't be found.

Probably best for you to do a full installation of MASM32, which will put itself in the root of the drive you select. Your (newer) versions of ML and link.exe should work (that's what MASM32 is based on, and the current versions are 6.14 for the assembler and 5.12 for the linker.

Check your file PATHs to make sure the assembler and linker can "see" the required files.

Elvenmonk

Well, what exactly does it need to see? If it's those included files then I have them set to their path on my computer.

MichaelW

The %PATH% environment variable specifies the search path for executables. Since the MASM32 package is designed to not depend on environment settings, IMO you should specify the full path for everything. That way you don't have to set up a workable environment, or otherwise have to worry about the existing environment causing the system or the tools to use an executable, include file, or library that you did not intend.

But the system, ML, and the linker can use the environment settings, and you can take advantage of this by setting up a copy of the environment with the necessary settings.

Test.asm:

;==============================================================================
    .486                       ; create 32 bit code
    .model flat, stdcall       ; 32 bit memory model
    option casemap :none       ; case sensitive

    include windows.inc
    include kernel32.inc
    includelib kernel32.lib
    include masm32.inc
    includelib masm32.lib
    include msvcrt.inc
    includelib msvcrt.lib

    include d:\masm32\macros\macros.asm
;==============================================================================

printf MACRO format:REQ, args:VARARG
    IFNB <args>
        invoke crt_printf, cfm$(format), args
    ELSE
        invoke crt_printf, cfm$(format)
    ENDIF
    EXITM <>
ENDM

;==============================================================================
    .data
        rect RECT <0,1,2,3>
    .code
;==============================================================================

testrc proc rc:RECT
    printf( "%d\t%d\t%d\t%d\n\n", rc.left, rc.top, rc.right, rc.bottom )
    ret
testrc endp

;==============================================================================
start:
;==============================================================================

    invoke testrc, rect

    inkey "Press any key to exit..."
    exit

;==============================================================================
end start

The batch file:

set file="test"
set path=d:\masm32\bin
set include=d:\masm32\include
set lib=d:\masm32\lib
ML /c /coff %file%.asm
pause
Link /SUBSYSTEM:CONSOLE %file%.obj
pause


eschew obfuscation

dedndave

what you are missing is the windows.inc include file, et al
that is where many of those symbols are defined
the simplest way to start a program is to use one include file that adds several others
        INCLUDE \masm32\include\masm32rt.inc

take a look at that file with notepad - it will show you all the typing it saves you   :P

dedndave

here is a little test program.....

Elvenmonk

Sorry for taking so long to reply, busy with school and work.
Well, I found out how our prof. wants us to use it, but he didn't explain how to implement it. I know we have to do: call scanf.
However I don't know how to use it honestly. Here is what I was trying. I asked him after class and he said if I installed the MASM like y'all we reccomendng I would've gotten a 0 because then the TA or him wouldn't have had itso the program would not run.

the bat file is what our prof told to use when compiling it.

Dedndave trying your code right now.

I ran you code without installing the MASM32 sdk and it didn't work. Then when I installed it I got this error:
Assembling: StdInTst.asm
\masm32\include\windows.inc(10938) : error A2191:cannot include structure in sel
f

MichaelW

#10
I modified your source and batch file so they do not depend on any MASM32 components other than ML and link, and obviously so they would work on my system, so you will need to correct the paths in the batch file.

; TITLE simple ML.exe test program assembled on @date at @time
;.MODEL FLAT,STDCALL

.486                  ; create 32 bit code, must precede model directive
.model flat, stdcall  ; 32 bit memory model
option casemap :none  ; case sensitive

;include C:\Users\Elvenmonk\Documents\programs\asm\msvcrt.inc
;include C:\Users\Elvenmonk\Documents\programs\asm\kernel32.inc
;includelib "C:\Program Files\Microsoft SDKs\Windows\v7.0A\Lib\kernel32.lib"
;includelib "C:\Program Files\Microsoft Visual Studio 10.0\VC\lib\msvcrt.lib"
;includelib "C:\Program Files\Microsoft Visual Studio 10.0\VC\lib\libcmt.lib"

; These prototypes make it possible to call the
; functions with invoke, but the push and call
; method will work just as well.

printf PROTO C :VARARG
scanf PROTO C :VARARG

.LISTMACROALL

;PRINTF MACRO string
;   IFB <string>
;   ECHO ***ERROR*** in macro PRINTF: String is empty
;   ;********
;   ;******
;   ;ECHO ***ERROR*** in macro PRINTF: String is empty
;   ;*****
;   ;********
;   ELSE
;     invoke printf, ADDR string
;   ENDIF
;ENDM

;SCANF  MACRO

;ENDM

.data
;hello  DB "Hello world!",10,0
;date   DB "Nothing",10,0
;charrar  DB "%s",0

xxx  dd 0
yyy  db 20 dup(0)

fmt1 db "%d",0
fmt2 db "%d%c",0
fmt3 db "%s",0
fmt4 db "%s%c",0

.code
main:

    ;PRINTF
    ;PRINTF hello
    ;PRINTF date
    ;SCANF
    ;mov dword [esp],charrar
    ;call scanf
    ;PRINTF [esp]

    invoke scanf, ADDR fmt1, ADDR xxx
    invoke printf, ADDR fmt2, xxx, 10

    invoke scanf, ADDR fmt3, ADDR xxx
    invoke printf, ADDR fmt4, ADDR xxx, 10

    ret
end  main


rem
rem  run assembler
rem

set file="test"
set path=D:\masm32\bin
set lib=C:\Program Files\Microsoft Visual C++ Toolkit 2003\lib

:echo on
del %file%.obj
del %file%.exe
del %file%.lst
del %file%.sbr
ml /c /coff /Cp /Fl /Fr  %file%.asm
pause
link %file%.obj /DEFAULTLIB:libcmt /SUBSYSTEM:CONSOLE /ENTRY:mainCRTStartup
pause
:echo off
:rem
echo.
test
pause


http://msdn.microsoft.com/en-us/library/9y6s16x1(v=vs.71).aspx

Edit: For some reason I was assuming that you wanted to input an integer. I have now modified the source to accept an integer and a string.
eschew obfuscation

Elvenmonk

The batch file wasn't mine, it was what my prof said would be used for running our code. Trying out the code now. Also, SCANF and PRINTF are supposed to be macros in our assignment.

Actually, thank you very much. Sorry for sounding so negative, but I'm just stressed due to this work. But, thank you MichaelW.You taught me a bit and how to use this. I was so focused on call scanf (as that's what a few other students were using) I didn't bother to look into invoke scanf.

And yes it worked,as an FYI. Thank you very much.
Assembly seems like such a nice(not in the friendly way) language I just wish I had some helpful readings for learning assembly.

MichaelW

Printf and scanf require a format string, so in your macros you can specify the first macro argument as REQ, and the second as VARARG. When you invoke the function within the macro you can just pass the second macro argument (IFNB) as a single argument, regardless of how many arguments it actually represents.

http://webster.cs.ucr.edu/Page_TechDocs/MASMDoc/ProgrammersGuide/Chap_09.htm
eschew obfuscation

dedndave

QuoteAlso, SCANF and PRINTF are supposed to be macros in our assignment.

these are functions in the msvcrt (microsoft visual c runtime) library:

http://msdn.microsoft.com/en-us/library/9y6s16x1.aspx
http://msdn.microsoft.com/en-us/library/6ttkkkhh.aspx
http://msdn.microsoft.com/en-us/library/xdb9w69d.aspx

http://msdn.microsoft.com/en-us/library/wc7014hz.aspx
http://msdn.microsoft.com/en-us/library/hf4y5e3w.aspx
http://msdn.microsoft.com/en-us/library/25366k66.aspx

QuoteI was so focused on call scanf (as that's what a few other students were using) I didn't bother to look into invoke scanf.
QuoteAlso, SCANF and PRINTF are supposed to be macros in our assignment.

macros are neither CALL'ed, nor INVOKE'd
however, macros may use those constructs inside them
for the sake of comparison, we have a macro in the masm32 package called "print"
it may be used in a number of ways, but a couple simple forms may look something like this
        print   offset szString
        print   chr$(13,10)


INVOKE is actually a macro, defined internally by the assembler
        INVOKE  SomeFunction,Parm1,Parm2
the assembler actually generates code that looks like this
        push    Parm2
        push    Parm1
        call    SomeFunction


QuoteHowever, our professor recently made it so we can't use Visual Studios anymore for input and output.

i am a little confused as to what the assignment requires, here   :P
it sounds to me as though he wants you to write printf and scanf macros that use the API functions
API functions for standard console output and input are part of the OS
generally, we use WriteFile and ReadFile functions to perform these operations, however there are other ways
those 2 API functions are part of kernel32

if you want a good grade...
1) find out exactly what your instructor expects
2) make your setup match his

MichaelW

The provided batch file specifies /DEFAULTLIB:libcmt, so I'm fairly certain that the macros were supposed to use the scanf and printf functions from the specified library, although I don't understand why a static library that supports multithreaded apps, for something like this.

I'm not sure that the use of invoke will be acceptable, but handling a VARARG function in a VARARG macro with the push call method would be somewhat difficult for a beginner, given the need to push the arguments in reverse order.
eschew obfuscation