{$mode objfpc}
unit uASM;
interface
uses StrUtils, SysUtils, Types, uPRECodes, uUtil;
type
TInformation = record
path, outpath: String;
_file: TextFile;
cline: Integer;
sline: String;
end;
TPREAssembler = class
private
FInterfaceData: TInterfaceDataArr;
{ FeEc 16-11-2022: idc that this violates my own Styleguide, its gonna get changed later on }
info: TInformation;
public
function Assemble: TByteArray;
procedure Run(const AFile: String);
end;
implementation
function TPREAssembler.Assemble: TByteArray;
var
instruction: String;
tmp, out: TByteArray;
split, parameters: Types.TStringDynArray;
begin
out := [];
while not eof(info._file) do
begin
info.cline := info.cline + 1;
Readln(info._file, info.sline);
info.sline := Trim(info.sline);
// Parse Line
if (info.sline[1] = ';') then continue;
split := SplitString(info.sline, ' ');
instruction := LowerCase(split[0]);
if (Length(split) > 1) then
parameters := Copy(split, 1, Length(split)-1)
else
parameters := [''];
// Assemble Instruction
try
case instruction of
'halt': begin
out := ConcatByteArrs(out, [OP_HALT]);
end;
'sys': begin
out := ConcatByteArrs(out, [OP_SYS]);
end;
'ld': begin
{
Possible Parameters
Param1
Hardcoded Byte / Byte Const
Param2
Hardcoded Any Type / Any Type Const
Variable
}
tmp := ParseASMParam(parameters[0], [prmByte], FInterfaceData); // Causes Stack Overflow, why???
tmp := ConcatByteArrs(tmp, ParseASMParam(parameters[1], [prmAll], FInterfaceData));
out := ConcatByteArrs(out, ConcatByteArrs([OP_LD], tmp));
end;
else
begin
writeln('presdk-asm: ', info.path, ' (line ', IntToStr(info.cline), '): error: Invalid Instruction "', instruction, '"');
end;
end
except
on e: EInvalidParameterException do
begin
writeln('presdk-asm: ', info.path, ' (line ', IntToStr(info.cline), '): error: ',
e.Message);
end;
end;
end;
result := out;
end;
procedure TPREAssembler.Run(const AFile: String);
var
bytecode: TByteArray;
i: Integer;
begin
if not FileExists(AFile) then
begin
writeln('PREASM: error: File "', AFile, '" does not exist!');
exit;
end;
info.path := AFile;
info.outpath := ExtractFilePath(AFile)+'/'+ExtractFileName(AFile)+'.prex';
Assign(info._file, info.path);
ReSet(info._file);
info.sline := '';
info.cline := 0;
// Interface Section
while not eof(info._file) and (info.sline <> '.start') do
begin
info.cline := info.cline + 1;
Readln(info._file, info.sline);
end;
// Source Code
bytecode := Assemble;
for i := 0 to Length(bytecode)-1 do
begin
write(Format('%.2x ', [bytecode[i]]));
if (i mod 8 = 0) and (i > 0) then writeln;
end;
writeln;
end;
end.