Comparing and Conditions

"Shall I compare thee to a summer's day?" - William Shakespeare, 'Sonnets'

by Ciaran McCreesh
Created: 24th October 1999
Last Modified: 27th November 1999

This page explains how to compare values and use conditional jumps.

Comparing - The CP Instruction

The CP instruction stands for compare. It takes the general form cp ValueToCompareWith and compares the value of the a register with ValueToCompareWith, which can be any 8 bit register, an 8 bit number or (hl). So:

  cp 7
  cp b
  cp e
  cp (hl)
  cp %11010111

and so on. What the CP instruction actually does is substracts ValueToCompareWith from the value of the a register, but it doesn't store the result anywhere or affect the value of either the a register or ValueToCompareWith. What it does do is affect the flags.

Flags - The f Register

The f register is sometimes called the flag register. It can't be used in maths, logic or any other 'useful' instruction (it can be pushed and popped from the stack when paired with a to give the af register pair). However, many instructions affect the value of f. Most of the bits in f have a meaning, for example one of the bits is set if there has been a carry and reset if there hasn't.

Conditional Calls and Jumps

The f register lets us use 'if..else' statements in assembly. There is another form of the CALL, JR and JP instructions, which is call condition,address (or jp condition,address or jr condition,address). The address part remains the same, and condition is one of the following (there are other possibilities, but they don't all work for JR):

Possible Conditions
Condition Meaning
Z Zero - the instruction is only executed if the result was zero (in other words if the value were equal).
NZ Not Zero - the instruction is only executed if the result was not zero (in other words if the value were not equal).
C Carry - the instruction is only executed if there was a carry (in other words if a was less than the argument).
NC No (or Not) Carry - the instruction is only executed if there was a not carry (in other words if a was greater than or equal to the argument).

Note that you can also do ret condition.

A Useful Program (Sort Of)

So you can now finally write a useful program (or at least you can once I've told you what call _getkey does). The _getkey ROM routine pauses the calculator until a key is pressed, and then returns the value of that key in the a register. It also trashes a few other registers, so if you need them don't forget to push them onto the stack. The number returned in the a register isn't the same as the one used in the built in language, it's a bit more advanced. There are equates defined for the different keys, so rather than doing cp 7 you can do cp kExit (for some reason there's no underscore). If you need a list of the equates for the keys they're in a file called "asm86.h" which you'll find in whatever directory you installed Assembly Studio in in a subdirectory called "include". They all start with a small k - the ones with a capital k are something else.

Program Specification

The program should clear the screen. It should then wait for a key to be pressed. If the key is [EXIT] then the program should quit. If the key is [ENTER] then the program should display a star (character 42) on the screen and go onto the next line. If it is any other key the program should do nothing. The program should then wait for another key and so on.

The Code

Try and work out your own code before copying the one below. Remember, your code will probably be different from mine because I've used a few shortcuts, but as long as it works that's fine.

Source: getkey1.asm
Compiled: getkey1.86p

#include "ti86asm.inc"
.org _asm_exec_ram

  call _clrScrn          ; Clears the screen (duuh!)
  call _homeup           ; Cursor to top left

LoopStart:
  call _getkey           ; Wait for a key to be pressed
  cp kExit               ; Compare it to kExit - [EXIT] key
  ret z                  ; If they're equal return to the OS

  cp kEnter              ; Otherwise compare it to kEnter - [ENTER] key
  jr nz,LoopStart        ; If it's not enter go and get another key

; If it is enter...
  ld a,42                ; a = 42 (ASCII character '*')
  call _putc             ; Display charater in a
  call _newline          ; Go onto a new line
  jr LoopStart           ; Then go back to the start of the loop

.end                     ; Tell the assembler to stop
Screenshots
Screenshot showing one star Screenshot showing four stars
One star Four stars