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