org $3000 START * tests each function (data are at end) * macro for printing (d1.l) as long print MACRO move.l #3,d0 ; print long trap #15 move.l #0,d0 ; print newline move.w #0,d1 trap #15 ENDM _main: * 1. test _max move.w #N,-(sp) pea SHORTS jsr _max adda.w #6,sp clr.l d1 move.w d0,d1 print * 2. test _compress move.w #M,-(sp) pea COMP pea BCDS jsr _compress adda.w #10,sp ; inspect memory to verify (exercise in memory layout) * 3. test _floor_mean suba.w #2,sp pea (sp) move.w #N,-(sp) pea SHORTS jsr _floor_mean adda.w #10,sp clr.l d1 move.w (sp)+,d1 print * 4. test _delta move.w #N,-(sp) pea DEST pea SHORTS jsr _delta adda.w #10,sp ; inspect memory to verify (exercise in 2s complement) move.l #9,d0 ; exit trap #15 ******************************************************************************* _max: move.l 4(sp),a0 ; table move.w 8(sp),d1 ; n beq exit0 ; if n == 0, rv is undefined move.l a0,a1 lsl.w #1,d1 ; x2 because shorts adda.w d1,a1 ; point to end of table move.w (a0)+,d0 ; first value from table loop0 move.w (a0)+,d1 cmp.w d1,d0 bcc skip0 move.w d1,d0 ; new max skip0 cmpa.l a0,a1 bne loop0 exit0 rts ******************************************************************************* _compress: move.l 4(sp),a0 ; source move.l 8(sp),a1 ; dest clr.w d0 move.w 12(sp),d1 ; n beq exit1 ; if n == 0, nothing to do (return 0) move.w #-1,d0 btst #0,d1 ; is n odd? bne exit1 ; if so, error (return -1) subi.w #1,d1 ; for dbf loop1 move.b (a0)+,d0 lsl.b #4,d0 ; upper nibble or.b (a0)+,d0 ; lower nibble move.b d0,(a1)+ dbf d1,loop1 clr.w d0 ; return 0 exit1 rts ******************************************************************************* _floor_mean: move.l 4(sp),a0 ; table move.w 8(sp),d1 ; n beq error2 ; if n == 0, return -1 clr.w d0 ; accumulator subi.w #1,d1 loop2 add.w (a0)+,d0 ; compute sum bcs error2 dbf d1,loop2 andi.l #$FFFF,d0 ; clear upper word for divu divu 8(sp),d0 ; no overflow possible move.l 10(sp),a0 ; rv move.w d0,(a0) ; write d0 to rv clr.w d0 ; no error bra exit2 error2 move.w #-1,d0 exit2 rts ******************************************************************************* _delta: link a6,#0 movem.w d2-d3,-(sp) ; only need to preserve d2 clr.w d0 tst.w 16(a6) ; n beq exit3 ; if n == 0, nothing to do (return 0) * call floor_mean suba.w #2,sp ; make space for rv on stack (-A) pea (sp) ; pass pointer to this stack space as rv (-B) move.w 16(a6),-(sp) ; n (-B) move.l 8(a6),-(sp) ; table (-B) jsr _floor_mean adda.l #10,sp ; restore stack from pushed arguments (+B) move.w (sp)+,d1 ; fetch floor_mean, recover space for rv (+A) tst.w d0 bne exit3 ; error occurred, so return error * result of floor_mean is in d1 move.l 8(a6),a0 ; table move.l 12(a6),a1 ; delta move.w 16(a6),d2 ; n move.w #-1,d0 ; error if exit early subi.w #1,d2 ; for dbf loop3 move.w (a0)+,d3 ; entry from table btst #15,d3 ; negative viewed as signed number? bne exit3 ; error sub.w d1,d3 ; compute difference from floor_mean move.w d3,(a1)+ ; store in delta dbf d2,loop3 clr.w d0 exit3 movem.w (sp)+,d2-d3 ; restore d2 unlk a6 rts ******************************************************************************* * data for _main SHORTS dc.w 13, 59, 691, 23, 412, 191, 65, 0, 170 E_SHORTS N equ (E_SHORTS-SHORTS)/2 DEST ds.w N BCDS dc.b $c, $0, $d, $e E_BCDS M equ E_BCDS-BCDS COMP ds.b M/2 end START