Assembly #2: String compare

Here we are again. For my first tutorial, see Assembly #1 Reverse a string. Bill set me up for a second challenge, and I took it up. This is another great bite sized exercise to learn how to compare blocks of memory. In this exercise we will compare 2 strings and let the user know if they are equal. We will make use of BASIC again to:

  1. Gather the user input
  2. Poke the strings to address where our assembly program can get to it
  3. Call our machine language program
  4. Peek at the result and tell the user if the two strings are equal.

Getting Started

The purpose of this project is to write another simple assembly language program, and learn to use a few more assembly mnemonics. Specifically the ones for comparing values. You will want to make sure you use the $JR compiler directive to make jumps easier.

The mnemonics for comparing are:

MNEMONIC      OPERATION   FLAGS EFFECTED  
CPIM n        [P] - n     C,Z  
CPIA n        A - n       C,Z
CPMA          [P] - A     C,Z

Use the following truth table to figure out what flags will be set.

TRUTH TABLE
EXAMPLE  FLAGS    MEANING
4 - 5    C=1,Z=0  left < right
5 - 5    C=0,Z=1  left = right
6 - 5    C=0,Z=0  left > right

You’re likely to find CPMA is the real workhorse when dealing with data. CPIA and CPIM are used when dealing with known values; Like if you want to see if something equals 0.

Once you have compared, you will use a branch mnemonic to jump to a new piece of code.

MNEMONIC      OPERATION
JPNZ nm       jump to nm if Z=0
JPNC nm       jump to nm if C=0
JPZ nm        jump to nm if Z=1
JPC nm        jump to nm if C=1
JP nm         jump to nm regardless of flags

As an example, lets say you want to see if the A reg equals the number 5. You would use the following code:

        CMIA    5       # A - n, check if A reg is 5
        JPZ     PLACE1
        # continue as A is not 5
        RTN

PLACE1: # A is 5
        RTN

JPZ jumps to PLACE1 if the zero flag was set, which according to the truth table means A equals 5.

Memory Map

This will be our memory setup. Program start is 49217.

ADDRESS       ASM VAR  COMMENT
49200         RESULT   Result (1 equal | 0 not equal)
49201 - 49207 SRC1     String 1
49208         SRCLEN1  Length of string 1
49209 - 49215 SRC2     String 2
49216         SRCLEN2  Length of string 2
49217                  Program start

Our assembly program will compare the 2 strings SRC1 and SRC2, making note of the string lengths SRCLEN1 & SRCLEN2, and store the result in address RESULT (49200).

Assembly Source

Compile and load at address 49200 (&C030). bin2wav.exe --type=bin --pc=1360 --addr=0xC030 output.bin and CLOAD M on your pocket computer.

    ##############################################################################
    # Compare the strings SRC1 and SRC2 to see if they
    # are equal. Store 0 in RESULT if no, 1 if they are.
    ##############################################################################

            $JR
            org     &C030

    I_REG   EQU     0               # Internal Registers
    J_REG   EQU     1
    A_REG   EQU     2
    B_REG   EQU     3
    XL_REG  EQU     4
    XH_REG  EQU     5
    YL_REG  EQU     6
    YH_REG  EQU     7
    K_REG   EQU     8
    L_REG   EQU     9
    M_REG   EQU     10
    N_REG   EQU     11
    PORTC   EQU     95

    # define data and put some dummy data in place
    RESULT:     DB      0 
    SRC1:       DB      48 49 50 51 52 53 54
    SRCLEN1:    DB      1
    SRC2:       DB      65 66 67 68 69 70 71
    SRCLEN2:    DB      1

    START:
            # Point the X register to SRC1
            LP      XH_REG      # P <- XH
            LIA     HB@SRC1
            EXAM                # A <-> [P] 
            LP      XL_REG      # P <- XL
            LIA     LB@SRC1
            EXAM                # A <-> [P] => X now contains SRC1
            DX                  # prep for ++X inside check1

            # Point the Y register to SRC2
            LP      YH_REG      # P <- YH
            LIA     HB@SRC2
            EXAM                # A <-> [P] 
            LP      YL_REG      # P <- YL
            LIA     LB@SRC2
            EXAM                # A <-> [P] => Y now contains SRC2
            DY                  # prep for ++Y inside check1

            # put srclen1 into A and srclen2 into B
            LIDP    SRCLEN2
            LDD                 # [DP] -> A - srclen -> A
            EXAB                # A <-> B - B contains srclen2
            LIDP    SRCLEN1
            LDD                 # A contains srclen1

            # check if strings are the same length
            LP      B_REG      # P points to B reg
            CPMA               # [P] - A -> C,Z     # compare A and B
            JPNZ    NOT_EQUAL

            # check byte by byte to see if the strings are the same length
            lp      K_REG
            exam            # K now contains srclen1
    check1:
            # put src1 bytes into A, src2 bytes into B, then compare A & B

            # load B from Y
            iy              # ++Y -> DP
            ldd             # [Y] -> A
            exab            # B contains [Y]

            # load A from X
            ixl             # ++X -> DP, [DP] -> A

            lp      B_REG
            cpma            # compare A and B
            jpnz    not_equal

            # decrement K reg
            deck
            jpnz    check1  # keep checking

            # fall through into equal

    equal:        
            lidp    result
            lia     1
            std
            rtn

    not_equal:
            lidp    result
            ra              # 0 -> A
            std
            rtn

BASIC Source

You can type RUN to start this program once loaded.

100 "S" WAIT 0
110 A=49201:R=49200
120 INPUT "String 1:";X$
130 INPUT "String 2:";Y$
135 PRINT "POKING"
140 K = LEN X$
150 L = LEN Y$
200 FOR I=1 TO K
205 V = ASC(MID$(X$,I,1))
210 POKE A,V
220 A=A+1
230 NEXT I
240 A=49209
250 FOR I=1 TO L
265 V = ASC(MID$(Y$,I,1))
270 POKE A,V
280 A=A+1
290 NEXT I
295 POKE 49208,K : POKE 49216,L
300 PRINT "CALLING ML"
310 CALL 49217
320 IF PEEK 49200 = 0 PRINT "NOT EQUAL"
330 IF PEEK 49200 = 1 PRINT "EQUAL"

Feel free to drop me a line at eightbit at axorion dot com. You can also start a thread on Simons Pocket Computer Forum. Best to let me know you did though, in case I don’t see your forum entry right away.

You Can Also Check Out