CS 273

HW7 Solution

Multiple-Precision Arithmetic

  1. Write a 32-bit addition routine. It should take three parameters, passed on the stack: the addresses of the two operands (pushed first), and then the address of the result. These are all sixteen bit addresses. Your procedure should perform the addition, and correctly set the NZVC condition code bits.

  2. Write a procedure which will multiply two 16-bit operands, generating a 32 bit result. Once again, it should take three parameters from the stack: the addresses of the two operands (pushed first), and then the address of the result. If your procedure requires any extra space (and it almost certainly will) it should allocate this space on the stack.

    Hint: It is possible to build this procedure on top of the MUL instruction. Here's a picture of the basic idea:

    
    
    
    
    
    ***************** PROGRAM 1 ************************
    
    
    **********************************************************
    *Strategy:  consider a + b = c.
    *	we do:
    *		1. copy a into c; 
    *		2. add b to c.
    *	During step 2, we do four one-byte addition 
    *	backwards from  the last bytes of the operands.
    *	Except the very first one-byte addition, we 
    *	use addition instructions which take the carry 
    *	bit such as ADCA, ADCB.  
    **********************************************************
    
    	org	$0000
    
    c	rmb	4
    
    	org	$f800
    
    a	fcb	$0f,$f9,$f0,$e9
    b	fcb	$f2,$20,$10,$28
    * expect   c =  $02,$1a,$01,$11
    
    main	lds	#$00ff
    	ldx	#a	*pass the address of the first operand,a
    	pshx	
    	ldx	#b	*pass the address of the second operand,b
    	pshx	
    	ldx	#c	*pass the address of the result, c
    	pshx	
    	jsr	add32   *call the subroutine
    	ins            	*restore the stack
    	ins
    	ins
    	ins
    	ins
    	ins
    
    eloop	bra	eloop
    
    
    add32	
    *       push the current environment
    	pshx	      	*push X
    	pshy          	*push Y
    	psha          	*push A
    	pshb          	*push B
    
    *	copy the first operand into the result 	
    	tsx	      	
    	ldy	8,x   	*get the address of the result into Y
    	ldx	12,x  	*get the address of the operand  a into X
    	ldd	0,x   	*read the two higher bytes of operand a into D
    	std	0,y   	*store them to the two higher bytes of result 
    	inx
    	inx
    	iny
    	iny
    	ldd	0,x   	*read the two lower bytes of operand a into D
    	std	0,y   	*store them to the two lower bytes of result 
    
    *	get ready for one-byte addition from the end of the operands 
    	iny	      	*let Y currently index to the last byte of the result
    	tsx	      	
    	ldx	10,x  	*get the address of the operand b into X
    	inx	      	*let X currently index to the last byte of operand b
    	inx
    	inx
    
    *	perform the addition byte by byte backwards from the end
    
    *	current position is the fourth byte 
    	ldaa	0,x	*get the current byte of operand b
    	adda	0,y	*add the current byte of the result (actually operand a) 
    	staa	0,y	*update the current byte of the result
    	dex		
    	dey
    
    *	current position is the third byte 
    	ldaa	0,x	*get the current byte of operand b
    	adca	0,y	*add the current byte of the result (actually operand a) 
    	staa	0,y	*update the current byte of the result
    	dex		
    	dey
    
    *	current position is the second byte 
    	ldaa	0,x	*get the current byte of operand b
    	adca	0,y	*add the current byte of the result (actually operand a) 
    	staa	0,y	*update the current byte of the result
    	dex		
    	dey
    
    *	current position is the first byte 
    	ldaa	0,x	*get the current byte of operand b
    	adca	0,y	*add the current byte of the result (actually operand a) 
    	staa	0,y	*update the current byte of the result
    
    	pulb          *pop B
    	pula          *pop A
    	puly          *pop Y
    	pulx          *pop X
    
    	rts
    
    	end	main
    
    
    
    
    
    
    
    
    
    
    *********************** PROGRAM 2 ***********************
    
    
    **********************************************************
    *Strategy:  consider PQ * UV = R.
    *	step 1: initialize R
    *	step 2: compute Q*V and add it appropriately to R 
    *	step 3: compute P*V and add it appropriately to R 
    *	step 4: compute Q*U and add it appropriately to R 
    *	step 5: compute P*U and add it appropriately to R 
    *
    **********************************************************
    
    	org	$0000
    
    c	rmb	4
    
    	org	$f800
    
    a	fcb	$01,$00	* P Q 
    b	fcb	$01,$00	* U V
    * expect c  =   $00,$01,$00,$00
    
    main	lds	#$00ff
    	ldx	#a	*pass the address of the first operand,a
    	pshx	
    	ldx	#b	*pass the address of the second operand,b
    	pshx	
    	ldx	#c	*pass the address of the result, c
    	pshx	
    	jsr	mul16   *call the subroutine
    	ins            	*restore the stack
    	ins
    	ins
    	ins
    	ins
    	ins
    
    eloop	bra	eloop
    
    
    mul16	
    *       push the current environment
    	pshx	      	*push X
    	pshy          	*push Y
    	psha          	*push A
    	pshb          	*push B
    
    *=======step 1: initialize the result with zero
    
    	tsx	      	
    	ldx	8,x  	*get the address of the result into X
    	clra
    	staa	0,x	
    	staa	1,x	
    	staa	2,x	
    	staa	3,x	
    
    *=======step 2: computing and store the effect of Q*V
    
    *	1.get Q and V
    	tsx	      	
    	ldx	12,x  	*get the address of the operand  a into X
    	ldaa	1,x  	*get Q into A
    	tsx	      	
    	ldx	10,x  	*get the address of the operand  b into X
    	ldab	1,x  	*get V into B
    
    *	2.compute Q*V
    	mul		*Q*V is now in accumulator D
    
    *	3.store Q*V into the result appropriately	
    	tsx	      	
    	ldx	8,x  	*get the address of the result into X
    	std	2,x	
    
    *=======step 3: computing and store the effect of P*V
    
    *	1.get P and V
    	tsx	      
    	ldx	12,x  	*get the address of the operand  a into X
    	ldaa	0,x  	*get P into A
    	tsx	      	
    	ldx	10,x  	*get the address of the operand  b into X
    	ldab	1,x  	*get V into B
    
    *	2.compute P*V
    	mul		*P*V is now in accumulator D
    
    *	3.store P*V into the result appropriately
    	tsx	      
    	ldx	8,x  	*get the address of the result into X
    	addb	2,x	*add B to the third byte (from left) of result 
    	stab	2,x	
    	adca	1,x	*add A to the second byte of result 
    	staa	1,x	
    	bcs	t1	*if there is a carry,add it to the first byte of result 
    	bra	qu
    t1	inc	0,x	
    
    *=======step 4: computing and store the effect of Q*U
    
    qu
    *	1.get Q and U 
    	tsx	      
    	ldx	12,x  	*get the address of the operand  a into X
    	ldaa	1,x  	*get Q into A
    	tsx	      	
    	ldx	10,x  	*get the address of the operand  b into X
    	ldab	0,x  	*get U into B
    
    *	2.compute Q*U
    	mul		*Q*U is now in accumulator D
    
    *	3.store Q*U into the result appropriately
    	tsx	      	
    	ldx	8,x  	*get the address of the result into X
    	addb	2,x	*add B to the third byte (from left) of result 
    	stab	2,x	
    	adca	1,x	*add A to the second byte of result 
    	staa	1,x	
    	bcs	t2	*if there is a carry,add it to the first byte of result 
    	bra	pu
    t2	inc	0,x	
    
    
    *=======step 5: computing and store the effect of P*U
    
    pu
    *	1.get P and V
    	tsx	      
    	ldx	12,x  	*get the address of the operand  a into X
    	ldaa	0,x  	*get P into A
    	tsx	      	
    	ldx	10,x  	*get the address of the operand  b into X
    	ldab	0,x  	*get U into B
    
    *	2.compute Q*U
    	mul		*Q*U is now in accumulator D
    
    *	3.store P*U into the result appropriately
    	tsx	      	
    	ldx	8,x  	*get the address of the result into X
    	addb	1,x	*add B to the third byte (from left) of result 
    	stab	1,x	
    	adca	0,x	*add A to the second byte of result 
    	staa	0,x	
    
    	pulb		*pull the saved environment
    	pula
    	puly
    	pulx
    
    	rts
    
    	end	main