Getting a signed multiply working (was: How do I print signed integer numbers?)

Basic and Machine Language

Moderator: Moderators

Post Reply
User avatar
MrSterlingBS
Vic 20 Enthusiast
Posts: 174
Joined: Tue Jan 31, 2023 2:56 am
Location: Germany,Braunschweig

Getting a signed multiply working (was: How do I print signed integer numbers?)

Post by MrSterlingBS »

Hello,

I used some unsigned integer multiply routines from codebase64.
Now I would like to compare some signed integer multiply rotines.
But how can I print the multiplier, multiplicand and result on screen with the sign - ?

As an example there is the code of my unsigned routine.

Code: Select all

; mult39.a
; from https://revs.bbcelite.com/source/main/subroutine/multiply8x8.html
; From 'Revs' for the BBC Micro
; tweaked a bit for size and speed
;
; 8 bit x 8 bit unsigned multiply, 16 bit result
; Average cycles: 107
; 69 bytes
; (A T) = A * U


FLPASC 	equ $DDDD
INTFLP	equ $D391		

CLRSCR	equ $E55F
WRTF	equ $E742
STROUT 	equ $CB1E
STACK	equ	$0100

u	    equ $30		; multiplicand
multiplier	equ $32
t      	equ $34		; 
producthigh 	equ $36

*=$1201
        dB	$0B, $12, $0A, $00, $9E
		dB	$38, $31, $39, $32			; SYS8192 = $2000
		dB	$00, $00, $00
*=$2000
			
	sei				; stop interrupts
	
	jsr CLRSCR		; clear screen
	
	
	lda #$00		; high
	ldy #155			; low
	sty multiplier
	jsr INTFLP		; integer to float point
	
	jsr Primm
	db "MULTIPLIER:  ",$00	
	
	jsr FLPASC
	ldy #>STACK
	lda #<STACK
	jsr STROUT
	
	
	lda #$00		; high
	ldy #155		; low
	sty u
	jsr INTFLP		; integer to float point
	
	jsr Primm
	db $0d,"MULTIPLICAND:",$00	
	
	jsr FLPASC
	ldy #>STACK
	lda #<STACK
	jsr STROUT
	
; code from the book VIC-20 MACHINE LANGUAGE GUIDE Abacus Software
	lda #0						
	sta $9129	; decrements every 256 µS	; 4 cycles
	sta $9128	; decrements every µS		; 4 cycles
	cld			; insure binary mode		; 2 cycles
	clc			; clear carry flag			; 2 cycles
; ************** Start Counter with 10 Cycles ********************	


; ***************************************************************************************

; On Entry:
;   A: multiplier
;   u: multiplicand
; On Exit:
;   t: low byte of product
;   A: high byte of product
	lda multiplier
Multiply8x8:
    lsr
    sta t
    lda #0
    bcc next1
    lda u
    lsr
next1:
    ror t
    bcc next2
    clc
    adc u
next2:
    ror
    ror t
    bcc next3
    clc
    adc u
next3:
    ror
    ror t
    bcc next4
    clc
    adc u
next4:
    ror
    ror t
    bcc next5
    clc
    adc u
next5:
    ror
    ror t
    bcc next6
    clc
    adc u
next6:
    ror
    ror t
    bcc next7
    clc
    adc u
next7:
    ror
    ror t
    bcc next8
    clc
    adc u
next8:
    ror
    ror t

	sta producthigh


; ************** Stop Counter ********************		
	
	lda $9128		
	sta $FB
		
	lda producthigh
	ldy t
	jsr INTFLP		; integer to float point
	
	jsr Primm
	db $0d,$0d,"SOLUTION:",$00	
	
	jsr FLPASC
	ldy #>STACK
	lda #<STACK
	jsr STROUT
	
	
	lda #$FF
	sbc $FB
	sbc #10
	tay				; low
	
	lda #0
	jsr INTFLP		; integer to float point
	
	
	jsr Primm
	db $0d,$0d,$0d,"CYCLES:",$00	
	
	jsr FLPASC
	ldy #>STACK
	lda #<STACK
	jsr STROUT
	
		
	jmp *			; infinity jump
	
Primm:
	pla
	sta $03
	pla
	sta $04
X10D6:	
	inc $03
	bne	X10DC
	inc $04
X10DC:
	ldy #$00
	lda ($03),y
	beq X10E7
	jsr WRTF
	bcc X10D6
X10E7:
	lda $04
	pha
	lda $03
	pha
	rts	

Maybe someone has an working routine for me or some tips.

Best regards
Sven
Attachments
Program.zip
(370 Bytes) Downloaded 52 times
User avatar
Mike
Herr VC
Posts: 4841
Joined: Wed Dec 01, 2004 1:57 pm
Location: Munich, Germany
Occupation: electrical engineer

Re: Getting a signed multiply working (was: How do I print signed integer numbers?)

Post by Mike »

:?:

What's the issue with:
  • checking the sign of the number X to be printed,
  • calculating -X, if negative (i.e. forming the magnitude of the number as unsigned integer),
  • printing a minus sign, if negative, and
  • using the already available number printing routine for unsigned numbers.
That even works for the lowest representable signed integer (-32768 for 16-bit numbers, for example).
wimoos
Vic 20 Afficionado
Posts: 348
Joined: Tue Apr 14, 2009 8:15 am
Website: http://wimbasic.webs.com
Location: Netherlands
Occupation: farmer

Re: Getting a signed multiply working (was: How do I print signed integer numbers?)

Post by wimoos »

This prints signed integers (-32768 to 32767), including the sign character. It uses Zp $60-$66 and $01FF-$0210.

Code: Select all

	LDY <low byte>
	LDA <high byte>
	JSR $D395		; convert to float
	INY			; eqv. LDY #$01
	JMP $DDD7
VICE; selfwritten 65asmgen; tasm; maintainer of WimBasic
User avatar
MrSterlingBS
Vic 20 Enthusiast
Posts: 174
Joined: Tue Jan 31, 2023 2:56 am
Location: Germany,Braunschweig

Re: Getting a signed multiply working (was: How do I print signed integer numbers?)

Post by MrSterlingBS »

Thanks a lot for your answers.

Unfortunately I can't get it right yet.
I'm just trying to get this routine going.
Unfortunately it doesn't work. Neither for unsigned nor signed.

The routine is almost at the bottom of the page.
https://llx.com/Neil/a2/mult.html

Code: Select all

	INIT:
	LDA #SSQLO/256
        STA PSLO+1
        LDA #SSQHI/256
        STA PSHI+1
        LDA #DSQLO/256
        STA PDLO+1
        LDA #DSQHI/256
        STA PDHI+1
        
        CALCULATION:
        STA PSLO     ;Index into sum table by A
        STA PSHI
        EOR #$FF
        STA PDLO     ;Index into diff table by -A-1
        STA PDHI
        LDA (PSLO),Y ;Get (a+y)^2/4 (lo byte)
        SEC
        SBC (PDLO),Y ;Subtract (-a+y)^2/4 (lo byte)
        TAX          ;Save it
        LDA (PSHI),Y ;Get (a+y)^2/4 (hi byte)
        SBC (PDHI),Y ;Subtract (-a+y)^2/4 (hi byte)
        
        
User avatar
Mike
Herr VC
Posts: 4841
Joined: Wed Dec 01, 2004 1:57 pm
Location: Munich, Germany
Occupation: electrical engineer

Re: Getting a signed multiply working (was: How do I print signed integer numbers?)

Post by Mike »

MrSterlingBS wrote:Unfortunately I can't get it right yet.
With "it" you mean the signed multiply or the printout of signed integers (despite Wimoos' and mine suggestions)?
I'm just trying to get [the] routine [below] going. Unfortunately it doesn't work. Neither for unsigned nor signed.
You need the four 512 byte tables SSQLO, SSQHI, DSQLO and DSQHI set up as per the article *) and in-between the INIT and CALCULATION step, you have to load A with one of the factors (Y containing the other one).
Neil Parker wrote:*) "The tables necessary to make this work are too long to show here, so I've provided them in a separate text file. Remember, the tables have to be page-aligned, or the above code won't work."
The code uses a clever method to add two index bytes for the addressing into the tables - but even that one could be sped up by putting the routine into zero page and using ABS,Y instead of (ZP),Y. The real bottleneck then however is the actual transfer between the argument/result registers of the multiply routine and the workspace memory of the application program.

...

Looking further at how Mr. Parker builds the signed multiply, his implementation takes ages to form the possibly negative result. This can be done much faster with just a correction of the result high byte.

...

Finally - obviously your question about how to print negative numbers is the Y of your XY problem. As X, you really wanted to check a signed multiply routine and the result could be checked quite as well with a support program in BASIC. Not everything needs to be done in machine code.

(mod: topic title changed to follow suit)
User avatar
MrSterlingBS
Vic 20 Enthusiast
Posts: 174
Joined: Tue Jan 31, 2023 2:56 am
Location: Germany,Braunschweig

Re: Getting a signed multiply working (was: How do I print signed integer numbers?)

Post by MrSterlingBS »

Thanks Mike!

I had a small typo in the allocation of memory.
Now unsigned multiplication works great.

Not bad for the VIC without hardware multiplication. The 6809 need 11 cycles per hardware i think.

Mike, I had already heard about speeding up program execution by inserting code into zerospace. How does this work?

My intention to speed up these routines is to calculate the 3D routines in my other post. Marcello has a routine there where signed numbers require approx. 120-140 cycles per run. A reduction to 70-80 cycles seems realistic to me.
Attachments
Mul8x8-fast.png
Mul8x8-fast.png (1.87 KiB) Viewed 2723 times
User avatar
Mike
Herr VC
Posts: 4841
Joined: Wed Dec 01, 2004 1:57 pm
Location: Munich, Germany
Occupation: electrical engineer

Re: Getting a signed multiply working (was: How do I print signed integer numbers?)

Post by Mike »

MrSterlingBS wrote:zerospace. How does this work?
Speeding up code this way mostly involves a self-modifying part when said part only needs to use ZP instead of ABS address mode. Otherwise, code runs as fast in zero page as it does everywhere else.

One example is the CHRGET routine at $0073. It modifies TXTPTR in $7A with two INC ZP instructions. If the routine (and consequently, TXTPTR) was located outside zero page, incrementing TXTPTR would instead need two INC ABS instructions, increasing total cycle count by 2.

...

Again, the most relevant bottleneck of the multiply routine IMO is the argument/result transfer. For example, with the rotation code you want to inline the multiply code instead of going through extended parameter shuffling plus losing 12 cycles on each multiply for JSR and RTS.


P.S. "solution" as seen in the screenshot of your preceding post is a false friend here: you are not actually solving an algebraic equation for an unknown, but rather you calculate a simple arithmetic multiplication result.
Post Reply