# Multiplikation von 2 16-bit-Zahlen

Wenn wir schriftlich zwei Zahlen multiplizieren, kommen immer größere Zahlen heraus, als jeder der beiden Faktoren.

Beispiel: 999 * 99999 = 99899001

Weil hier eine dreistellige Zahl mit einer fünfstelligen Zahl multipliziert wurde, kann das Ergebnis achtstellig sein.

Das ist bei Binärzahlen genauso:

Wenn eine 8-Bit-Zahl mit einer 8-Bit-Zahl multipliziert wird, wird ein 16-bit-Ergebnis herauskommen.

## Der Programmcode 16 bit mal 16 bit ergibt 32 bit

// This routine multiplies two 16 bit integers,
// The return value is a 32 bit integer
//

#include <heport.h>
#include <heimath.h>		// definition of mul_uw_uw
#ifdef AVR
#include <avr/io.h>
#endif

#ifndef AVR
// Other processors do not need speed up
FUNCT uint32_t mul_uw_uw( uint16_t x , uint16_t y )
{
uint32_t res ;

res = (uint32_t)x * (uint32_t)y ;
return res ;
}

#else

#if !defined(__AVR_HAVE_MUL__) /* Software- Multiply */
// input:
// r23_r22 = x.h_x.l
// r25_r24 = y.h_y.l
// may destroy r18 r19 r20 r21 r22 r23 r24* r25* r26* r27*
// may not destroy r14 r15 r16 r17 r28=YL r29=YH
// return r25_r24_r23_r22

FUNCT uint32_t dummy_mul_uw_uw( uint16_t x , uint16_t y )
{

// asm(" .text " "\n");
asm(" ; " "\n");
asm("  .global mul_uw_uw" "\n");
asm(" ; See as well mul_uc_uc : 8 bit by 8 bit, result 16 bits " "\n");
asm(" ; " "\n");
asm(" ; Function mul_uw_uw " "\n");
asm(" ; multiply unsigned 16 bit by 16 bit " "\n");
asm(" ; " "\n");
asm(" ; Input: " "\n");
asm(" ;     r23:r22   : The factor x " "\n");
asm(" ;     r25:r24   : The factor y " "\n");
asm(" ; Results " "\n");
asm(" ;     r25:r24:r23:r22    : result " "\n");
asm(" ; Destroyed registers " "\n");
asm(" ;     none " "\n");
asm(" ; This program is verified by qqarith.asm " "\n");
asm(" ; " "\n");
//asm(" _Z9mul_uw_uwtt: " "\n");
asm("mul_uw_uw: " "\n");
asm(" 	push r16 ; " "\n");
asm(" 	push r18 ; " "\n");
asm(" 	push r19 ; " "\n");
asm(" 	push r20 ; " "\n");
asm(" 	push r21 ; " "\n");
asm(" 	push r26 ; " "\n");
asm(" 	push r27 ; " "\n");
asm(" ; Clear start values " "\n");
#ifdef __AVR_HAVE_MOVW__
asm(" 	movw r26,r22 ; factor x to interim storage " "\n");
asm(" 	movw r18,r24 ; factor y to interim storage , extend" "\n");
#else
asm(" 	mov r26,r22 ; factor x to interim storage " "\n");
asm(" 	mov r27,r23 " "\n");
asm(" 	mov r18,r24 ; factor y to interim storage , extend" "\n");
asm(" 	mov r19,r25 " "\n");
#endif
asm(" 	clr r20 " "\n");
asm(" 	clr r21 " "\n");
asm(" ; Clear result r25:r24;r23;r22 " "\n");
asm(" 	clr r22 " "\n");
asm(" 	clr r23 " "\n");
asm(" 	clr r24 " "\n");
asm(" 	clr r25 " "\n");
asm(" ; " "\n");
asm(" mul_uw_uw_3: " "\n");
asm(" 	lsr	r27 ; shift x" "\n");
asm(" 	ror	r26		; next binary digit of right factor to carry " "\n");
asm(" 	brcc	mul_uw_uw_4 " "\n");
asm(" ; Add the (shifted) left factor into result " "\n");
asm(" mul_uw_uw_4: " "\n");
asm(" ; shift the factor y by 1 bit to left" "\n");
asm(" 	mov	r16,r26		; no more of right factor left " "\n");
asm(" 	or	r16,r27 " "\n");
asm(" 	brne mul_uw_uw_3 " "\n");
asm(" ; result is 32 bits in r25:r24:r23:r22 " "\n");
asm(" 	pop	r27 " "\n");
asm(" 	pop	r26 " "\n");
asm(" 	pop	r21 " "\n");
asm(" 	pop	r20 " "\n");
asm(" 	pop	r19 " "\n");
asm(" 	pop	r18 " "\n");
asm(" 	pop	r16 " "\n");
// asm(" 	ret " "\n");

// The warning here is intentionally expected. a dummy return would waste 8 words
// return 0 ;
}

#else

// Hardware multiply MUL
// input:
// r23_r22 = x.h_x.l
// r25_r24 = y.h_y.l
// may destroy r18 r19 r20 r21 r22 r23 r24* r25* r26* r27*
// may not destroy r14 r15 r16 r17 r28=YL r29=YH
// return r25_r24_r23_r22

FUNCT int32_t dummy_mul_uw_uw( int16_t x , int16_t y )
{
//asm(" .text " "\n");
asm(" .global mul_uw_uw" "\n");
asm(" ; See as well mul_uc_uc : 8 bit by 8 bit, result 16 bits " "\n");
asm(" ; " "\n");
asm(" ; Function mul_uw_uw " "\n");
asm(" ; multiply unsigned 16 bit by 16 bit " "\n");
asm(" ; " "\n");
asm(" ; Input: " "\n");
asm(" ;     r23:r22   : The factor " "\n");
asm(" ;     r25:r24   : The factor " "\n");
asm(" ; Results " "\n");
asm(" ;     r25:r24:r23:r22    : result" "\n");
asm(" ; r1 = 0 (as it is GCC standard)" "\n" );
asm(" ; Destroyed registers " "\n");
asm(" ;     ro (as allows GCC standard) " "\n");
asm(" ; This program is verified by qqarith.asm " "\n");
asm(" ; " "\n");
//asm(" _Z9mul_uw_uwtt: " "\n");
asm("mul_uw_uw: " "\n");
asm(" 	push r18 ; " "\n");
asm(" 	push r19 ; " "\n");
asm(" 	push r20 ; " "\n");
asm(" 	push r21 ; " "\n");
#ifdef __AVR_HAVE_MOVW__
asm(" 	movw r20,r22 ; factor x to interim storage " "\n");
asm(" 	movw r18,r24 ; factor y to interim storage " "\n");
#else
asm(" 	mov r20,r22 ; factor x to interim storage " "\n");
asm(" 	mov	r21,r23 " "\n");
asm(" 	mov r18,r24 ; factor y to interim storage " "\n");
asm(" 	mov	r19,r25 " "\n");
#endif

asm(" 	mul	r20,r18 ; low byte * low byte" "\n" );
#ifdef __AVR_HAVE_MOVW__
asm(" 	movw	r22,r0 ; low result word" "\n" );
#else
asm(" 	mov	r22,r0 ; low result word" "\n" );
asm(" 	mov	r23,r1 ; low result word" "\n" );
#endif
asm(" 	mul	r21,r19 ; high byte * high byte" "\n" );
#ifdef __AVR_HAVE_MOVW__
asm(" 	movw	r24,r0 ; high result word" "\n" );
#else
asm(" 	mov	r24,r0 ; high result word" "\n" );
asm(" 	mov	r25,r1 ; high result word" "\n" );
#endif
asm(" 	mul	r20,r19 ; low byte * high byte" "\n" );
asm(" 	add	r23,r0 ; medium result word" "\n" );
asm(" 	adc	r24,r1 ; medium result word" "\n" );
asm(" 	clr	r1 ; does not modify Carry flag" "\n" );
asm(" 	adc	r25,r1 ; carry to highest byte" "\n" );
asm(" 	mul	r21,r18 ; low byte * high byte" "\n" );
asm(" 	add	r23,r0 ; medium result word" "\n" );
asm(" 	adc	r24,r1 ; medium result word" "\n" );
asm(" 	clr	r1 ; does not modify Carry flag" "\n" );
asm(" 	adc	r25,r1 ; carry to highest byte" "\n" );
asm(" ; result is 32 bits in r25:r24:r23:r22 " "\n");
asm(" 	pop	r21 " "\n");
asm(" 	pop	r20 " "\n");
asm(" 	pop	r19 " "\n");
asm(" 	pop	r18 " "\n");
// asm(" 	ret " "\n");

// The warning here is intentionally expected. a dummy return would waste 8 words
// return 0 ;
}

#endif

#endif


Der Aufruf aus C erfolgt z.B. so:

uint32_t erg ;
uint16_t f1 ;
uint16_t f2 ;

erg = mul_uw_uw(f1,f2);