MASM/Subtraction

:
==globals.masm==
 nine ptr-size
 old-ipt
 arg
 arg1
 arg2
 ret
==if-else.masm==
 tmp
 not-four
 offset
 arg-as-bool-times-eight
 
 lab if-else
 alc one
 get arg
 fre arg
 nnd vpt
 set tmp
 
 cmt tmp = arg except it's 0x00 if zero and 0xff otherwise
 alc one
 get tmp
 rot one
 nnd tmp
 fre tmp
 nnd vpt
 set tmp
 
 alc one
 get tmp
 rot one
 nnd tmp
 fre tmp
 nnd vpt
 set tmp
 
 alc one
 get tmp
 rot one
 nnd tmp
 fre tmp
 nnd vpt
 set tmp
 
 alc one
 get tmp
 rot one
 nnd tmp
 fre tmp
 nnd vpt
 set tmp
 
 alc one
 get tmp
 rot one
 nnd tmp
 fre tmp
 nnd vpt
 set tmp
 
 alc one
 get tmp
 rot one
 nnd tmp
 fre tmp
 nnd vpt
 set tmp
 
 alc one
 get tmp
 rot one
 nnd tmp
 fre tmp
 set tmp
 
 cmt tmp (which is 0x00 or 0xff) is converted to 0x00 (arg = 0)
 cmt or 0x08 (arg = nonzero) to potentially skip commands
 alc one
 get tmp
 fre tmp
 nnd one
 nnd vpt
 rot one
 rot one
 rot one
 rot one
 rot one
 set arg-as-bool-times-eight
 
 cmt not-four = 4 nand 4
 alc one
 get one
 rot one
 rot one
 rot one
 rot one
 rot one
 rot one
 nnd vpt
 set not-four
 
 cmt combines arg-as-bool-times-eight and not-four to create
 cmt either 4 or 12
 alc one
 get arg-as-bool-times-eight
 fre arg-as-bool-times-eight
 nnd vpt
 nnd not-four
 fre not-four
 set offset
 
 cmt adds offset (which is either 4 or 12) to ipt
 cmt to call either function A (if it's 4) or B
 cmt (if it's 12)
 alc ptr-size
 set tmp
 adr ipt
 get offset
 drf vpt
 fre tmp
 set ipt
 
 cmt call arg2. this will be skipped if arg
 cmt equals 0, in which case offset equals 4.
 cmt not how old-ipt isn't changed, so the label
 cmt arg2 is pointing to will move ipt back to
 cmt where it was before calling this if/else
 cmt statement
 fre offset
 alc ptr-size
 set tmp
 adr arg2
 drf vpt
 fre tmp
 set ipt
 
 cmt noop (could be anything; won't be executed
 cmt anyways) so ipt doesn't jump to the wrong place
 cmt when offset is added
 set vpt
 
 cmt call arg1 if offset doesn't equal 0, in
 cmt which case offset equals 12
 fre offset
 alc ptr-size
 set tmp
 adr arg1
 drf vpt
 fre tmp
 set ipt
==addition-and-subtraction.masm==
 add
 negative
 return-arg-or-arg1
 return-arg-xor-arg1-plus-carry
 if-else
 tmp
 carry
 arg-cpy
 arg1-cpy
 old-old-ipt
 arg1-cpy-for-subtract
 
 lab return-arg-or-arg1
 alc one
 set tmp
 get arg-cpy
 nnd vpt
 alc one
 get arg1-cpy
 nnd vpt
 nnd tmp
 fre tmp
 set ret
 
 fre arg-cpy
 fre arg1-cpy
 
 alc ptr-size
 set tmp
 adr old-ipt
 get nine
 drf vpt
 fre tmp
 set ipt
 
 lab return-arg-xor-arg1-plus-carry
 cmt tmp = arg-cpy or arg1-cpy
 alc one
 set tmp
 get arg-cpy
 nnd vpt
 alc one
 get arg1-cpy
 nnd vpt
 nnd tmp
 fre tmp
 set tmp
 
 cmt arg = (arg-cpy nand arg1-cpy) and tmp
 cmt = (arg-cpy nand arg1-cpy) and (arg-cpy or arg1-cpy)
 cmt = arg-cpy xor arg1-cpy
 alc one
 get arg-cpy
 nnd arg1-cpy
 nnd tmp
 fre tmp
 nnd vpt
 set arg
 
 cmt tmp = (arg-cpy and arg1-cpy) << 1
 alc one
 get arg-cpy
 nnd arg1-cpy
 nnd vpt
 rot one
 rot one
 rot one
 rot one
 rot one
 rot one
 rot one
 set tmp
 
 cmt arg1 = tmp and (not one) = (arg-cpy and arg1-cpy) * 2
 alc one
 get one
 nnd vpt
 nnd tmp
 nnd vpt
 fre tmp
 set arg1
 
 fre arg-cpy
 fre arg1-cpy
 
 cmt call add
 alc ptr-size
 set tmp
 adr add
 drf vpt
 fre tmp
 set ipt
 
 lab add
 cmt copies args to new variables
 alc one
 get arg
 fre arg
 set arg-cpy
 alc one
 get arg1
 fre arg1
 set arg1-cpy
 
 cmt arg = arg-cpy and arg1-cpy
 alc one
 get arg-cpy
 nnd arg1-cpy
 nnd vpt
 set arg
 
 cmt arg1 = return-arg-xor-arg1-plus-carry
 alc ptr-size
 set tmp
 adr return-arg-xor-arg1-plus-carry
 drf vpt
 fre tmp
 set arg1
 
 cmt arg2 = return-arg-or-arg1
 alc ptr-size
 set tmp
 adr return-arg-or-arg1
 drf vpt
 fre tmp
 set arg2
 
 cmt goto if-else. old-ipt doesn't need to be
 cmt initialized, because this function will be
 cmt left by ipt anyways
 alc ptr-size
 set tmp
 adr if-else
 drf vpt
 fre tmp
 set ipt
 
 cmt -x = ~x + 1
 lab negative
 cmt arg = ~arg
 alc one
 get arg
 fre arg
 nnd vpt
 set arg
 
 cmt arg1 = 1
 alc one
 get one
 set arg1
 
 cmt call add. old-ipt isn't initialized because
 cmt this function is finished anyways
 alc ptr-size
 set tmp
 adr add
 drf vpt
 fre tmp
 set ipt
 
 lab subtract
 cmt swap arg and arg1 so arg1 is made negative instead of arg
 cmt arg1 will be changed by negative because it calls add,
 cmt so it's instead copied. even arg1-cpy is, however, changed
 cmt by add, so we need a third buffer to store arg1 in
 alc one
 get arg
 fre arg
 set tmp
 alc one
 get arg1
 set arg
 alc one
 get tmp
 fre tmp
 set arg1-cpy-for-subtract
 
 cmt old-old-ipt = old-ipt
 alc ptr-size
 set tmp
 adr old-ipt
 drf vpt
 fre tmp
 set old-old-ipt
 
 cmt init old-ipt
 alc ptr-size
 set tmp
 adr ipt
 drf vpt
 fre tmp
 set old-ipt
 
 cmt call negative
 alc ptr-size
 set tmp
 adr negative
 drf vpt
 fre tmp
 set ipt
 
 alc one
 get ret
 fre ret
 set arg
 
 alc one
 get arg1-cpy-for-subtract
 fre arg1-cpy-for-subtract
 set arg1
 
 cmt old-ipt = old-old-ipt so add makes ipt jump back
 cmt to where it was before calling subtract
 alc ptr-size
 set tmp
 adr old-old-ipt
 drf vpt
 fre tmp
 set old-ipt
 
 cmt call add
 alc ptr-size
 set tmp
 adr add
 drf vpt
 fre tmp
 set ipt
==main.masm==
 add
 subtract
 loop
 tmp
 _48
 two
 new-out
 
 lab loop
 alc ptr-size
 set tmp
 adr loop
 drf vpt
 set ipt
 
 lab main
 cmt contruct nine (aka ptr-size)
 alc one
 get one
 rot one
 rot one
 rot one
 rot one
 rot one
 nnd vpt
 set tmp
 alc one
 get one
 nnd vpt
 nnd tmp
 fre tmp
 set nine
 
 cmt 48 = 0b00110000
 alc one
 get one
 rot one
 rot one
 rot one
 nnd vpt
 set tmp
 alc one
 get one
 rot one
 rot one
 rot one
 rot one
 nnd vpt
 nnd tmp
 fre tmp
 set _48
 
 
 cmt 48 will be subtracted from in[1] to convert it
 cmt to an integer (48 is the ascii value of '0')
 alc ptr-size
 set tmp
 adr in
 get one
 drf vpt
 fre tmp
 set tmp
 alc one
 get tmp
 set arg
 
 alc one
 get _48
 set arg1
 
 cmt init old-ipt
 alc ptr-size
 set tmp
 adr ipt
 drf vpt
 fre tmp
 set old-ipt
 
 cmt call subtract
 alc ptr-size
 set tmp
 adr subtract
 drf vpt
 fre tmp
 set ipt
 
 fre _48
 
 cmt arg1 = input[1] as number
 alc one
 get ret
 fre ret
 set arg1
 
 cmt arg = input[0] as char (copied because arg1 will be freed by add)
 alc one
 get in
 set arg
 
 cmt init old-ipt
 alc ptr-size
 set tmp
 adr ipt
 drf vpt
 fre tmp
 set old-ipt
 
 cmt call add
 alc ptr-size
 set tmp
 adr subtract
 drf vpt
 fre tmp
 set ipt
 
 cmt init two
 alc one
 get one
 rot one
 rot one
 rot one
 rot one
 rot one
 rot one
 rot one
 set two
 
 cmt new-out[0] = ret
 alc two
 set new-out
 get ret
 fre ret
 
 cmt new-out[1] = 0
 alc ptr-size
 set tmp
 adr new-out
 get one
 drf vpt
 fre tmp
 get out
 
 cmt out = new-out
 alc ptr-size
 set tmp
 adr new-out
 drf vpt
 fre tmp
 set out
 
 cmt goto loop
 alc ptr-size
 set tmp
 adr loop
 drf vpt
 set ipt
Category:Examples