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

This commit is contained in:
CrazyEttin 2022-07-31 21:58:23 +03:00
parent 49942ac88d
commit e2b545afa5
4 changed files with 73 additions and 25 deletions

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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
---------------------