📄 simx86p.pas
字号:
end;
Procedure SetGet(Pat:TPatPtr);
begin
HasOpcode := True;
Opcode := $0;
HasReg := true;
RegCode := $0;
HasOperand := true;
OperandCode := $6;
end;
Procedure SetAX(Pat:TPatPtr);
begin
HasReg := True;
Regcode := $00;
end;
Procedure SetBX(Pat:TPatPtr);
begin
HasReg := True;
Regcode := $08;
end;
Procedure SetCX(Pat:TPatPtr);
begin
HasReg := True;
Regcode := $10;
end;
Procedure SetDX(Pat:TPatPtr);
begin
HasReg := True;
Regcode := $18;
end;
Procedure SetAX2(Pat:TPatPtr);
begin
HasOperand := True;
Operandcode := $00;
end;
Procedure SetBX2(Pat:TPatPtr);
begin
HasOperand := True;
Operandcode := $1;
end;
Procedure SetCX2(Pat:TPatPtr);
begin
HasOperand := True;
Operandcode := $2;
end;
Procedure SetDX2(Pat:TPatPtr);
begin
HasOperand := True;
Operandcode := $3;
end;
Procedure SetBXInd(Pat:TPatPtr);
begin
HasOperand := True;
Operandcode := $4;
end;
Procedure SetBXIndx(Pat:TPatPtr);
begin
HasOperand := True;
Operandcode := $5;
end;
Procedure SetABS(Pat:TPatPtr);
begin
HasOperand := True;
Operandcode := $6;
end;
Procedure SetImm(Pat:TPatPtr);
begin
HasOperand := True;
Operandcode := $7;
end;
{$F-}
{ Whenever the user presses the CLEAR button on the memory page, the }
{ following method zeros out memory. }
procedure TSIMx86Form.ClrMemBtnClick(Sender: TObject);
var i:word;
begin
AdrsEntry.Text := '0000';
AdrsEntryChange(AdrsEntry);
{ Zero out memory }
for i := 0 to $ffef do
Memory^[i] := 0;
MemAdrs := 0;
Adrs := 0;
end;
{ Handle the NEW, OPEN, SAVE, SAVEAS, Print, and QUIT entries in the File Menu }
procedure TSIMx86Form.QuitClick(Sender: TObject);
begin
Application.Terminate;
end;
procedure TSIMx86Form.PrintMenuItemClick(Sender: TObject);
var
i: integer;
f: TextFile;
begin
if PrintDialog.Execute then begin
if (SIMx86Pages.PageIndex = 0) then begin
AssignPrn(f);
Rewrite(f);
for i := 0 to SourceCode.Lines.Count-1 do
writeln(f,SourceCode.Lines[i]);
CloseFile(f);
end
else Print;
end;
end;
procedure TSIMx86Form.NewClick(Sender: TObject);
begin
SourceCode.Clear;
Filename := '';
end;
procedure TSIMx86Form.OpenClick(Sender: TObject);
var
name:string;
begin
if OpenDialog.Execute then
begin
SourceCode.Lines.LoadFromFile(OpenDialog.Filename);
Filename := OpenDialog.Filename;
end;
end;
procedure TSIMx86Form.SaveAsClick(Sender: TObject);
begin
if SaveDialog.Execute then
begin
FileName := SaveDialog.Filename;
SourceCode.Lines.SaveToFile(SaveDialog.Filename);
end;
end;
procedure TSIMx86Form.SaveClick(Sender: TObject);
begin
if (Filename = '') then
begin
if SaveDialog.Execute then
Filename := SaveDialog.Filename;
end;
if (Filename <> '') then
begin
SourceCode.Lines.SaveToFile(Filename);
end;
end;
{ Handle Cut, Copy, Paste, Delete, and SelectAll in the Edit Menu }
procedure TSIMx86Form.CutClick(Sender: TObject);
begin
SourceCode.CutToClipBoard;
end;
procedure TSIMx86Form.CopyClick(Sender: TObject);
begin
SourceCode.CopyToClipBoard;
end;
procedure TSIMx86Form.PasteClick(Sender: TObject);
begin
SourceCode.PasteFromClipBoard;
end;
procedure TSIMx86Form.DeleteClick(Sender: TObject);
begin
SourceCode.ClearSelection;
end;
procedure TSIMx86Form.SelectAllClick(Sender: TObject);
begin
SourceCode.SelectAll;
SourceCode.Repaint;
end;
{ Whenver a value changes in one of the memory data entry boxes, this }
{ method converts the data data to hexadecimal and stores the resulting }
{ value away into memory. }
procedure TSIMx86Form.HexChange(Sender: TObject);
var Cell:TEdit;
HexVal:byte;
i,
j,
index:word;
begin
Cell := TEdit(Sender);
CheckHex(Cell);
{ Only store the data if there is no error. If there is an error, }
{ the memory cell's background color will be red. }
if (Cell.Color <> clRed) then
begin
for i := 0 to 7 do
for j := 0 to 7 do
if (Sender = MemEntry[i,j]) then
WriteMem(MemAdrs+ i*8+j, HexToWord(Cell.Text));
end;
end;
{ AdrsEntryChange- This method executes whenever the user changes }
{ a value in the address box on the Memory page. }
{ This method converts the string representation }
{ of the address to binary, updates all the labels}
{ on the screen, and then updates all the memory }
{ entry boxes on the page. }
procedure TSIMx86Form.AdrsEntryChange(Sender: TObject);
var
HexVal: word;
index: word;
i,j: word;
begin
CheckHex(TEdit(Sender));
{ If the entry is invalid, don't do anything. }
if (AdrsEntry.Color <> clRed) then begin
HexVal := HexToWord(AdrsEntry.Text);
{ Update the labels on the page. Make sure the values we use }
{ are all even multiples of eight. }
MemAdrs := HexVal and $FFF8;
Lbl8.Caption := IntToHex(MemAdrs+8,4);
Lbl10.Caption := IntToHex(MemAdrs+16,4);
Lbl18.Caption := IntToHex(MemAdrs+24,4);
Lbl20.Caption := IntToHex(MemAdrs+32,4);
Lbl28.Caption := IntToHex(MemAdrs+40,4);
Lbl30.Caption := IntToHex(MemAdrs+48,4);
Lbl38.Caption := IntToHex(MemAdrs+56,4);
{ Update the data in the entry cells on the page. If }
{ the location we access is before the starting address }
{ (because we may have rounded it down to the previous }
{ eight-byte boundary), then turn the background color }
{ gray. }
for i := 0 to 7 do
for j := 0 to 7 do
begin
index := MemAdrs + i*8 + j;
MemEntry[i,j].Text := IntToHex(ReadMem(index),2);
if ((index < HexVal) or (Index >=$fff0)) then
begin
MemEntry[i,j].Color := clSilver;
MemEntry[i,j].Enabled := false;
end
else begin
MemEntry[i,j].Color := clWindow;
MemEntry[i,j].Enabled := true;
end;
end;
end;
end;
procedure TSIMx86Form.StartAdrsChange(Sender: TObject);
begin
CheckHex(StartAdrs);
end;
{ Do the assembly here }
procedure TSIMx86Form.ASMbtnClick(Sender: TObject);
var
i:word;
ch:char;
line:array[0..255] of char;
s:PChar;
begin
{ Initialize the symbol table }
for ch := 'A' to 'Z' do
begin
SymTbl[ch].Value := 0;
SymTbl[ch].Defined := false;
end;
{ Compute the address of the first instruction }
if (StartAdrs.Color <> clRed) then
Adrs := HexToWord(StartAdrs.Text)
else Adrs := 0;
{ Assemble each line of source code }
for LineNum := 0 to SourceCode.Lines.Count-1 do begin
s := strPCopy(line, SourceCode.Lines[LineNum]);
NoError := true;
HasValue := false;
HasOpcode := false;
HasReg := false;
HasOperand := false;
if (not Match(stmt, s)) then
begin
if (NoError) then
ErrorMsg('Syntax Error',
SourceCode.lines[LineNum]);
if (AbortAsm) then break;
end
else begin
{ Okay, the instruction is syntactically cor- }
{ rect. Now emit the opcode and any necessary }
{ operands to memory. }
Val := 0;
if (HasOpcode) then {It's not a blank line }
begin
Val := Val or Opcode;
if (HasReg) then Val := Val or Regcode;
if (HasOperand) then Val := Val or OperandCode;
WriteMem(Adrs, Val);
inc(adrs);
if (HasValue) then begin {It has an operand }
WriteMem(Adrs, OperandValue and $ff);
inc(adrs);
WriteMem(Adrs, OperandValue shr 8);
inc (adrs);
end;
end;
end;
end;
{ Check to see if there were any undefined symbols }
for ch := 'A' to 'Z' do
if (not SymTbl[ch].Defined)then
if (SymTbl[ch].Value <> 0) then
ErrorMsg('Undefined Symbol', ch);
end;
{ Given an opcode, the following function returns the size of }
{ an instruction (in bytes). This is either one or three. }
function InstrSz(opcode:word):integer;
begin
if (opcode > $1f) or ((opcode and $18) = $10) then
if (opcode and $7) >= 5 then Result := 3
else Result := 1
else if (opcode and $18) = $8 then Result := 3
else Result := 1;
end;
{ Given an opcode, the following function returns a string that }
{ corresponds to the instruction's mnemonic. }
function Instr(opcode:word):string;
begin
Result := '????';
case (opcode shr 5) of
1: Result := 'or ';
2: Result := 'and ';
3: Result := 'cmp ';
4: Result := 'sub ';
5: Result := 'add ';
6: Result := 'mov ';
7: Result := 'mov ';
0: begin
if (opcode and $18) = $10 then
Result := 'not '
else if (opcode and $18) = $8 then
begin
case opcode and $7 of
0: Result := 'je ';
1: Result := 'jne ';
2: Result := 'jb ';
3: Result := 'jbe ';
4: Result := 'ja ';
5: Result := 'jae ';
6: Result := 'jmp ';
7: Result := '****';
end;
end
else if (opcode and $18) = $18 then Result := '****'
else begin
case (opcode and $7) of
0: Result := '****';
1: Result := '****';
2: Result := '****';
3: Result := 'brk ';
4: Result := 'iret';
5: Result := 'halt';
6: Result := 'get ';
7: Result := 'put ';
end;
end;
end;
end;
end;
{ Given an opcode and an option operand, the following function returns }
{ a string that represents the reg/memory addressing mode. }
function AdrsMode(opcode, operand:word):string;
function MemMode(opcode,operand:word):string;
begin
case opcode and $7 of
0: Result := 'ax';
1: Result := 'bx';
2: Result := 'cx';
3: Result := 'dx';
4: Result := '[bx]';
5: Result := '['+IntToHex(operand,4)+'+bx]';
6: Result := '['+IntToHex(operand,4)+']';
7: Result := IntToHex(operand,4);
end;
end;
begin
if (opcode > $1f) or (opcode and $18 = $10) then
Result := MemMode(opcode,operand)
else if (opcode and $18 = $8) then
Result := MemMode($27, operand)
else Result := '';
end;
{ The following function disassembles a single instruction at the given }
{ address and returns the string representation of that instruction. }
function Disassemble2(var CodeAdrs:word):string;
var Size,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -