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:
address | value |
---|---|
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 theIXL
? That was needed becauseIXL
will incrementX
before it loads the value. If we left out theDX
,IXL
would have loaded 30 intoA
. In C it would have effectively looked likex=1; a=numbers[++x];
The ++x would be be evaluated first, then it would bea=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.
Copyright © 2025, Lee Patterson