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:
parent
49942ac88d
commit
e2b545afa5
|
@ -20,6 +20,13 @@ var
|
||||||
Bin: array [0 .. $ffef] of byte; //Assembled binary
|
Bin: array [0 .. $ffef] of byte; //Assembled binary
|
||||||
Prog: file of byte; //Program file
|
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
|
//Print an argument error and abort
|
||||||
procedure ArgError;
|
procedure ArgError;
|
||||||
begin
|
begin
|
||||||
|
@ -31,7 +38,7 @@ end;
|
||||||
procedure MemError;
|
procedure MemError;
|
||||||
begin
|
begin
|
||||||
if (BP + 2) >= $fff0 then begin
|
if (BP + 2) >= $fff0 then begin
|
||||||
writeln ('Error (line ', LP, '): out of memory');
|
writeln ('Error (line ', LP, '): memory overflow');
|
||||||
halt;
|
halt;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
@ -78,6 +85,12 @@ begin
|
||||||
//Read a line
|
//Read a line
|
||||||
readln (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
|
//Remove the comment if any
|
||||||
Line := Trim (ExtractDelimited (1, Line, [';']));
|
Line := Trim (ExtractDelimited (1, Line, [';']));
|
||||||
|
|
||||||
|
@ -93,27 +106,40 @@ begin
|
||||||
|
|
||||||
//Check if the first element is a label
|
//Check if the first element is a label
|
||||||
if RightStr (Trim (ExtractWord (1, Line, [' ', ' '])), 1) = ':' then begin
|
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
|
//Extract the label
|
||||||
Lbl [Count] .Addr := BP;
|
|
||||||
Elem [0] := Trim (ExtractDelimited (1, Line, [':']));
|
Elem [0] := Trim (ExtractDelimited (1, Line, [':']));
|
||||||
Lbl [Count] .Lbl := Elem [0];
|
|
||||||
Line := Trim (ExtractDelimited (2, Line, [':']));
|
Line := Trim (ExtractDelimited (2, Line, [':']));
|
||||||
//Check for forward references
|
//Check if the label is hexadecimal
|
||||||
Count := 0;
|
try
|
||||||
repeat
|
Count := Hex2Dec (Elem [0]);
|
||||||
while CompareText (Elem [0], Ref [Count] .Lbl) <> 0 do begin
|
writeln ('Error (line ', LP, '): labels cannot be hexadecimal numbers');
|
||||||
if Ref [Count] .Lbl = '' then break;
|
halt;
|
||||||
Count := Count + 1;
|
except
|
||||||
|
//Check if the label is alphanumeric
|
||||||
|
if IsAlphaNum (Elem [0]) = false then begin
|
||||||
|
writeln ('Error (line ', LP, '): labels must be alphanumeric');
|
||||||
|
halt;
|
||||||
end;
|
end;
|
||||||
if Ref [Count] .Lbl <> '' then begin
|
//Find the first empty slot in the label table
|
||||||
Bin [Ref [Count] .Addr] := BP shr 8;
|
Count := 0;
|
||||||
Bin [Ref [Count] .Addr + 1] := BP and $00ff;
|
while Lbl [Count] .Lbl <> '' do Count := Count + 1;
|
||||||
Count := Count + 1;
|
//Store the label in the table
|
||||||
end;
|
Lbl [Count] .Addr := BP;
|
||||||
until Ref [Count] .Lbl = '';
|
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;
|
end;
|
||||||
|
|
||||||
//Check for the org pseudo-instruction
|
//Check for the org pseudo-instruction
|
||||||
|
@ -222,6 +248,11 @@ begin
|
||||||
else ArgError;
|
else ArgError;
|
||||||
except
|
except
|
||||||
//Label reference
|
//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
|
//Backwards
|
||||||
Count := 0;
|
Count := 0;
|
||||||
while CompareText (Elem [3], Lbl [Count] .Lbl) <> 0 do begin
|
while CompareText (Elem [3], Lbl [Count] .Lbl) <> 0 do begin
|
||||||
|
@ -234,7 +265,7 @@ begin
|
||||||
//Find the first empty slot in the reference table
|
//Find the first empty slot in the reference table
|
||||||
Count := 0;
|
Count := 0;
|
||||||
while Ref [Count] .Lbl <> '' do Count := Count + 1;
|
while Ref [Count] .Lbl <> '' do Count := Count + 1;
|
||||||
//Extract the reference
|
//Store the reference in the table
|
||||||
Ref [Count] .Addr := BP + 1;
|
Ref [Count] .Addr := BP + 1;
|
||||||
Ref [Count] .Lbl := Elem [3];
|
Ref [Count] .Lbl := Elem [3];
|
||||||
//Placeholder
|
//Placeholder
|
||||||
|
@ -254,6 +285,11 @@ begin
|
||||||
else ArgError;
|
else ArgError;
|
||||||
except
|
except
|
||||||
//Label reference
|
//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
|
//Backwards
|
||||||
Count := 0;
|
Count := 0;
|
||||||
while CompareText (Elem [2], Lbl [Count] .Lbl) <> 0 do begin
|
while CompareText (Elem [2], Lbl [Count] .Lbl) <> 0 do begin
|
||||||
|
@ -266,7 +302,7 @@ begin
|
||||||
//Find the first empty slot in the reference table
|
//Find the first empty slot in the reference table
|
||||||
Count := 0;
|
Count := 0;
|
||||||
while Ref [Count] .Lbl <> '' do Count := Count + 1;
|
while Ref [Count] .Lbl <> '' do Count := Count + 1;
|
||||||
//Extract the reference
|
//Store the reference in the table
|
||||||
Ref [Count] .Addr := BP + 1;
|
Ref [Count] .Addr := BP + 1;
|
||||||
Ref [Count] .Lbl := Elem [2];
|
Ref [Count] .Lbl := Elem [2];
|
||||||
//Placeholder
|
//Placeholder
|
||||||
|
@ -294,6 +330,11 @@ begin
|
||||||
else ArgError;
|
else ArgError;
|
||||||
except
|
except
|
||||||
//Label reference
|
//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
|
//Backwards
|
||||||
Count := 0;
|
Count := 0;
|
||||||
while CompareText (Elem [4], Lbl [Count] .Lbl) <> 0 do begin
|
while CompareText (Elem [4], Lbl [Count] .Lbl) <> 0 do begin
|
||||||
|
@ -306,7 +347,7 @@ begin
|
||||||
//Find the first empty slot in the reference table
|
//Find the first empty slot in the reference table
|
||||||
Count := 0;
|
Count := 0;
|
||||||
while Ref [Count] .Lbl <> '' do Count := Count + 1;
|
while Ref [Count] .Lbl <> '' do Count := Count + 1;
|
||||||
//Extract the reference
|
//Store the reference in the table
|
||||||
Ref [Count] .Addr := BP + 1;
|
Ref [Count] .Addr := BP + 1;
|
||||||
Ref [Count] .Lbl := Elem [4];
|
Ref [Count] .Lbl := Elem [4];
|
||||||
//Placeholder
|
//Placeholder
|
||||||
|
@ -329,9 +370,6 @@ begin
|
||||||
//Increment the line pointer
|
//Increment the line pointer
|
||||||
LP := LP + 1;
|
LP := LP + 1;
|
||||||
|
|
||||||
//A hack for fixing an unexplained extra readln after the loop that does nothing
|
|
||||||
if BP = $fff0 then break;
|
|
||||||
|
|
||||||
until eof ();
|
until eof ();
|
||||||
|
|
||||||
//Set the end pointer and reset the byte pointer to the start of the program
|
//Set the end pointer and reset the byte pointer to the start of the program
|
||||||
|
|
|
@ -50,7 +50,10 @@ begin
|
||||||
read (Prog, Bin [BP]);
|
read (Prog, Bin [BP]);
|
||||||
BP := BP + 1;
|
BP := BP + 1;
|
||||||
until (eof (Prog)) or (BP = $fff0);
|
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
|
//Save the end point and reinitialise the byte pointer
|
||||||
EP := BP;
|
EP := BP;
|
||||||
BP := 0;
|
BP := 0;
|
||||||
|
|
|
@ -39,6 +39,10 @@ begin
|
||||||
read (Prog, Mem [IP]);
|
read (Prog, Mem [IP]);
|
||||||
IP := IP + 1;
|
IP := IP + 1;
|
||||||
until (eof (Prog)) or (IP = $fff0);
|
until (eof (Prog)) or (IP = $fff0);
|
||||||
|
if IP = $fff0 then begin
|
||||||
|
writeln ('Error: memory overflow');
|
||||||
|
halt;
|
||||||
|
end;
|
||||||
|
|
||||||
//Reinitialise the instruction pointer
|
//Reinitialise the instruction pointer
|
||||||
IP := 0;
|
IP := 0;
|
||||||
|
|
|
@ -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 first instruction and cannot have a label, and is not required if
|
||||||
the starting address is 0. DATA introduces a byte of data.
|
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
|
Memory-Mapped Devices
|
||||||
---------------------
|
---------------------
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue