ASSEMBLY LANGUAGE - WEEK VI					November 30, 1986



PLANNING A GUESS NUMBER GAME

One of the major differences between Assembly Language and Basic is that assembly language demands some clear plan of what you intend to do. You must first define your program, break each step of the program down into a manageable routine, and then code each routine. When you break your main program down into manageable routines, you can try each routine before it is included in the main program.

In BASIC, you can start writing your program, try it, and then figure out why it doesn't work. This type of approach is not productive in assembly language. It is difficult to move from source code to object code, and it is more difficult to place check-points in the program to indicate what is going on. Let's use a "GUESS NUMBER GAME" to illustrate how one would approach an assembly programming problem.



I. Define the program: We want to write a program that compares a number we type in against a number that the computer has created. The program will tell us if our guess is higher or lower than the "created" number and allow us to guess again. When we guess the correct number, the computer tells us the guess is correct, and ends the game.



II. A diagram of this program would look like this:


          _________________________________________
          |                                       |
          |  Print Introduction and Instructions  |
          |_______________________________________|
                              ||
                              ||
          ____________________||____________________
         |                                        |
         |            Get Random Number           |
         |________________________________________|
                             ||
                             ||
                             ||
                _____________||_____________
                |                          |
    ------------| Get Number from Keyboard |------------
    |           |__________________________|           |
    |                        ||                        |
    |                        ||                        |
    |          ______________||_____________           |
    |          |                           |           |
    |          |        Compare Number     |           |
    |          |___________________________|           |
    |             |          |           |             |
    |             |<         |=          |>            |
 ___|_____________|_  _______|_______  __|_____________|____
 |                 |  |	           |  | 	              |
 |  If guess	    |  |	Print      |  | 	If guess      |
 |  less than      |  |	correct	 |  |	greater than  |
 |  computer no.   |  |	guess      |  |     computer no.  |
 |  go get         |  |  "you win"  |  |     go get        |
 |  another no.    |  |             |  |     another no.   |
 |_________________|  |_____________|  |___________________|
                            ||
                            ||
                        ____||____
                        |        |
                        |  END   |
                        |________|




III. Let's describe each of these routines separately. 
     

a. Create a random number. - Lesson VII - We know from our experience that it is possible to get a random number from the computer. The routine uses the refresh register which is continuously counting from 0 to 127. At any moment that we read the refresh register, we will see a number in that range. 

     

b. Get a number. - Lesson VI - We have been able to read "characters" from the keyboard and print them to the screen or store them in memory. However, these characters do not represent any number or quantity to the computer. We have to convert a string of numeric characters to a numeric equivalent which has meaning to the computer.

     

c. Compare numbers. - Lesson VIII - We have to numbers or values and we have to determine which is larger or if they are equal. The result of the comparison will determine where we go next in our program.

     

d. General input and output...We have developed routines that allow us to read the keyboard and display messages to the screen. We will use these in our program.




Let's look more closely at converting a string of characters into a value that is meaningful to the computer. We can break our routine down even more...

           a. Read character from keyboard

           b. Is it < 0 (ASCII CODE LESS THAN 30H)

           c. It it > 9 (ASCII CODE GREATER THAN 39H)

           d. Convert character to binary equivalent

           e. Do this N times.


Now we must decide what the upper limit on our number guess is going to be. If we use a binary number, our 16-bit word in the computer limits our guess to 65535. We could set that limit, but let's use a limit of 999. There is another numeric conversion that can be used by the computer called Binary Coded Decimal. We will not discuss this here.




Number conversion is a two way street. We also have to have a way of converting a number that is coded in binary to a series of ASCII characters that can be displayed on the screen.
 
           a. Take binary number
 
           b. Convert to a string of ASCII characters
 
           c. Display string




We can write these subroutines, assemble them, and then check them out using DEBUG.




ASCII DECIMAL TO BINARY CONVERSION.


Let's think for a minute about what is happening when we enter a string of numbers in the keyboard. If we were going to enter say, 367 in the keyboard, we know that we mean three hundred sixty seven. However, a person watching the screen doesn't know what we mean as we enter the number. The first number entered, 3, means "three" until we enter the second number, 6. The 36 can be expressed as 3*10 + 6. The third number, 7, makes the number 367. We can take the previous number, 36, multiply it by 10 and add the third number to it to make three hundred sixty seven.

We can see from this it is possible to write a routine to let the computer do this work for us.

Recall:
The ROM routines OUTC at 0033H and CHKIO at 002BH use the AF and the DE register. If we put the maximum number of characters we are going to allow in the B register, we can use the DJNZ operand to stay in a loop until the maximum number of characters has been entered. We want to keep the number we have already added handy. The index register IX is not used by the ROM routines we are interested in, so we will use that to store the binary number. We need to save the final binary number in memory so that we can recall it later. While we are checking out this routine, we want to store the number characters we have entered, so we can compare the decimal value of the numbers we have entered against the binary conversion. We will load the HL register with the memory location where we will store the string of digits we enter.

We can now write a detailed outline of the routine before we code it:

1. Setup:
Put the location of the character storage in HL
Put the maximum number of digits to get in B
Clear the IX register by putting zero in it.
Gingerbread:
Clear the screen
Place a question mark on the screen to prompt the user that we are waiting for input.

2. Getdig:
Get a character
For our purposes, display the character 
If the character is a carriage return, quit.
Recall that the character as entered is stored in the memory or in a register as an ASCII character. Which means that the digits 0 to 9 are represented as 30H to 39H. We first have to strip off the 30H to get a hexadecimal number from 0H to 9H.
If we subtract 30H from our digit and get a negative value, we know our character entered is an ASCII character less than "0". We do not want to use that character and just go get another character.
If we compare the character we entered against "10" and get a positive value, we know that character is greater than 9 - another illegal character which we want to ignore.
Now we have to set up our routine to take our previous number we entered, multiply that number by 10 and add the digit we just entered to that result. The Z-80 doesn't have a MULTiply function in it. All our multiplication has to be accomplished by a series of additions. A number added to itself is equivalent to multiplying by 2. IF we add that result to itself, we have essentially multiplied by 4. If we add that result to itself we have multiplied by 8. Unfortunately, we have to multiply by 10, which is not an even set of additions. However, if we save our *2 number, and add it to our *8 number, we get a *10 number.
Now we have to add the digit we entered to the *10 number.j
We also want to store the digit we entered in the memory location pointed to by the address in HL. After we have stored a digit, we have to move the pointer to the next memory location.
Now we want to decrement our counter, and if we are not at our limit, go get another digit. We can do all of this will one instruction if our count is in the B register. That instruction is DJNZ.
If we have entered our maximum number of digits allowed, or if a carriage return was entered, we want to exit the program. Before we leave, though, we want to store our binary number in memory.
For now, we can then jump to DOS, or to DEBUG. If we want to jump to DEBUG, we must first have loaded DEBUG from the disk.

The source code for this routine is listed on the attached sheet.

If we had a binary number in memory, and wanted to display it on the screen we would have to convert it to an ASCII equivalent:

1. Divide the binary data by 10.
2. Save the quotient of the divide for the next divide.
3. Add 30H to the remainder to produce an ASCII 0 through 9.
4. Store the ASCII character in the next RIGHTMOST character position in a buffer.
5. Repeat steps 1 through 4 until the quotient is zero.

                                                                                                                                                                                                   