3

I am trying to learn assembler on the various retro machines I own, or am about to buy.

Today I tried converting this 8080 routine (which worked, repeatedly):

| START: | MVI A,0  | 8000 | 3e |
|        |          | 8001 | 00 |
| LOOP:  | INR A    | 8002 | 3c |
|        | CPI 10   | 8003 | fe |
|        |          | 8004 | 0a |
|        | JZ HALT  | 8005 | ca |
|        |          | 8006 | 0b |
|        |          | 8007 | 80 |
|        | JMP LOOP | 8008 | c3 |
|        |          | 8009 | 02 |
|        |          | 800a | 80 |
| HALT:  | HLT      | 800b | 76 |

to run on my Epson HX-20, which has two Hitachi 6301 chips, using the datasheet available at vintagecomputer.net. It was a lot of guesswork on my part with the mnemonics, but I came up with this:

| START: | LDA A 0  | 1000 | 86  |
|        |          | 1001 | 00  |
| LOOP:  | INC A    | 1002 | 4c  |
|        | CMP A 10 | 1003 | b1  |
|        |          | 1004 | 0a  |
|        | BEO      | 1005 | 27  | #Branch if = zero
|        |          | 1006 | 0b  |
|        |          | 1007 | 10  |
|        | JMP LOOP | 1008 | 6e  |
|        |          | 1009 | 02  |
|        |          | 100a | 10  |
| HALT:  | SWI      | 100b | 3f  | #Software interrupt

To my surprise, this worked first time, and I could see the A accumulator* now held 0a. To my greater surprise, it hasn't worked since, when I have changed the value of 1004. I tried turning the machine on and off, but due to the way the HX-20 works, this does not clear RAM.

Why did this routine only work once? My guess is that branch is not quite the same as jump, and it is waiting to come back, or maybe I need to reset the zero flag?

In any case, I can set the value of the A accumulator manually using LDA A, or the HX-20 Monitor x command, so it would not appear to be a malfunctioning RAM issue.

I'm now wondering if I'm going mad, and it didn't work the first time after all...

* The HX-20 also has a B accumulator.

1 Answer 1

13

There are several issues:

  • BEQ is a two byte instruction, using a relative offset, not a 3 byte with an absolute address.

  • The $6E JMP you used is an indexed one, with two bytes length, not three. Its parameter is a relative offset added to the X register.

So for the BEQ you want to use a two byte offset, as in 27 02, to jump around.

For the JMP, $7E would be the right encoding when using absolute, or rather use a BRA ($20) to keep the program short and relocatable.

The final program would look more like this:

1000 86 00    LDAA #00
1002 4C       INCA
1003 B1 0A    CMPA #10
1005 27 02    BEQ  L1009
1007 20 F9    BRA  L1002
1009 3F       SWI

(Well, a real program one would change the BEQ for a BNE and scrap the BRA, but that's a different story)


If I may add, your assumption seems to be that a port can be done by just exchanging opcodes, but that's as frivolous as translating from English to German by swapping words according to some dictionary.

2
  • 4
    Yeah, since asking the question I've been reading more about the chip and realising how wrong I was to try to translate mnemonic-for-mnemonic. I'd got about halfway towards your answer, but was stuck on exactly how to calculate relative addressing, which your example clearly illustrated. So I accept it was a bad question, and am grateful for the time you took to nevertheless write a good answer! :-)
    – harlandski
    Mar 15, 2018 at 18:30
  • Thanks, glad I could help. Relative addressing is, at least on 6800ish CPUs, rather straight forewart. Just take the address of the next instruction and subtract it from you target.
    – Raffzahn
    Mar 15, 2018 at 18:53

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .