Simple multiplication

Here you can ask questions or provide insights about how to use efficiently 6502 assembly code on the Oric.
Post Reply
User avatar
Pengwin
Pilot Officer
Posts: 67
Joined: Sun Jan 07, 2007 11:03 pm
Location: Scotland
Contact:

Simple multiplication

Post by Pengwin » Sun Jan 20, 2013 7:22 pm

Just checking I have understood things.
I have written, what I hope is a simple multiplication routine to multiply 2 bytes, returning a word. This could obviously be very useful for calculating screen addresses.

Just want to check that what I have come up with is as efficient as possible, so I would like some of you gurus to have a quick look over it please.

First up, I have designated these locations for custom maths routines I may come up with:

Code: Select all

; First operand for custom maths routines
#define		MATHOP1	$00		
; Second operand for custom math routines
#define		MATHOP2	$02		
; Answer from custom maths routines
#define		MATHRES	$04		
Then I have the subroutine that uses those locations:

Code: Select all

; Multiply routine
;
; This routine multiplies two bytes together,
; resulting in a word.
;
; Pass the two arguments via (Page 0 addresses):
;		MATHOP1			($00)
;		MATHOP2			($02)
;
; The jump to the subroutine:
;		multiply
;
; The answer is held in (Page 0 address):
;		MATHRES			($04)
; and 	MATHRES+1		($05)
;
; Corrupts the following registers:
;			P, X, A
;
; Corrupts the following memory locations:
;			MATHOP1

Multiply	
.(
			cld
			lda #0
			sta MATHRES
			sta MATHRES + 1
			ldx #8				
multloop	asl MATHRES
			rol MATHRES + 1
			asl MATHOP1
			bcc multnext
			clc
			lda MATHOP2
			adc MATHRES
			sta MATHRES
			lda MATHRES + 1
			adc #0
			sta MATHRES + 1
multnext	dex
			bne multloop
			rts
.)
Have I understood things correctly? Is there a more efficient way of doing this?

User avatar
Chema
Game master
Posts: 2079
Joined: Tue Jan 17, 2006 10:55 am
Location: Gijón, SPAIN
Contact:

Re: Simple multiplication

Post by Chema » Sun Jan 20, 2013 9:40 pm

Hi!

You're using the shift & add method for 8 bit, aren't you? That is quite fast and compact.

If you ever need a really fast method you can check my post here. I really needed that speed in 1337, due all the matrix operations that were needed.

Check www.6502.org for more interesting sources for this and other areas.

Oh, and if you are looking for a fast method to obtain the pixel address for a given coordinate pair (x,y) stored in regs X and Y respectively to set/clear a pixel in HIRES screen, check this code (from Dbug). tmp0 is a ZP address:

Code: Select all

	
             lda _HiresAddrLow,y
             sta tmp0+0	
             lda _HiresAddrHigh,y
             sta tmp0+1	
             ldy _TableDiv6,x
             lda _TableBit6Reverse,x
             ora (tmp0),y	
             sta (tmp0),y   
The code to setup those tables is (I've taken this from 1337, modifying a couple of bits by hand, so don't trust it 100% - However I think the code has been posted somewhere, maybe in the SVN, maybe even it is included in the OSDK):

Code: Select all

#define X_SIZE      240
#define Y_SIZE      200
#define ROW_SIZE    X_SIZE/6

    .dsb 256-(*&255)
_HiresAddrLow           .dsb Y_SIZE
    .dsb 256-(*&255)
_HiresAddrHigh          .dsb Y_SIZE
    .dsb 256-(*&255)
_TableDiv6              .dsb X_SIZE
    .dsb 256-(*&255)
_TableBit6Reverse
    .byt 32,16,8,4,2,1
    .byt 32,16,8,4,2,1
    .byt 32,16,8,4,2,1
    .byt 32,16,8,4,2,1
    .byt 32,16,8,4,2,1
    .byt 32,16,8,4,2,1
    .byt 32,16,8,4,2,1
    .byt 32,16,8,4,2,1
    .byt 32,16,8,4,2,1
    .byt 32,16,8,4,2,1

    .byt 32,16,8,4,2,1
    .byt 32,16,8,4,2,1
    .byt 32,16,8,4,2,1
    .byt 32,16,8,4,2,1
    .byt 32,16,8,4,2,1
    .byt 32,16,8,4,2,1
    .byt 32,16,8,4,2,1
    .byt 32,16,8,4,2,1
    .byt 32,16,8,4,2,1
    .byt 32,16,8,4,2,1

    .byt 32,16,8,4,2,1
    .byt 32,16,8,4,2,1
    .byt 32,16,8,4,2,1
    .byt 32,16,8,4,2,1
    .byt 32,16,8,4,2,1
    .byt 32,16,8,4,2,1
    .byt 32,16,8,4,2,1
    .byt 32,16,8,4,2,1
    .byt 32,16,8,4,2,1
    .byt 32,16,8,4,2,1

    .byt 32,16,8,4,2,1
    .byt 32,16,8,4,2,1
    .byt 32,16,8,4,2,1
    .byt 32,16,8,4,2,1
    .byt 32,16,8,4,2,1
    .byt 32,16,8,4,2,1
    .byt 32,16,8,4,2,1
    .byt 32,16,8,4,2,1
    .byt 32,16,8,4,2,1
    .byt 32,16,8,4,2,1

    .dsb 256-(*&255)

    .byt 0

_GenerateTables
.(
	ldx #0
loop
	; generate two bytes screen adress
	clc
	lda tmp0+0
	sta _HiresAddrLow,x
	adc #ROW_SIZE
	sta tmp0+0
	lda tmp0+1
	sta _HiresAddrHigh,x
	adc #0
	sta tmp0+1

	inx
	cpx #Y_SIZE
	bne loop
.)
.(
    ; Generate multiple of 6 data table
    lda #0      ; cur div
    tay         ; cur mod
    tax
loop
    sta _TableDiv6,x
    iny
    cpy #6
    bne skip_mod
    ldy #0
    adc #0      ; carry = 1!
skip_mod

    inx
    cpx #X_SIZE
    bne loop
.)
    rts

User avatar
Dbug
Site Admin
Posts: 2391
Joined: Fri Jan 06, 2006 10:00 pm
Location: Oslo, Norway
Contact:

Re: Simple multiplication

Post by Dbug » Mon Jan 21, 2013 8:31 pm

Pengwin wrote:Just checking I have understood things.
I have written, what I hope is a simple multiplication routine to multiply 2 bytes, returning a word. This could obviously be very useful for calculating screen addresses.
As Chema wrote, the best way is to not calculate screen addresses at all but instead to use tables.
If you have room, just store the table in the data section, already generated.
If you want to make a small demo, you can store the table in the bss section and generate it on startup.

The fastest code is the one you don't run :)

User avatar
Chema
Game master
Posts: 2079
Joined: Tue Jan 17, 2006 10:55 am
Location: Gijón, SPAIN
Contact:

Re: Simple multiplication

Post by Chema » Mon Jan 21, 2013 8:41 pm

Dbug wrote:The fastest code is the one you don't run :)
Yeah, that I learned from you, Dbug. I remember how I was trying to make a fast compact pixel_address and line routines and how you demonstrated me that it was way better to use tables and avoid running code.

You enlightened me indeed!

User avatar
Pengwin
Pilot Officer
Posts: 67
Joined: Sun Jan 07, 2007 11:03 pm
Location: Scotland
Contact:

Re: Simple multiplication

Post by Pengwin » Mon Jan 21, 2013 9:06 pm

Thanks for the answers guys, plus the tip of using tables for screen coordinates, I can see how that could save a massive number of clock cycles.

Post Reply

Who is online

Users browsing this forum: No registered users and 2 guests