aforth

FORTH for Linux x86-64, written in assembly.
git clone git://henryandlizzy.uk/aforth
Log | Files | Refs | README

commit b4d34d17bd62e9cab9862492ea44efc0af74081f
parent 7912e92df0558c6d8578fa860f7067eb176d79a7
Author: Henry Wilson <m3henry@googlemail.com>
Date:   Tue,  1 Aug 2017 00:30:57 +0100

split source file up in to categories

Diffstat:
Aboolean.s | 46++++++++++++++++++++++++++++++++++++++++++++++
Acompiler.s | 49+++++++++++++++++++++++++++++++++++++++++++++++++
Adictionary.s | 43+++++++++++++++++++++++++++++++++++++++++++
Aextras.s | 26++++++++++++++++++++++++++
Ainput.s | 55+++++++++++++++++++++++++++++++++++++++++++++++++++++++
Minput.txt | 2+-
Ainterpreter.s | 87+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mmain.s | 710++-----------------------------------------------------------------------------
Amaths.s | 120+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amemory.s | 104+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aoutput.s | 85+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Astack.s | 76++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12 files changed, 702 insertions(+), 701 deletions(-)

diff --git a/boolean.s b/boolean.s @@ -0,0 +1,46 @@ +# Logic + +verb code TRUE + _dup + movq $-1, TOS + jmp next + +verb code FALSE "0" + _dup + xor TOS, TOS + jmp next + +verb code lshift "<<" + minstk 1 + shl TOS + jmp next + +verb code rshift ">>" + minstk 1 + shr TOS + jmp next + +verb code halve "2/" + minstk 1 + sar TOS + jmp next + +verb code NOT + minstk 1 + not TOS + jmp next + +verb code AND + minstk 2 + and TOS, (SP) + jmp _drop + +verb code OR + minstk 2 + or TOS, (SP) + jmp _drop + +verb code XOR + minstk 2 + xor TOS, (SP) + jmp _drop diff --git a/compiler.s b/compiler.s @@ -0,0 +1,49 @@ +# Compiler + +verb forth HERE + variable + endword + +verb forth modeI "[" immediate + set MODE 0 + endword + +verb forth modeC "]" + set MODE -1 + endword + +verb forth ALLOT + get HERE + do plus + set HERE + endword + +verb forth COMPILE "COMPILE" immediate + get HERE + do store + const 8 + do ALLOT + endword + +verb forth compnew "\x3A" # : + do modeC + get HERE + get LAST + do COMPILE + do WORD + do fetch + const 8 + do plus + do ALLOT + do TRUE + do COMPILE + const enter + do COMPILE + endword + +verb forth compend "\x3B" immediate # ; + const EXIT + do COMPILE + do modeI + set LAST + endword diff --git a/dictionary.s b/dictionary.s @@ -0,0 +1,43 @@ +# Dictionary + +verb forth LAST + variable + endword + +verb forth DICTIONARY + get LAST +2: do DUP + do fetch + const 0 + do equal + if 1f + do DUP + const 8 + do plus + do PRINT + do fetch + do SPACE + goto 2b +1: do DROP + endword + +verb forth FIND + get LAST +2: do dup2 + const 8 + do plus + do STRCMP + unless 1f + const 24 + do plus + do SWAP + do fetch + do plus + do TRUE + endword +1: do fetch + do DUP + if 2b + do DROP + do FALSE + endword diff --git a/extras.s b/extras.s @@ -0,0 +1,26 @@ +# User Words + +verb forth greet GREET + say "Hello, World!" + do CR + endword + +verb forth FLAG + 1: do OVER + do line + do dec + do DUP + if 1b + do DROP + do DROP + endword + +line: forthword + 1: const '*' + do EMIT + do dec + do DUP + if 1b + do DROP + do CR + endword diff --git a/input.s b/input.s @@ -0,0 +1,55 @@ +# Input + +verb forth TIB + scratch 80 + endword + +verb forth numtib "\#TIB" + variable + endword + +verb forth numin "\#IN" + variable + endword + +verb code ACCEPT + minstk 2 + mov $0, CMD + mov $0, ARGA + mov (SP), ARGB + mov TOS, ARGC + syscall + mov CMD, (SP) + jmp _drop + +verb forth WORD + get HERE + const 0 + do OVER + do store + const 8 + do plus +1: get numin + get numtib + do gequal + if 3f + do TIB + get numin + do plus + do fetchb + do numin + do incaddr + do DUP + const ' ' + do lequal + if 2f + get HERE + do incaddr + do OVER + do storeb + do inc + goto 1b + 2: do DROP +3: do DROP + get HERE + endword diff --git a/input.txt b/input.txt @@ -4,4 +4,4 @@ GREET 8 3 FLAG : SQUARE DUP * ; 12 SQUARE . CR -HALT +CR DICTIONARY CR diff --git a/interpreter.s b/interpreter.s @@ -0,0 +1,87 @@ +# Interpreter + +verb forth MODE + variable + endword + +verb forth INTERPRET + set numin 0 + 3: do WORD + do DUP + do fetch + if 0f + do DROP + goto 2f + 0: do FIND + if 1f + const 0 + do SWAP + do DUP + const 8 + do plus + do SWAP + do fetch + do CONVERT + do drop2 + test greater 0 2f + do DROP + get HERE + escape 91 + say "Unknown token: " + do PRINT + do CR + do ABORT + goto 2f + 1: do DUP + const 8 + do minus + do fetch + get MODE + do AND + if 1f + do EXECUTE + goto 2f + 1: do COMPILE + 2: get numin + get numtib + do less + if 3b + escape 92 + do DEPTH + test equal 0 4f + say " ⏎ " + test equal 1 5f + do DUP + do dot +5: do DROP + say "[" + do DUP + do dot + saycr "]" + endword +4: do DROP + saycr " 🗸" + endword + +verb forth CONVERT +2: test equal 0 1f + do pushret + do DUP + do pushret + do fetchb + const '0' + do minus + test greater 9 0f + do SWAP + const 10 + do mult + do plus + do popret + do inc + do popret + do dec + goto 2b +0: do DROP + do popret + do popret +1: endword diff --git a/main.s b/main.s @@ -76,518 +76,20 @@ verb forth QUIT escape 0 do HALT -# Interpreter - -verb forth PAD - scratch 90 - endword - -verb forth TIB - scratch 80 - endword - -verb forth numtib "\#TIB" - variable - endword - -verb forth numin "\#IN" - variable - endword - -verb forth MODE - variable - endword - -verb forth INTERPRET - set numin 0 - 3: do WORD - do DUP - do fetch - if 0f - do DROP - goto 2f - 0: do FIND - if 1f - const 0 - do SWAP - do DUP - const 8 - do plus - do SWAP - do fetch - do CONVERT - do drop2 - test greater 0 2f - do DROP - get HERE - escape 91 - say "Unknown token: " - do PRINT - do CR - do ABORT - goto 2f - 1: do DUP - const 8 - do minus - do fetch - get MODE - do AND - if 1f - do EXECUTE - goto 2f - 1: do COMPILE - 2: get numin - get numtib - do less - if 3b - escape 92 - do DEPTH - test equal 0 4f - say " ⏎ " - test equal 1 5f - do DUP - do dot -5: do DROP - say "[" - do DUP - do dot - saycr "]" - endword -4: do DROP - saycr " 🗸" - endword - -verb forth CONVERT -2: test equal 0 1f - do pushret - do DUP - do pushret - do fetchb - const '0' - do minus - test greater 9 0f - do SWAP - const 10 - do mult - do plus - do popret - do inc - do popret - do dec - goto 2b -0: do DROP - do popret - do popret -1: endword - -verb forth WORD - get HERE - const 0 - do OVER - do store - const 8 - do plus -1: get numin - get numtib - do gequal - if 3f - do TIB - get numin - do plus - do fetchb - do numin - do incaddr - do DUP - const ' ' - do lequal - if 2f - get HERE - do incaddr - do OVER - do storeb - do inc - goto 1b - 2: do DROP -3: do DROP - get HERE - endword - -verb forth LAST - variable - endword - -verb forth DICTIONARY - get LAST -2: do DUP - do fetch - const 0 - do equal - if 1f - do DUP - const 8 - do plus - do PRINT - do fetch - do SPACE - goto 2b -1: do DROP - endword - -verb forth FIND - get LAST -2: do dup2 - const 8 - do plus - do STRCMP - unless 1f - const 24 - do plus - do SWAP - do fetch - do plus - do TRUE - endword -1: do fetch - do DUP - if 2b - do DROP - do FALSE - endword - -# Compiler - -verb forth HERE - variable - endword - -verb forth modeI "[" immediate - set MODE 0 - endword - -verb forth modeC "]" - set MODE -1 - endword - -verb forth ALLOT - get HERE - do plus - set HERE - endword - -verb forth COMPILE "COMPILE" immediate - get HERE - do store - const 8 - do ALLOT - endword - -verb forth compnew "\x3A" # : - do modeC - get HERE - get LAST - do COMPILE - do WORD - do fetch - const 8 - do plus - do ALLOT - do TRUE - do COMPILE - const enter - do COMPILE - endword - -verb forth compend "\x3B" immediate # ; - const EXIT - do COMPILE - do modeI - set LAST - endword - -# User Words - -verb forth greet GREET - say "Hello, World!" - do CR - endword - -verb forth FLAG - 1: do OVER - do line - do dec - do DUP - if 1b - do DROP - do DROP - endword - -line: forthword - 1: const '*' - do EMIT - do dec - do DUP - if 1b - do DROP - do CR - endword - -verb forth SPACE - const ' ' - do EMIT - endword - -verb forth CR - const '\n' - do EMIT - endword - -verb forth dot "." - test gequal 0 1f - const '-' - do EMIT - do NEGATE -1: do _dot - endword - -_dot: forthword - test less 10 1f - const 10 - do divmod - do SWAP - do _dot -1: - const '0' - do plus - do EMIT - endword - -verb forth dotdot "..." - say "..." - do top - const stack - do nequal - if 1f - say "Stack Empty" -1: do _dotdot - saycr "..." - endword - -_dotdot: forthword - do top - const stack - do equal - if 1f - do pushret # Top of stack - do _dotdot # - do popret # - const '\t' - do EMIT - do DUP - do dot -1: endword - -verb forth dup2 "2DUP" - do OVER - do OVER - endword - -verb forth MIN - do dup2 - do less - if 1f - do SWAP -1: do DROP - endword - -verb forth MAX - do dup2 - do greater - if 1f - do SWAP -1: do DROP - endword - -verb forth STRCMP - do dup2 - do fetch - do SWAP - do fetch - do equal - unless 0f - do OVER - do fetch - const 8 - do divmod - do SWAP - do pushret # Quotient - do DUP # - do pushret # # Remainder - do plus # # - do SWAP # # - do popret # # - do plus # - do popret # - do inc - do QUADCMP - endword -0: do drop2 - do FALSE - endword - -verb forth QUADCMP -2: do DUP - if 1f - do drop2 - do DROP - do TRUE - endword -1: do pushret # Count - do dup2 # - do indneq # - if 0f # - do inc # - do SWAP # - do inc # - do SWAP # - do popret # - do dec - goto 2b +.include "stack.s" +.include "memory.s" +.include "boolean.s" +.include "maths.s" +.include "input.s" +.include "dictionary.s" +.include "interpreter.s" +.include "compiler.s" +.include "output.s" +.include "extras.s" -0: do drop2 # (Count) - do popret # - do DROP - do FALSE - endword - -verb forth divide "/" - do divmod - do DROP - endword - -verb forth mod "%" - do divmod - do SWAP - do DROP - endword - -verb forth muldiv "*/" - do muldivmod - do DROP - endword - -verb forth iszero "0=" - do FALSE - do equal - endword - -verb forth CMOVE -2: test equal 0 1f - do dec - do pushret # Count - do OVER # - do fetchb # - do OVER # - do storeb # - const 8 # - do plus # - do SWAP # - const 8 # - do plus # - do SWAP # - do popret # - goto 2 -1: do DROP - do drop2 - endword - -verb forth STRMOVE - do OVER - do fetch - const 8 - do plus - do CMOVE - endword # "CODEWORDS" - -# Stack manipulation - -verb code RESETDATA - mov $stack, SP - jmp next - -verb code RESETRETURN - mov rspbk, %rsp - jmp next - -verb code DUP - minstk 1 - _dup - jmp next - -verb code drop2 "2DROP" - minstk 2 -_drop2: advance SP - mov (SP), TOS - advance SP - jmp next - -verb code DROP - minstk 1 -_drop: mov (SP), TOS - advance SP - jmp next - -_uflow: do RESETDATA - saycr "\x1B[91m Stack underflow!" - do QUIT - -verb code SWAP - minstk 2 - push TOS - mov (SP), TOS - pop (SP) - jmp next - -verb code OVER - minstk 2 - push (SP) - _dup - pop TOS - jmp next - -# Output - -verb code EMIT - minstk 1 - movq TOS, buff - mov $1, CMD # system call 1 is write - mov $1, ARGA # file handle 1 is stdout - mov $buff, ARGB # address of string to output - mov $1, ARGC # number of bytes - syscall - jmp _drop - -verb code PRINT - minstk 1 - mov $1, CMD - mov $1, ARGA - mov (TOS), ARGC - advance TOS - mov TOS, ARGB - syscall - jmp _drop - -verb code TYPE - minstk 2 - mov $1, CMD - mov $1, ARGA - mov (SP), ARGB - mov TOS, ARGC - syscall - jmp _drop2 - verb code HALT _halt: xor ARGA, ARGA # default return code 0 sub $stack, SP @@ -596,18 +98,6 @@ _halt: xor ARGA, ARGA # default return code 0 1: mov $60, CMD # system call 60 is exit syscall -# Input - -verb code ACCEPT - minstk 2 - mov $0, CMD - mov $0, ARGA - mov (SP), ARGB - mov TOS, ARGC - syscall - mov CMD, (SP) - jmp _drop - # Do Stuff docon: codeword @@ -649,186 +139,6 @@ dountil: codeword sub (IP), IP jmp _drop -# Memory management - -verb code DEPTH - mov $stack, ACC - sub SP, ACC - shr ACC - shr ACC - shr ACC - _dup - mov ACC, TOS - jmp next - -verb code fetch "@>" - minstk 1 - mov (TOS), TOS - jmp next - -fetchb: codeword - minstk 1 - movb (TOS), TOSB - and $0xFF, TOS - jmp next - -verb code store ">@" - minstk 2 - mov (SP), ACC - mov ACC, (TOS) - jmp _drop2 - -storeb: codeword - minstk 2 - mov (SP), ACC - movb ACCB, (TOS) - jmp _drop2 - -top: codeword - push SP - _dup - pop TOS - jmp next - -verb code pushret ">R" - minstk 1 - push TOS - jmp _drop - -verb code popret "R>" - _dup - pop TOS - jmp next - -# Logic - -verb code TRUE - _dup - movq $-1, TOS - jmp next - -verb code FALSE "0" - _dup - xor TOS, TOS - jmp next - -verb code lshift "<<" - minstk 1 - shl TOS - jmp next - -verb code rshift ">>" - minstk 1 - shr TOS - jmp next - -verb code halve "2/" - minstk 1 - sar TOS - jmp next - -verb code NOT - minstk 1 - not TOS - jmp next - -verb code AND - minstk 2 - and TOS, (SP) - jmp _drop - -verb code OR - minstk 2 - or TOS, (SP) - jmp _drop - -verb code XOR - minstk 2 - xor TOS, (SP) - jmp _drop - -# Maths - -verb code plus "+" - minstk 2 - add TOS, (SP) - jmp _drop - -verb code minus "-" - minstk 2 - sub TOS, (SP) - jmp _drop - -verb code inc "1+" - minstk 1 - inc TOS - jmp next - -verb code dec "1-" - minstk 1 - dec TOS - jmp next - -verb code incaddr "@1+" - minstk 1 - incq (TOS) - jmp _drop - -verb code decaddr "@1-" - minstk 1 - decq (TOS) - jmp _drop - -verb code NEGATE - minstk 1 - neg TOS - jmp next - -verb code mult "*" - minstk 2 - mov (SP), %rax - mul TOS - mov %rax, (SP) - jmp _drop - -verb code divmod "/%" - minstk 2 - xor %rdx, %rdx - mov (SP), %rax - div TOS - mov %rax, (SP) - mov %rdx, TOS - jmp next - -verb code muldivmod "*/%" - minstk 3 - mov (SP), %rax - mul TOS - divq -8(SP) - mov %rax, -8(SP) - mov %rdx, (SP) - jmp _drop - -# Comparison - -truecmp: - movq $-1, (SP) - jmp _drop - -compare je equal "\=" -compare jne nequal "<>" -compare jg greater ">" -compare jl less "<" -compare jge gequal ">=" -compare jle lequal "<=" -compare ja above "S>" -compare jb below "S<" -compare jae aequal "S>=" -compare jbe bequal "S<=" - -cmpaddr je indeq "@=" -cmpaddr jne indneq "@<>" - # Kernel verb code EXIT diff --git a/maths.s b/maths.s @@ -0,0 +1,120 @@ +# Maths + +verb code plus "+" + minstk 2 + add TOS, (SP) + jmp _drop + +verb code minus "-" + minstk 2 + sub TOS, (SP) + jmp _drop + +verb code inc "1+" + minstk 1 + inc TOS + jmp next + +verb code dec "1-" + minstk 1 + dec TOS + jmp next + +verb code incaddr "@1+" + minstk 1 + incq (TOS) + jmp _drop + +verb code decaddr "@1-" + minstk 1 + decq (TOS) + jmp _drop + +verb code NEGATE + minstk 1 + neg TOS + jmp next + +verb code mult "*" + minstk 2 + mov (SP), %rax + mul TOS + mov %rax, (SP) + jmp _drop + +verb code divmod "/%" + minstk 2 + xor %rdx, %rdx + mov (SP), %rax + div TOS + mov %rax, (SP) + mov %rdx, TOS + jmp next + +verb forth divide "/" + do divmod + do DROP + endword + +verb forth mod "%" + do divmod + do SWAP + do DROP + endword + +verb code muldivmod "*/%" + minstk 3 + mov (SP), %rax + mul TOS + divq -8(SP) + mov %rax, -8(SP) + mov %rdx, (SP) + jmp _drop + +verb forth muldiv "*/" + do muldivmod + do DROP + endword + +# Functions + +verb forth MIN + do dup2 + do less + if 1f + do SWAP +1: do DROP + endword + +verb forth MAX + do dup2 + do greater + if 1f + do SWAP +1: do DROP + endword + +# Comparison + +verb forth iszero "0=" + do FALSE + do equal + endword + +truecmp: + movq $-1, (SP) + jmp _drop + +compare je equal "\=" +compare jne nequal "<>" +compare jg greater ">" +compare jl less "<" +compare jge gequal ">=" +compare jle lequal "<=" +compare ja above "S>" +compare jb below "S<" +compare jae aequal "S>=" +compare jbe bequal "S<=" + +cmpaddr je indeq "@=" +cmpaddr jne indneq "@<>" diff --git a/memory.s b/memory.s @@ -0,0 +1,104 @@ +# Memory management + +verb code fetch "@>" + minstk 1 + mov (TOS), TOS + jmp next + +fetchb: codeword + minstk 1 + movb (TOS), TOSB + and $0xFF, TOS + jmp next + +verb code store ">@" + minstk 2 + mov (SP), ACC + mov ACC, (TOS) + jmp _drop2 + +storeb: codeword + minstk 2 + mov (SP), ACC + movb ACCB, (TOS) + jmp _drop2 + +verb forth QUADCMP +2: do DUP + if 1f + do drop2 + do DROP + do TRUE + endword +1: do pushret # Count + do dup2 # + do indneq # + if 0f # + do inc # + do SWAP # + do inc # + do SWAP # + do popret # + do dec + goto 2b + +0: do drop2 # (Count) + do popret # + do DROP + do FALSE + endword + +verb forth STRCMP + do dup2 + do fetch + do SWAP + do fetch + do equal + unless 0f + do OVER + do fetch + const 8 + do divmod + do SWAP + do pushret # Quotient + do DUP # + do pushret # # Remainder + do plus # # + do SWAP # # + do popret # # + do plus # + do popret # + do inc + do QUADCMP + endword +0: do drop2 + do FALSE + endword + +verb forth CMOVE +2: test equal 0 1f + do dec + do pushret # Count + do OVER # + do fetchb # + do OVER # + do storeb # + const 8 # + do plus # + do SWAP # + const 8 # + do plus # + do SWAP # + do popret # + goto 2 +1: do DROP + do drop2 + endword + +verb forth STRMOVE + do OVER + do fetch + const 8 + do plus + do CMOVE + endword diff --git a/output.s b/output.s @@ -0,0 +1,85 @@ +# Output + +verb code EMIT + minstk 1 + movq TOS, buff + mov $1, CMD # system call 1 is write + mov $1, ARGA # file handle 1 is stdout + mov $buff, ARGB # address of string to output + mov $1, ARGC # number of bytes + syscall + jmp _drop + +verb forth CR + const '\n' + do EMIT + endword + +verb forth SPACE + const ' ' + do EMIT + endword + +verb code PRINT + minstk 1 + mov $1, CMD + mov $1, ARGA + mov (TOS), ARGC + advance TOS + mov TOS, ARGB + syscall + jmp _drop + +verb code TYPE + minstk 2 + mov $1, CMD + mov $1, ARGA + mov (SP), ARGB + mov TOS, ARGC + syscall + jmp _drop2 + +verb forth dot "." + test gequal 0 1f + const '-' + do EMIT + do NEGATE +1: do _dot + endword + +_dot: forthword + test less 10 1f + const 10 + do divmod + do SWAP + do _dot +1: + const '0' + do plus + do EMIT + endword + +verb forth dotdot "..." + say "..." + do top + const stack + do nequal + if 1f + say "Stack Empty" +1: do _dotdot + saycr "..." + endword + +_dotdot: forthword + do top + const stack + do equal + if 1f + do pushret # Top of stack + do _dotdot # + do popret # + const '\t' + do EMIT + do DUP + do dot +1: endword diff --git a/stack.s b/stack.s @@ -0,0 +1,76 @@ +# Stack manipulation + +verb code RESETDATA + mov $stack, SP + jmp next + +verb code RESETRETURN + mov rspbk, %rsp + jmp next + +verb code DUP + minstk 1 + _dup + jmp next + +verb forth dup2 "2DUP" + do OVER + do OVER + endword + +verb code drop2 "2DROP" + minstk 2 +_drop2: advance SP + mov (SP), TOS + advance SP + jmp next + +verb code DROP + minstk 1 +_drop: mov (SP), TOS + advance SP + jmp next + +_uflow: do RESETDATA + saycr "\x1B[91m Stack underflow!" + do QUIT + +verb code SWAP + minstk 2 + push TOS + mov (SP), TOS + pop (SP) + jmp next + +verb code OVER + minstk 2 + push (SP) + _dup + pop TOS + jmp next + +verb code DEPTH + mov $stack, ACC + sub SP, ACC + shr ACC + shr ACC + shr ACC + _dup + mov ACC, TOS + jmp next + +top: codeword + push SP + _dup + pop TOS + jmp next + +verb code pushret ">R" + minstk 1 + push TOS + jmp _drop + +verb code popret "R>" + _dup + pop TOS + jmp next