Assembly Language Character I/O


This tutorial is intended to follow the tutorial on assembly language branching.

The IJVM instruction set includes two instructions to provide character input and output:  IN and OUT, respectively. The IN instruction reads the first character from the input buffer, converts it to an unsigned integer value (the low-order 8-bits store the character value), and pushes it onto the stack. If there is nothing in the input buffer then a value of zero is pushed onto the stack. The OUT instruction pops the top element from the stack, extracts the low-order byte, and writes that byte to the input/output window as character data.

 1. Clear the memory of the computer (Memory menu; Clear Memory).

 2. If necessary, clear the source code editor (Source menu, Clear Source Code).

 3. Enter the following assembly language program using the source code editor. This program displays a menu with two options ("Uppercase" and "Lowercase"), displays a prompt for input, and waits for the user to enter a single character response. If the user types 'u' or 'U' then the text "IJVM" will be sent to the input/output window. If the user types 'l' or 'L' then the text "ijvm" will be sent to the input/output window. Otherwise, the text "ERROR" will be displayed.

Note: This is a long program but it is highly repetitive so make good use of copy and paste.

.constant
    NEWLINE 10
.end-constant

.main
    .var
        option
    .end-var

// Display the menu and user prompt

    bipush 'U'
    out
    bipush 'p'
    out
    bipush 'p'
    out
    bipush 'e'
    out
    bipush 'r'
    out
    bipush 'c'
    out
    bipush 'a'
    out
    bipush 's'
    out
    bipush 'e'
    out
    ldc_w NEWLINE
    out
    bipush 'L'
    out
    bipush 'o'
    out
    bipush 'w'
    out
    bipush 'e'
    out
    bipush 'r'
    out
    bipush 'c'
    out
    bipush 'a'
    out
    bipush 's'
    out
    bipush 'e'
    out
    ldc_w NEWLINE
    out
    ldc_w NEWLINE
    out
    bipush 'C'
    out
    bipush 'h'
    out
    bipush 'o'
    out
    bipush 'i'
    out
    bipush 'c'
    out
    bipush 'e'
    out
    bipush '('
    out
    bipush 'U'
    out
    bipush ' '
    out
    bipush 'o'
    out
    bipush 'r'
    out
    bipush ' '
    out
    bipush 'L'
    out
    bipush ')'
    out
    bipush '?'
    out
    bipush ' '
    out

// Get a keystroke from the user

top:
    in               // Push character (or zero) onto the stack
    dup              // Duplicate the character value on the stack
    ifeq clear       // If character = 0 then branch to clear
    goto end         // Otherwise, branch to the end of loop
clear:
    pop              // Clear the stack
    goto top         // Branch back to the top of the loop
end:
	istore option

// Echo the user's keystroke to the output window

    iload option
    out
    ldc_w NEWLINE
    out

// Perform the indicated operation

    iload option         // if (option == 'u') goto uppercase
    bipush 'u'
    if_icmpeq uppercase

    iload option         // else if (option == 'U') goto uppercase 
    bipush 'U'
    if_icmpeq uppercase

    iload option         // else if (option == 'l') goto lowercase
    bipush 'l'
    if_icmpeq lowercase

    iload option         // else if (option == 'L') goto lowercase
    bipush 'L'
    if_icmpeq lowercase

    err                  // else error

uppercase:
    bipush 'I'
    out
    bipush 'J'
    out
    bipush 'V'
    out
    bipush 'M'
    out
    goto halt

lowercase:
    bipush 'i'
    out
    bipush 'j'
    out
    bipush 'v'
    out
    bipush 'm'
    out

halt:
    halt
.end-main

 4. Assemble the program (tap the F2 function key). If you do not want to save this program, just click the Cancel button in the file save dialog; the machine language code will still be loaded into memory.

 5. Check the Single-Step through IJVM Code checkbox below the input/output window.

 6. Click the Reset button.

 7. Click the Display Words button below the memory display.

 8. Click the IJVM Step button two (2) times to allow the machine language interpreter to perform its start-up routine.

Note: Be very careful as you complete the steps below. It is easy to get out of sync with the instructions.

Display the Menu and User Prompt

 9. The first 74 statements display the menu and the user prompt. You could single-step through these instructions, but there may be a better way. Make sure that the checkboxes that disable animation are unchecked. We want to slow the simulator down. What you want to do is click the Run button and then click the Break button (its the same button with a different label) when this section of code has almost been executed. I suggest you click the Break button when you see the prompt being displayed in the input/output window. Then, click the IJVM Step button until you have executed the final OUT instruction: "113:  OUT". The last character sent to the input/window is the blank space that follows the '?' and separates the prompt from the user's response. The input/output window looks like this:

Get a Keystroke from the User

 10. This section of code begins with a loop that waits until the user has entered a keystroke. The keystroke entered by the user will be stored in the variable "option". Click the Goto SP button and confirm that the top of the stack is at 4096. (The 32 at address 4097 is the character code for the blank space that was just sent to the input/output window.)

 11. Click the IJVM Step button. Since the input buffer is empty, IN pushes a value of 0 onto the stack:

 12. Click the IJVM Step button. This value is duplicated on the stack.

 13. Click the IJVM Step button. The IFEQ instruction has just been executed. Since the Z flag is 1, the branch to address 122 succeeds (the next instruction is "122:  POP"). The value originally returned by IN is, once again, on the top of the stack:

 14. Click the IJVM Step button. The POP instruction removes the value returned by the previous IN instruction in preparation for going back to the top of the loop.

 15. Click the IJVM Step button. The unconditional branch takes us back up to the top of the loop at byte-address 114.

 16. Click anywhere in the input/output window. The input/output window is implemented as a JTextArea and it must have the focus in order to receive input. Clicking anywhere within the window gives it the focus.

 17. Type the letter 'u' on the keyboard.

 18. Click the IJVM Step button. The character code for 'u' is pushed onto the stack by the IN instruction:

 19. Click the IJVM Step button. This character code is duplicated on the stack:

 20. Click the IJVM Step button. Since the Z flag is 0, the IFEQ branch to 122 fails (the next instruction is "119:  GOTO 126"). The code originally returned by IN is, once again, on top of the stack:

 21. Click the IJVM Step button. The unconditional GOTO takes us out of the loop.

 22. Click the IJVM Step button. The keystroke entered by the user is popped from the stack (SP is back to 4096) and copied to the variable "option" (offset 0 from LV):

Echo the User's Keystroke to the Output Window

 23. Click the IJVM Step button four (4) times. These four instructions output the keystroke entered by the user and a new-line character:

Perform the Indicated Operation

 24. Click the IJVM Step button. The option selected by the user is pushed onto the stack:

 25. Click the IJVM Step button. The code for 'u' is pushed onto the stack:

 26. Click the IJVM Step button. The top two values are popped from the stack and compared (the difference is calculated in the ALU). Since the top two values were equal, the IF_ICMPEQ branch to 164 succeeds (the next instruction is "164:  BIPUSH 73"). If you look, you will notice that the branch succeeded even though Z is not equal to 1. Actually, Z was 1 but the machine language interpreter has already begun the  process of reading the next byte from the program by incrementing the PC register. See the section on single-stepping through a machine language program in the overview for more details.

 27. Click the IJVM Step button until the program terminates (i.e., until the HALT instruction is executed). The uppercase letters "IJVM" are sent to the input/output window:

 28. Rerun the program (Click Reset and then Run) several times with different keystrokes until you are convinced that the program works correctly. When you click the Run button, the input/output window automatically gets the focus and it should not be necessary to click on the window before entering your keystroke (unless, of course you have clicked on some other interface component first).

The next tutorial covers assembly language methods.