From e2b545afa5f88344174bab9ee8b2472571fadac6 Mon Sep 17 00:00:00 2001 From: CrazyEttin <> Date: Sun, 31 Jul 2022 21:58:23 +0300 Subject: [PATCH] Add checking that labels and references are alphabumeric to the assembler and a warn about its lack of checking for references to non-existing labels in the readme, and add memory overflow errors --- assembler.pas | 86 ++++++++++++++++++++++++++++++++++-------------- disassembler.pas | 5 ++- emulator.pas | 4 +++ readme.md | 3 ++ 4 files changed, 73 insertions(+), 25 deletions(-) diff --git a/assembler.pas b/assembler.pas index 19ffde0..e404847 100644 --- a/assembler.pas +++ b/assembler.pas @@ -20,6 +20,13 @@ var Bin: array [0 .. $ffef] of byte; //Assembled binary Prog: file of byte; //Program file +//Check if a string is alphanumeric +function IsAlphaNum (Arg: string): boolean; +begin + for Count := 1 to length (Arg) do if not (Arg [Count] in ['a' .. 'z', 'A' .. 'Z', '0' .. '9']) then exit (false); + exit (true); +end; + //Print an argument error and abort procedure ArgError; begin @@ -31,7 +38,7 @@ end; procedure MemError; begin if (BP + 2) >= $fff0 then begin - writeln ('Error (line ', LP, '): out of memory'); + writeln ('Error (line ', LP, '): memory overflow'); halt; end; end; @@ -78,6 +85,12 @@ begin //Read a line readln (Line); + //A hack for fixing an unexplained extra readln after the loop that does nothing + if BP = $fff0 then begin + writeln ('Error (line ', LP, '): memory overflow'); + halt; + end; + //Remove the comment if any Line := Trim (ExtractDelimited (1, Line, [';'])); @@ -93,27 +106,40 @@ begin //Check if the first element is a label if RightStr (Trim (ExtractWord (1, Line, [' ', ' '])), 1) = ':' then begin - //Find the first empty slot in the label table - Count := 0; - while Lbl [Count] .Lbl <> '' do Count := Count + 1; //Extract the label - Lbl [Count] .Addr := BP; Elem [0] := Trim (ExtractDelimited (1, Line, [':'])); - Lbl [Count] .Lbl := Elem [0]; Line := Trim (ExtractDelimited (2, Line, [':'])); - //Check for forward references - Count := 0; - repeat - while CompareText (Elem [0], Ref [Count] .Lbl) <> 0 do begin - if Ref [Count] .Lbl = '' then break; - Count := Count + 1; + //Check if the label is hexadecimal + try + Count := Hex2Dec (Elem [0]); + writeln ('Error (line ', LP, '): labels cannot be hexadecimal numbers'); + halt; + except + //Check if the label is alphanumeric + if IsAlphaNum (Elem [0]) = false then begin + writeln ('Error (line ', LP, '): labels must be alphanumeric'); + halt; end; - if Ref [Count] .Lbl <> '' then begin - Bin [Ref [Count] .Addr] := BP shr 8; - Bin [Ref [Count] .Addr + 1] := BP and $00ff; - Count := Count + 1; - end; - until Ref [Count] .Lbl = ''; + //Find the first empty slot in the label table + Count := 0; + while Lbl [Count] .Lbl <> '' do Count := Count + 1; + //Store the label in the table + Lbl [Count] .Addr := BP; + Lbl [Count] .Lbl := Elem [0]; + //Check for forward references + Count := 0; + repeat + while CompareText (Elem [0], Ref [Count] .Lbl) <> 0 do begin + if Ref [Count] .Lbl = '' then break; + Count := Count + 1; + end; + if Ref [Count] .Lbl <> '' then begin + Bin [Ref [Count] .Addr] := BP shr 8; + Bin [Ref [Count] .Addr + 1] := BP and $00ff; + Count := Count + 1; + end; + until Ref [Count] .Lbl = ''; + end; end; //Check for the org pseudo-instruction @@ -222,6 +248,11 @@ begin else ArgError; except //Label reference + //Check if the reference is alphanumeric + if IsAlphaNum (Elem [3]) = false then begin + writeln ('Error (line ', LP, '): references must be alphanumeric'); + halt; + end; //Backwards Count := 0; while CompareText (Elem [3], Lbl [Count] .Lbl) <> 0 do begin @@ -234,7 +265,7 @@ begin //Find the first empty slot in the reference table Count := 0; while Ref [Count] .Lbl <> '' do Count := Count + 1; - //Extract the reference + //Store the reference in the table Ref [Count] .Addr := BP + 1; Ref [Count] .Lbl := Elem [3]; //Placeholder @@ -254,6 +285,11 @@ begin else ArgError; except //Label reference + //Check if the reference is alphanumeric + if IsAlphaNum (Elem [2]) = false then begin + writeln ('Error (line ', LP, '): references must be alphanumeric'); + halt; + end; //Backwards Count := 0; while CompareText (Elem [2], Lbl [Count] .Lbl) <> 0 do begin @@ -266,7 +302,7 @@ begin //Find the first empty slot in the reference table Count := 0; while Ref [Count] .Lbl <> '' do Count := Count + 1; - //Extract the reference + //Store the reference in the table Ref [Count] .Addr := BP + 1; Ref [Count] .Lbl := Elem [2]; //Placeholder @@ -294,6 +330,11 @@ begin else ArgError; except //Label reference + //Check if the reference is alphanumeric + if IsAlphaNum (Elem [4]) = false then begin + writeln ('Error (line ', LP, '): references must be alphanumeric'); + halt; + end; //Backwards Count := 0; while CompareText (Elem [4], Lbl [Count] .Lbl) <> 0 do begin @@ -306,7 +347,7 @@ begin //Find the first empty slot in the reference table Count := 0; while Ref [Count] .Lbl <> '' do Count := Count + 1; - //Extract the reference + //Store the reference in the table Ref [Count] .Addr := BP + 1; Ref [Count] .Lbl := Elem [4]; //Placeholder @@ -329,9 +370,6 @@ begin //Increment the line pointer LP := LP + 1; - //A hack for fixing an unexplained extra readln after the loop that does nothing - if BP = $fff0 then break; - until eof (); //Set the end pointer and reset the byte pointer to the start of the program diff --git a/disassembler.pas b/disassembler.pas index cc70a27..0ea27f6 100644 --- a/disassembler.pas +++ b/disassembler.pas @@ -50,7 +50,10 @@ begin read (Prog, Bin [BP]); BP := BP + 1; until (eof (Prog)) or (BP = $fff0); - + if BP = $fff0 then begin + writeln ('Error: memory overflow'); + halt; + end; //Save the end point and reinitialise the byte pointer EP := BP; BP := 0; diff --git a/emulator.pas b/emulator.pas index 4bea539..e44ef1f 100644 --- a/emulator.pas +++ b/emulator.pas @@ -39,6 +39,10 @@ begin read (Prog, Mem [IP]); IP := IP + 1; until (eof (Prog)) or (IP = $fff0); + if IP = $fff0 then begin + writeln ('Error: memory overflow'); + halt; + end; //Reinitialise the instruction pointer IP := 0; diff --git a/readme.md b/readme.md index cb5b846..fd05983 100644 --- a/readme.md +++ b/readme.md @@ -67,6 +67,9 @@ ORG defines the starting address of the program: it can only occur as the first instruction and cannot have a label, and is not required if the starting address is 0. DATA introduces a byte of data. +Note that the assembler does not check for references to non-existing +labels. + Memory-Mapped Devices ---------------------