Assembly #4: Working with an array

It’s so easy to take something like the following for granted in C or Java:

int[] numbers = {10,20,30,40,50};
int a = numbers[1];
//a is now 20

That is, until you try it in assembly! Let’s say we have the following bytes defined. This is what an array looks like in assembly:

numbers:    db      10 20 30 40 50

Now lets say we want to see the number at element 1, which is 20. On the Sharp PC–1360’s SC61860 CPU, we could try:

numbers:    db      10 20 30 40 50
            lidp    numbers     # point DP to numbers
            ldd                 # load A with [DP]

But A will be loaded with the value 10, which is the first element, element 0. We want element 1, which is 20. Okay, why not add 1 to DP? Sounds like a great idea, but after looking through the instruction set, we don’t have any instructions (also called mnemonics) to do that. There in lies the problem, nay, challenge of working with assembly. You can work directly with some registers, and instructions only work on others.

You can however manipulate the X and Y registers, and they will copy themselves to DP.

Hex   Dec   Instruction   Function                         Bytes  Cycles  Flags
&04   004   IX            X + 1 -> X                       l      6
                          X -> DP
&05   005   DX            X - 1 -> X                       1      6             
                          X -> DP                                               
&06   006   IY            Y + 1 -> Y                       1      6             
                          Y -> DP                                               
&07   007   DY            Y - 1 -> Y                       1      6             
                          Y -> DP                                               
&24   036   IXL           X + 1 -> X                       1      7
                          X -> DP
                          [DP] -> A

That last instruction IXL looks interesting. It will increment X, store the new value of X to DP, then copy the value at [DP] to A. We’ll be taking advantage of that. Any time you can do more then one thing at a time in a single mnemonic, do it.

So let’s look at those numbers again, and think about things as an offset into those numbers, which is like saying the index into the array:

addressvalue
numbers 10
numbers+1 20
numbers+2 30
numbers+3 40
numbers+4 50

We want numbers+1 to get the value 20. So, we can point X to the address of number, and add 1, so X points to address numbers+1. Here is some code to do just that. It makes use of ADB, which is a 16-bit add instruction. You load X with a 16-bit value, then ADB will add B and A to it. I’ll save explaining ADB fully for another time.

numbers:    db      10 20 30 40 50
            lp      XH_REG          # P  [P] 
            lp      XL_REG          # P  [P] => X now contains the address of numbers
            lia     1               # low byte in 16-bit add
            lib     0               # high byte in 16-bit add
            lp      XL_REG          # point P to XL, the low byte
            adb                     # add B,A to X
            dx                      # dec so we can ixl to load
            ixl                     # loads correct value from numbers[1], A is now 20

Did you notice the DX just before the IXL? That was needed because IXL will increment X before it loads the value. If we left out the DX, IXL would have loaded 30 into A. In C it would have effectively looked like x=1; a=numbers[++x]; The ++x would be be evaluated first, then it would be a=numbers[2];.

So there you have it. Our 2 lines of C code turned into 13 line of assembly. Take heart though. It compiles down to only 27 bytes!

Now, if one where to need to access an array several times in ones code, one would be foolish to copy that same code over and over. Instead, one could create a routine, like the following. It may seem like you are using a lot more code, but if you call the routine in 7 places, you have started to save.

I created a full demo program, with examples of how to test it in the RUN or PRO mode of a PC–1403 or PC–1360.

##############################################################################
## array.asm
## Test accessing memory like an array.
##
## PEEK 49203           Check the result
## 0.
## PEEK 49204           Check the index
## 1.
## CALL 49200
## PEEK 49203           Check the result
## 20.
## POKE 49204,3         Change the index
## CALL 49200
## PEEK 49203           Check the result
## 40.
##
## http://www.axorion.com
##############################################################################

                $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

                jp      start

result:         db      0                
index:          db      1
numbers:        db      10 20 30 40 50

start:          lidp    index           # point in index
                lp      K_REG
                mvmd                    # K=index value 
                lia     LB@numbers      # A&B point to array
                lib     HB@numbers
                call    arrayValue      # get the value, returns A = numbers[A]

                lidp    result
                std                     # store A into result

                rtn                     # result should contain 20


######################################################################
## arrayValue - Retrieve the value pointed to by A,B offset by K
##
## IN:          A Low byte of array
##              B High byte of array
##              K Element of index to grab
##
## OUT:         A value of index element
##
## Used:        A,B,K,J,X
######################################################################
arrayValue:     liq     A_REG
                lp      XL_REG
                lij     1               # J is used in MVB
                mvb                     # XL = A, XH = B
                lp      K_REG           # K=index
                exam                    # A=K,K=A, A contains index
                lp      XL_REG          # point to XL again
                lib     0
                adb                     # 16-bit add
                dx
                ixl                     # load the value at the calculated index into A
                rtn                     # A now contains numbers[A]

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