; CSE 30. Bennet Yee . Oct 19, 1999. ; Extended macro assembly example. ; Macro to clear a memory region (clearmem), plus a few auxilliary ; macros (shift16, shift4/mul16, add). ; This handout demonstrates the concrete syntax for macros (.macro, ; .endmacro), the use of .data, .text, and .word assembler pseudo-ops, ; the triple(.,.,.) notation, local labels, and how to use ; self-modifying code to step through an array. ; XXX -- these are "generic" globals and should probably be in a ; separate, common file so they can be shared rather than repeated and ; generating name conflicts. .data zero: .word 0 ; "constant" zero ; woe if this is ever changed tmp: .word 0 ; a global tmp for goto ; add dst,a1,a2. adds contents of memory at arguments a1 and a2, ; storing the result in dst. trashes global location tmp. add: .macro dst,a1,a2 ; global tmp okay for simple .data Ltmp: .word 0 ; a private location .text subz Ltmp,Ltmp,next ; macros subz Ltmp,a1,next subz Ltmp,a2,next subz dst,dst,next subz dst,Ltmp,next .endmacro ; mul16 dst,src. takes src value and multiplies by 16, storing result ; in dst. we get 16 efficiently by using the fact that 16 = 10 + 6, ; 10 = 6 + 4, and 4 = 2 + 2. ; 11 instructions. .data mul16A: .word 0 mul16B: .word 0 mul16: .macro dst,src .text subz mul16A,mul16A,next ; 0 subz mul16B,mul16B,next ; 0 subz mul16A,src,next subz mul16A,src,next ; -2 src subz mul16B,mul16A,next subz mul16B,mul16A,next ; 4 src subz mul16A,mul16B,next ; -6 src subz dst,dst,next subz dst,mul16A,next ; 6 src subz mul16A,mul16B,next ; -10 src subz dst,mul16A,next ; 16 src == src << 4 .endmacro ; shift4 dst,src. just another name for mul16. shift4: .macro dst,src mul16 dst,src .endmacro ; shift16 dst,src. takes src value and bit-shifts to the left 16 ; positions, storing result in dst. we just invoke the shift4 macro 4 ; times. we could have tried to generate an additive sequence like ; above, but that would be too painful. we use .data s16tmp: .word 0 shift16: .macro dst,src .text shift4 s16tmp,src ; src << 4 shift4 dst,s16tmp ; src << 8 shift4 s16tmp,dst ; src << 12 shift4 dst,s16tmp ; src << 16 .endmacro ; clearmem baseaddr,count. given a baseaddr and count arguments, ; clears count words of memory starting at baseaddr. a zero count is ; handled properly. the count argument is treated as an unsigned ; value, so more than 32Kwords can be handled. trashes count, but ; leaves baseaddr alone. ; the use of self-modifying code to step through the region of memory ; from baseaddr to baseaddr+count-1 is a little tricky. make sure you ; understand how it works. .data ptr1: .word 0 ptr2: .word 0 one: .word 1 ; not needed if $1 used clear_inc: .word -triple(1,1,0) ; NOTE NEW NOTATION clearmem: .macro baseaddr, count .data L2val: .word L2 .text subz count,zero,Ldone shift16 ptr1,baseaddr shift16 ptr2,ptr1 add L1,ptr1,ptr2 add L1,L1,L2val L1: .word 0 ; initially subz baseaddr,basedarr,next L2: subz count,one,Ldone ; subz count,$1,Ldone subz L1,clear_inc,next ; change L1 to ; subz baseaddr+N,baseaddr+N,next subz tmp,tmp,L1 Ldone: .endmacro ; clearmem2 baseaddr,count. given a baseaddr and count arguments, ; clears count words of memory starting at baseaddr. a zero count is ; handled properly. the count argument is treated as an unsigned ; value, so more than 32Kwords can be handled. ; the use of self-modifying code to step through the region of memory ; from baseaddr to baseaddr+count-1 is a little tricky. make sure you ; understand how it works. .data cptr1: .word 0 cptr2: .word 0 negcount: .word 0 negone: .word -1 ; 0xffffffffffff clearmem2: .macro baseaddr, count .data L2val: .word L2 .text subz count,zero,Ldone subz negcount,negcount,next subz negcount,count,next shift16 cptr1,baseaddr shift16 cptr2,cptr1 add L1,cptr1,cptr2 add L1,L1,L2val L1: .word 0 ; initially subz baseaddr,basedarr,next L2: subz negcount,negone,Ldone ; subz negcount,$-1,done subz L1,clear_inc,next ; change L1 to ; subz baseaddr+N,baseaddr+N,next subz tmp,tmp,L1 Ldone: .endmacro