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.
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
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
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
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.
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.
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.
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
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
here is a little test program.....
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
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.
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.
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
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
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.
This is what the instructions are. I was working on STDIN macro when I came here.
Design and implement macros to do the following:
•Convert a signed BCD integer to a signed integer, allowing the programmer to determine the length of the resulting binary number (32, 16 or 8 bit). Remember that you need to handle BCD strings that are too large (or small) to convert successfully.
•Convert a signed integer (32, 16 or 8 bit) to a signed BCD integer suitable for printing.
•Print a string to STDOUT using the Standard C Library
•Read a string from STDIN using the Standard C Library
Before we were using inline assembly(with visual studios) for all I/O and variable declarations ( something else I'm still not 100% on in assembly)
currently reading all the docs you guys provided right now.
that doesn't look too bad :P
it looks like he wants you to incorporate printf and scanf into macros
however, he didn't say that the macros had to accomodate the full functionality of those functions
he seems to be misusing the term "BCD strings" - i think he means ASCII strings (e.g. "suitable for printing")
Quote from: dedndave on November 21, 2011, 01:02:10 AMhe seems to be misusing the term "BCD strings" - i think he means ASCII strings (e.g. "suitable for printing")
however, MASM can encode BCD numbers (->TBYTE).
The most recent description seems to use "BCD integer" and "BCD string" interchangeably, so I'm assuming that a BCD string is what I would call a decimal string. The description does not mention scanf or printf, and apparently you are not to use these or other CRT functions to do the integer to/from decimal string conversions. I think the intended CRT functions may be _cgets (http://msdn.microsoft.com/en-us/library/3197776x(v=VS.71).aspx) and _cputs (http://msdn.microsoft.com/en-us/library/3w2s47z0(v=VS.71).aspx).
cgets and cputs?
As for the BCD we're supposed to read in 15chars of numbers plus a sign then remove the "3"s so like 12 would be "3132" and cut it down to "12".
Also, Michael when using your code I ran into an error. Whenever I would type in a string higher then 4 chars it would cut off the first 4 characters.
Edit, nevermind? It's odd when I typed it out, like you had it I was getting print errors. So I then copy your code and it worked 100%. So, I then compared it line by line with what I typed, but it was 100% exactly has you had typed. I have no idea why it was wigging out. Thank you so much.
cgets - i'd use _cgets_s
Gets a character string from the console.
http://msdn.microsoft.com/en-us/library/tz00x758.aspx
although, you can use the simpler version _cgets
http://msdn.microsoft.com/en-us/library/3197776x.aspx
_cputs
Puts a string to the console.
http://msdn.microsoft.com/en-us/library/3w2s47z0.aspx
wrap them in macros and that part is done
the "hard" part is base conversion, which isn't all that hard
there are a few special cases to watch for...
8-bit signed values range from -128 to +127
16-bit signed values range from -32768 to +32767
32-bit signed values range from -2147483648 to +2147483647
so, except for the values -128, -32768, and -2147483648, you can NEGate negative values and convert them as positive
those values are special because they cannot be negated without overflow
in hex, they are 80h, 8000h, and 80000000h, respectively
also...
you can use the CBW, CWD, CWDE, CDQ instructions to extend signed values in size
http://www.arl.wustl.edu/~lockwood/class/cs306/books/artofasm/Chapter_6/CH06-1.html#HEADING1-226
this type of method may allow you to share the same code for conversions of all the required sizes