This intro provides a little fun background on why I started all this assembly on the PC-1360. You can skip ahead to the Getting Started section below if you wish to skip the intro.
I was talking with a coworker, Bill, one day, about how I liked the idea of writing assembly language programs, and how I wanted to use it for my robot projects. Assembly to me, has always been the ultimate programming language. There’s just something about scraping your knuckles on the bare hardware, working directly with the CPU and it’s hardware. I get all giddy just thinking about it.
Bill had done a lot of assembly back in the day, and expressed he had no desire to ever do it again. He described it as painful and tedious. So he set a challenge for me, maybe to prove how much of a pain assembly is, and shut me up. “Why on earth would he want to write assembly code?” The challenge was to write a routine in assebly to reverse a string.
At the time, I was learning to use an AVR chip, which is a tiny RISC based CPU available in a number of pin sizes. The smallest of which is just 8 pins; no bigger then a 555 timer. Then I found the Arduino, and fell in love with how easy was to write code for it. Unfortunatly, I found it too convenient to use C on the Arduino, and never bothered with assembly on the AVR chip.
Fast forward 2 years, and I am looking through some old boxes, and I happen upon my Sharp PC-1360. “Cool!” I say, and I tapped out a quick BASIC program. It was then that I was reminded how slow BASIC was, and I was curious if I could write assembly language programs for it. I discovered both Aldweb and simons pocket computer reference site, and discovered that yes, I could write assembly for it! The string reverser project was born. I am actually glad I did the project on the PC-1360. Turns out to be a very nice platform to work on. You have a screen, keyboard, and the ability to look at and change bytes in memory.
A couple convention examples. When you see something like X – 1 -> X you are saying X=X-1 or –X. When you see A -> [DP] you are copying the value of A register to the location pointed to by DP. In C it would look like *ptr = 123. X -> DP is like saying ptr = 0xC030. If you need more info, see the Machine Language Quick Manual on aldweb.
&C030 is an example of a hex value. 0xC030 is also, and is used in C/C++ and Java. When working with the pocket computers, you will need to use &C030 form. I may slip in 0xC030 now and then since that is what I use outside of pockets computers.
The purpose of this project is to write a simple assembly language program, just to get the hang of things.
What I learned while writing this was what registers are used for what. I came to the conclusion that X is typically used when reading data. I came to this conclusion because you can see the IXL instruction will increment itself, copy it’s value to DP and load the A register with the data at [DP]; all in one instruction. Similarly, the Y register is great for storing data. IYS will increment Y, copy to DP, and store A to [DP]. I also got a better understanding of PUSH and how to use LOOP.
Lastly, I finally came to terms with the P register. I figured out that it is used to point to registers you can’t directly access. For example, you can’t directly load the X and Y registers. Instead you have to do it indirectly by pointing the P register to first XH then XL. For example, the following code will point X to SOURCE:
ORG &C030 SOURCE: DB 48 49 50 51 52 53 54 # load X with SOURCE LP XH_REG # point P to XH LIA HB@SOURCE # A contains &C0 EXAM # A -> [P] LP XL_REG # point P to XL LIA LB@SOURCE # A contains &30 EXAM # X now points SOURCE
You will find similar instances where you have to point P to a register to perform an operation. CPMA is a perfect example. If you wanted to compare the registers A and B, you’ll discover there are no instructions to do that. Instead you point P to the B register, then call CPMA which will compare [P] with A. That in effect will compare B with A. Sneaky isn’t it?
I broke this task into two parts.
I did this to keep the assembly part simple. We will just let BASIC read from the keyboard and display to the screen, since it’s great for that. Actually, you will discover that we really don’t really even need to have the BASIC part, but it does make the whole process a little easier to test results, and show the results to friends.
The assembly program will have a predefined location for the source string (the string to reverse), and a location to store the reversed string. We also need to store the length of the source string.
Note that the term assembly language typically refers to the source, and machine language or machine code refers to the compiled version of the assembly language. I may use the terms interchangbly.
The BASIC program will:
The assembly program will simply:
Compile and load this at address 49200 (&C030) via CLOAD M on the pocket computer and . Once loaded, you can use PEEK to look at addresses 49207 – 49209 and see they contain the value 35. Which his what we have defined at DEST in the source below.
Before we load up the BASIC program, lets run the machine code via CALL 49215, and again PEEK at addresses 49207 – 49209. You will notice it now contains 50, 49, 48. It read the data from SOURCE and put the reverse in DEST, but only did it for LENGTH bytes.
# Reverse a number of bytes # X register points to the source data # Y register points to the destination data # We point X to the last character of the input string, # and Y to the first of the destination. Then just loop # the correct number of times and copy data along the way. # When we are done, the reversed sting is stored in DEST. # Important instructions: # IXL loads A from [X] (via DP) # IYS stores A to [++Y] # DYS stores A to [--Y] # 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 SOURCE: DB 48 49 50 51 52 53 54 DEST: DB 35 35 35 35 35 35 35 LENGTH: DB 3 # Copy SOURCE to DEST in the reverse order, copying LENGTH bytes. START1: # load X with source LP XH_REG LIA HB@SOURCE EXAM # A -> [P] LP XL_REG LIA LB@SOURCE EXAM # X now points SOURCE DX # needed because DXL is a little odd # Move the source to the end of the string LIDP LENGTH # point to length byte LDD # [DP] -> A CPIA 0 # check if string length is 0 JPZ DONE # length is 0 PUSH # used in loop later LP I_REG # point P to I register EXAM # A -> [P], I reg now contains length INCXPTR: IX # ++X LOOP INCXPTR # loop A times # load Y with dest LP YH_REG LIA HB@DEST EXAM LP YL_REG LIA LB@DEST EXAM # Y points to dest DY # one less for ++Y later LOOP1: DXL # [--X] -> A IYS # A -> [++Y] DECI JPNZ LOOP1 DONE: RTN
The BASIC program assumes you have already loaded the machine code. Load this in PRO mode via CLOAD. Appologies for not renumbering the code. I haven’t tried the tool that does it on my Mac, and can’t send data from the 1360 to my Mac yet.
Once loaded, if you type RUN it will dump the contents of memory addresses 49200-49214, to show you both the source and destination values. Use DEF S to start the real program (at line 100.) Once I find a renumbering tool, I’ll update the listing.
You’ll notice at line 127 IF L = 0 THEN 155, I check if the user entered a zero length string, and skip poking the contends of the string. You’ll also noticed that I will still call the assembly program, as it will handle a zero length string.
5 S=49200 : A=S 6 WAIT 0 7 GOSUB 10 8 END 10 FOR I=1 TO 14 15 IF I=14 WAIT 20 PRINT CHR$ PEEK a;" "; 25 A=A+1 26 if I=7 THEN PRINT "-" 30 NEXT I 40 RETURN 100 "S" 101 S$="" 104 WAIT 0 105 A=49200 110 INPUT "ENTER STRING (MAX 7)? ";S$ 120 IF LEN(S$) > 7 THEN PRINT "TOO LONG" : GOTO 110 124 PRINT "USING [";S$;"]" 125 REM STORE ENTRY FOR ML PROGRAM TO ACCESS 126 L = LEN(S$) : POKE 49214,L 127 IF L = 0 THEN 155 130 FOR I=1 TO L 135 V = ASC(MID$(S$,I,1)) 136 PRINT "POKING ";V;"INTO ";A 140 POKE A,V 145 A=A+1 150 NEXT I 155 PRINT "CALLING REVERSER" 160 CALL 49215 165 S$="" 170 PRINT "RESULT" 180 A=49207 182 IF L=0 THEN 215 185 FOR I=1 TO L 190 S$=S$+CHR$ PEEK A 200 A=A+1 210 NEXT I 215 PRINT "RESULT [";S$;"]" 220 A=49200 230 GOSUB 10 240 END
Feel free to drop me a line at eightbit at axorion. 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.
Where to go next? See my next project, Assembly #2 String Compare.
Copyright © 2025, Lee Patterson