Input/Output in Assembler
There are no native
assembler I/O commands in the current Windows environment. In the DOS
environment, strings could be printed directly to the screen or even to the
printer. However, since all I/O is done in character form, even in DOS numbers
had to be converted to character to be printed, and converted from character to
integer when read in to be used in arithmetic. We are using an I/O package from
Detmer's other book (with permission). The I/O package
uses C commands atod (ASCII to decimal) and dtoa (decimal to ASCII), as well as two functions
that are probably Detmer-written: input and output.
Printing a Decimal Value
A decimal value must be converted to a character string to be output. We will use the C function dtoa (decimal to ASCII) to convert an integer value to a string. We will print the resulting string using the output command.
The dtoa function has two operands; the first is a storage location in memory set up as a string of bytes, and the second is a register or variable that holds an integer. In the display, val_str is a memory location of 11 bytes, uninitialized, followed by a hex 0 to terminate the string:
val_str byte 11 dup(?),0
(Since the string will be printed with the output command, it must be null-terminated. The null byte is actually stored as a hex 0.) The string is 11 bytes to provide for the longest integer we might print; if the number is shorter, we end up with a lot of leading blanks, but we can't shorten this string.
The output command will print any 0-terminated string to the screen. We might output a prompt, a message, or an integer converted to a string.
Here is an example that converts the value of the variable val to a string and prints that string using output:
val_str byte 11 dup(?),0
val dword 17
...
dtoa val_str,val
output val_str
Converting a Statement that Prints to cout
If the assignment says to do this:
cout << "ans =" << ans << " num =" << num << endl;
then you have 5 items to print.
The items that look like "ans =" should be set up as strings; that is, an array of bytes, null-terminated. (The null byte is actually a hex 0.) Here is an example:
ansis byte "ans = ",0
The items that are variables must be converted to strings (using dtoa) before printing. The example I gave you earlier showed you how to set up a memory location to hold the converted value and to combine it with the message string (like ansis) to print it. I also showed you how to set up a memory location to hold the converted value that can be printed separately.
The memory location that holds the converted value must also be a string (strings have type byte--you can use db), and the book uses 11 bytes (probably too many), also 0-terminated. Here is an example:
ansch byte 11 dup(?)
byte 0
This sets up a 12-byte string, the first 11 uninitialized, the last containing a hex 0.
A newline can be attached to a string or printed separately. I showed you how to declare it so that it can be printed separately, since you need to go to a new line only after printing several values, not after each one.
To set up a newline to print separately, do this:
newline
byte 13,10,0 ; carriage return, line feed,
0-termination
To attach a newline to a string, put the 13, 10 either before or after the string itself, as shown in this example (both before and after):
myname byte 13,10,"Jones",13,10,0
Let's put it all together to translate this line: cout << "ans = "<< ans <<endl;
ans dword 17
ansis byte
"ans = ",0
ansch byte
11 dup(?)
byte 0
newline byte 13,10,0
...
; cout << "ans = " << ans << endl;
output ansis ; print
ansis
dtoa ansch,ans ;
convert ans to character
output
ansch ;
print ans
output
newline ; print newline
Note that the second operand of dtoa can be a register or a variable
Reading in an Integer
Since input is also done in character form, we are going to use another C function (atod) to do input.
You will write a prompt to the screen, using output. Here is the prompt and the command to print it:
prompt1 byte "Enter first number: ", 0
...
output prompt
To read in characters from the keyboard, you use the input command. The command reads characters until you press <Enter>. It fails if you enter anything but digits or a minus sign.
The input command takes one operand, which is the name of a storage location in memory designated to hold a string. Here is an example, showing the declaration of the string and the input command that reads into the string.
string byte 40 dup (?)
...
input string, 40 ; read ASCII characters
The example reserves 40 bytes for the value typed in, which would allow a huge number; it is probably too large, but it doesn't matter. The variable string doesn't need to be 0-terminated because we aren't printing it.
Once the string has been read in, we use atod to convert the value in string to an integer and put it in eax. From eax, we can store it in memory or use it in arithmetic, etc. The operand eax is implicit (that is, we don't write it out as an operand). This is shown below.
number dword ?
. . .
atod
string ; convert string
to integer in eax
mov number, eax ; store value from eax
in number in memory
This example puts it all together:
prompt byte "Enter first number: ", 0
string byte 40 dup (?)
number dword ?
...
output prompt
input string, 40 ; read ASCII characters
atod string ; convert to integer
mov number, eax ; store in memory