MASM/Subtraction

From Esolang
Jump to navigation Jump to search
Back to Minimal assembly language

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