Author Topic: General Coding  (Read 2523 times)

Offline Eddy-B

  • Hero Member
  • *****
  • Posts: 1186
    • http://www.eddy-b.com
General Coding
« on: June 06, 2005, 12:37:08 PM »
Hey coders!

Since we've got this nice cypher-crypto-whatever thing going on the general forumites, how about a new challange for us, coders, sorta-like an oldskool thing ?

I got the idea during chat tonite: Once upon a long, LONG time ago (when i was still in school, back in 1992, my last year) our "digital technology" teacher asked us to write a assembler program that would multiply 2 8bit numbers, using the processor that had been used many years in small game-computers/home computers (like ZX spectrum and Apple): the Z80. If you're not familiar with this processor, the instruction set is quite simular to the 8080/8085 family. These are ALL 8-bit processors, which makes a WORD-sized multiplication more challanging.

So, the job is simply: write a program (in Z80 or 8085 asm) that would do an 8bit*8bit multiply: operands were to be supplied into specific memory locations. For this example we'll take hex addresses: 0100 and 0101 for the 2 factors, and the resulting product to be stored in 0102/0103 (a 16bit WORD)
AFTER execution of the multiplication code, the values inside memory addresses 0100 and 0101 should still be the same!


Our instruction then was to create code as short and fast as possible. Needless to say: i beat my professor! My code was just a few bytes shorter, and on average, i'd say about 2048 times faster (give or take a few 1000) :D

So all you coders out there: let's see who can beat my teacher as well!


Links:
Z80 overview
Z80 instruction set



PS: he didn't want to be embarressed too much, so he didn't ask us write a division program the week afterwards.. lol

[EDIT] Updated the instructions slightly. Every hour i remember more about this glorious day in my history :)

oh, and the actual school-coding was indeed in 8085 assembler, i now remember!
« Last Edit: June 06, 2005, 06:10:02 PM by Eddy-B »
Rule #1:  Eddy is always right
Rule #2: If you think he's wrong, see rule #1
--------------------

Outpost : Renegades - Eddy-B.com - Electronics Pit[/siz

Offline Hooman

  • Administrator
  • Hero Member
  • *****
  • Posts: 4954
General Coding
« Reply #1 on: June 06, 2005, 06:21:29 PM »
I guess I'll take a stab at it. Correct me if I get the syntax wrong.

Code: [Select]
LD E, (1000)
LD D, 0          ; DE holds 0 extended value
LD B, (1001)
LD HL, 0          ; Clear partial result

Loop:
SRL B    ; Leasy significant bit is in Carry, Z (Zero flag) is set accordingly
JR NC, SkipAdd-$
ADD HL, DE
SkipAdd:

; Now we want to shift the multiplicand left. But only suitable 16 bit opcode is ADD HL, ss
EX DE, HL
ADD HL, HL
EX DE, HL
JR NZ, Loop-$  ; Repeat while B is nonzero (note that only the SRL instruction affects the Z flag)

LD (1002), HL  ; Write the result to memory
RET


The part the shifts DE left is sick, but oh well. Doesn't really seem to be a better way. At least none that I can see with my meager experience with the Z80.
« Last Edit: June 06, 2005, 06:22:22 PM by Hooman »

Offline Cynex

  • Newbie
  • *
  • Posts: 31
General Coding
« Reply #2 on: June 11, 2005, 07:59:33 PM »
That's nearly the same as I would do it.

Why not use
Code: [Select]
SLA E
RL D
instead of the EX-ADD-EX-method?

And maybe it'd be slighly faster to use A in place of B...?

Edit:
From what I've seen SRL doesn't affect Z.
That makes using A instead of B very easy to justify.
« Last Edit: June 11, 2005, 08:09:15 PM by Cynex »

Offline Hooman

  • Administrator
  • Hero Member
  • *****
  • Posts: 4954
General Coding
« Reply #3 on: June 11, 2005, 10:25:03 PM »
Because I have no idea how to use a Z80.  B)

And I think you're right. That does seem to be a more intuitive and faster way. I just happened to see a code example in the manual that used the EX, ADD, EX method. Guess it got stuck in my head.

Also, according to my manual, SRL affects the S, and Z flags "according to the result of the operation".

Hmm, that makes me just realize that if I used SLA and RL, then I'd have destroyed the flags needed for the jump.

As for why I used B instead of A, I have no idea. I was just grabbing registers as I needed them. I guess there's a better chance of A being more optimized for use, but I don't immediately see why it would be faster. Is it to do with the opcode encoding? Or am I missing something else?

It's getting really temping to setup ones of these things and try out some code.  :)  

Offline Finder00

  • Newbie
  • *
  • Posts: 5
General Coding
« Reply #4 on: June 12, 2005, 12:22:17 AM »
Just a bit of trivia:

The Z80 processor can be found in the TI-83 calculator, so if anyone needs a test bed, TI has provided a assembly simulator for ther calc. It may be useful, who knows?

TI-83 SDK page

Offline Cynex

  • Newbie
  • *
  • Posts: 31
General Coding
« Reply #5 on: June 12, 2005, 05:22:58 PM »
Sorry. Of course I was wrong with my interpretation of the '*' in the manual.

For A there is no shorter opcode, but it might be better optimised.
At least you won't have to save BC on stack.

Offline Hooman

  • Administrator
  • Hero Member
  • *****
  • Posts: 4954
General Coding
« Reply #6 on: June 12, 2005, 06:11:05 PM »
Ahh, calling conventions. I hadn't thought of that. Yeah, I guess it would have been wise to preserve some registers or avoid trashing them. I was just freely trashing every register there was.   :blink:

I also just took a look at the instruction encoding and execution time. The instruciton size and execution time seem to be a fixed for each instruction. It doesn't seem to depend on which register is used. They're just encoded as a field of 3 bits (8 registers). Although, A does seem to have some extra opcodes to work with, so you'd have a better chance of selecting better instructions if you used that register. Plus, without a proper calling convention, you're probably gonna screw yourself over on the large scale with either bugs or speed issues.