Help with some assembly

polarmystery

Diamond Member
Aug 21, 2005
3,888
8
81
Hey guys,

I am trying to write a program that does a multiplication of two 8 bit values and displays the results on 4-seven segment LED characters. I am having difficulty with understanding what I'm doing wrong. Can someone care to digest this and tell me why it doesn't work?

Code:
mult:   LOAD    sE, sA ; load multiplicand into register sE (to be right shifted)
        LOAD    sF, sA ; load multiplicand to be added to total (to be left shifted)
        LOAD    s8, 04 ; loop counter

mult_loop:    COMPARE s8,00
              JUMP     Z, final ; goes back to main program
              CALL     multiply
              SUB     s8,01
              JUMP     mult_loop

multiply:    SR0    sE              ; shifts multiplicand to check for carry bit
             JUMP    C, mult_add    ; if carry = 1 is detected, add value to total
             SL0    sF
             RETURN

mult_add:    ADD    s3, sF        ; register s3 for the right byte on display
             ADDCY    s4, 00      ; register s4 for the left byte on display
             RETURN

I followed my code and I think I have it somewhat correct, but when I try to issue the command for this, it only adds one value. :confused:
 

Ken g6

Programming Moderator, Elite Member
Moderator
Dec 11, 1999
16,695
4,658
75
First, what assembly is this? It's not x86. MIPS?

Second, is there a conditional CALL instruction? (Hint, hint.)
 

HopJokey

Platinum Member
May 6, 2005
2,110
0
0
Hey guys,

I am trying to write a program that does a multiplication of two 8 bit values and displays the results on 4-seven segment LED characters. I am having difficulty with understanding what I'm doing wrong. Can someone care to digest this and tell me why it doesn't work?

Code:
mult:   LOAD    sE, sA ; load multiplicand into register sE (to be right shifted)
        LOAD    sF, sA ; load multiplicand to be added to total (to be left shifted)
        LOAD    s8, 04 ; loop counter

mult_loop:    COMPARE s8,00
              JUMP     Z, final ; goes back to main program
              CALL     multiply
              SUB     s8,01
              JUMP     mult_loop

multiply:    SR0    sE              ; shifts multiplicand to check for carry bit
             JUMP    C, mult_add    ; if carry = 1 is detected, add value to total
             SL0    sF
             RETURN

mult_add:    ADD    s3, sF        ; register s3 for the right byte on display
             ADDCY    s4, 00      ; register s4 for the left byte on display
             RETURN

I followed my code and I think I have it somewhat correct, but when I try to issue the command for this, it only adds one value. :confused:

Can you translate into pseudo C style code? What language is this, some custom chip assembly?
 

polarmystery

Diamond Member
Aug 21, 2005
3,888
8
81

Schmide

Diamond Member
Mar 7, 2002
5,745
1,036
126
Why not use the multiply routine on page 31 of the manual?

Edit: Since I talk about it might as well post it.

Code:
; Multiplier Routine (8-bit x 8-bit = 16-bit product)
; ==================================================
; Shift and add algorithm
;
mult_8x8:
                  NAMEREG s0, multiplicand ; preserved
                  NAMEREG s1, multiplier ; preserved
                  NAMEREG s2, bit_mask ; modified
                  NAMEREG s3, result_msb ; most-significant byte (MSB) of result,
; modified
                  NAMEREG s4, result_lsb ; least-significant byte (LSB) of result,
; modified
;
                  LOAD bit_mask, 01 ; start with least-significant bit (lsb)
                  LOAD result_msb, 00 ; clear product MSB
                  LOAD result_lsb, 00 ; clear product LSB (not required)
;
; loop through all bits in multiplier
mult_loop: TEST multiplier, bit_mask ; check if bit is set
                  JUMP Z, no_add ; if bit is not set, skip addition
;
                  ADD result_msb, multiplicand ; addition only occurs in MSB
;
no_add: SRA result_msb ; shift MSB right, CARRY into bit 7,
; lsb into CARRY
                  SRA result_lsb ; shift LSB right,
; lsb from result_msb into bit 7
;
                  SL0 bit_mask ; shift bit_mask left to examine
; next bit in multiplier
;
                  JUMP NZ, mult_loop ; if all bit examined, then bit_mask = 0,
; loop if not 0
                  RETURN ; multiplier result now available in
; result_msb and result_lsb
 
Last edited:

Schmide

Diamond Member
Mar 7, 2002
5,745
1,036
126
It's basically adding a bunch of shifted words to do the multiplication.

Example 0x00001010 * 0x01000101

10 * 69

equals

0x00000000 + 0x00001010 + (1st bit) (not shifted)
0x00000000 + 0x00101000 + (3rd bit) (shifted twice)
0x00000010 + 0x10000000 + (7th bit) (shifted 6 times)
=
0x00000010 + 0x10110010

690
 

Cogman

Lifer
Sep 19, 2000
10,286
145
106

Schmide

Diamond Member
Mar 7, 2002
5,745
1,036
126
I just glanced at the code before. I looked back at it and it actually kind of elegant how they add to the msb, possibly pushing a bit into the carry bit, then shift right, returning that bit to the msb and pushing the lowest bit of the msb into the carry bit. Then shifting right on the lsb acquires that bit. This happens 8 times till the first add is finally shifted into the zero bit.
 

exdeath

Lifer
Jan 29, 2004
13,679
10
81
Very common optimization on older hardware.

Multiplying by powers of 2 by shifting 1 bit per power by recognizing that every bit is itself a power of 2 in binary.

a * 2 == a<<1
a * 4 == a<<2
etc

For non powers of two you use the distributive property of multiplication:

a * 3 == a * (1+2) == a*1 + a*2 == a + (a<< 1)

A shift and add take 1 cycle each on even old hardware while a mul instruction may take 10s of cycles. In something like a software 3D rasterizer on a 16 MHz CPU in something like a gameboy where you have possibly millions of multiplies per frame, shift and add can be the difference between impossible and 30 FPS.

The same is true with division and shifting right instead. And a DIV can be upwards of 70 cycles on some hardware. Things like perspective correct texture mapping require a divide for every pixel rendered.
 
Last edited:

exdeath

Lifer
Jan 29, 2004
13,679
10
81
check your stack. you are popping more than pushing.

This too. You are mixing calls and jumps with return. Don't use return with jump, use an unconditional jump to go back instead (even though its bad form like GOTO in BASIC).
 
Last edited: