📄 simx86p.pas
字号:
Operand:word;
begin
Result := IntToHex(CodeAdrs,4) + ': ' +
IntToHex(ReadMem(CodeAdrs),2) + ' ';
Size := InstrSz(ReadMem(CodeAdrs));
Opcode := ReadMem(CodeAdrs);
if Size = 1 then
begin
Result := Result + ' ';
inc(CodeAdrs);
end
else begin
Result := Result +
IntToHex(ReadMem(CodeAdrs+1),2) + ' ' +
IntToHex(ReadMem(CodeAdrs+2),2) + ' ';
Operand := ReadMem(CodeAdrs+1) + (ReadMem(CodeAdrs+2) shl 8);
CodeAdrs := CodeAdrs + 3;
end;
Result := Result + Instr(opcode) + ' ';
case (opcode shr 5) of
1,2,3,4,5,6:begin
case ((opcode shr 3) and $3) of
0: Result := Result + 'ax, ';
1: Result := Result + 'bx, ';
2: Result := Result + 'cx, ';
3: Result := Result + 'dx, ';
end;
Result := Result + AdrsMode(Opcode, Operand);
end;
7:begin
Result := Result + AdrsMode(Opcode, Operand) + ', ';
case ((opcode shr 3) and $3) of
0: Result := Result + 'ax';
1: Result := Result + 'bx';
2: Result := Result + 'cx';
3: Result := Result + 'dx';
end;
end;
0: begin
case (opcode shr 3) and $3 of
1: Result := Result + IntToHex(Operand,4);
2: Result := Result + AdrsMode(Opcode,Operand);
end;
end;
end;
end;
function Disassemble(CodeAdrs:word):string;
begin
Result := Disassemble2(CodeAdrs);
end;
{ The following event method handles switching between pages on the form. }
procedure TSIMx86Form.Simx86PagesChange(Sender: TObject;
NewTab: Integer;
var AllowChange: Boolean);
var DisAdrs:word;
i:integer;
begin
{ Don't allow a change if a program is running. }
if (Running and (NewTab = 0)) then
begin
AllowChange := false;
end
{ If the user switches to the memory page, redraw all the cells. }
else if (NewTab = 1) then
AdrsEntryChange(AdrsEntry)
{ If the user switches to the execute page, disassemble some }
{ code for the disassembly list box. }
else if (NewTab = 2) then
begin
DisAdrs := HexToWord(DisAsmAdrs.Text);
DisAsm.Clear;
for i := 1 to 15 do
DisAsm.Items.Add(Disassemble2(DisAdrs));
Instruction.Caption := Disassemble(IP);
end;
end;
{ If the user changes the address in the TEdit box at the bottom of the }
{ disassembly list box, the following procedure converts this to a word }
{ and disassembles 15 instructions starting at this new address. }
procedure TSIMx86Form.DisAsmAdrsChange(Sender: TObject);
var i:integer;
DisAdrs:word;
begin
DisAdrs := HexToWord(DisAsmAdrs.Text);
DisAsm.Clear;
for i := 1 to 15 do
DisAsm.Items.Add(Disassemble2(DisAdrs));
end;
{ If the user presses on the down portion of the spinner at the bottom }
{ of the disassembly list box, this method increments the disassembly }
{ address and updates the disassembly list box. }
procedure TSIMx86Form.SpinButtonDownClick(Sender: TObject);
var value:word;
begin
Value := HexToWord(DisAsmAdrs.Text);
inc(Value);
DisAsmAdrs.Text := IntToHex(Value,4);
end;
{ If they press on the up arrow portion of the spinner, this code will }
{ decrement the starting disassembly address and update the list box. }
procedure TSIMx86Form.SpinButtonUpClick(Sender: TObject);
var value:word;
begin
Value := HexToWord(DisAsmAdrs.Text);
dec(Value);
DisAsmAdrs.Text := IntToHex(Value,4);
end;
procedure OneInstr;
procedure Store(mode:byte; index:word; value: word);
begin
case mode of
0: AX := value;
1: BX := value;
2: CX := value;
3: DX := value;
4: begin
WriteMem(bx, value and $FF);
WriteMem(bx+1, value shr 8);
end;
5: begin
WriteMem(bx+index, value and $FF);
WriteMem(bx+index+1, value shr 8);
end;
6: begin
WriteMem(index, value and $FF);
WriteMem(index+1, value shr 8);
end;
end;
end;
begin
with SIMx86Form do begin
if (PendingInt) and (not InInt) then
if (IntAdrs <> $FFFF) then
begin
InInt := true;
SaveAX := AX;
SaveBX := BX;
SaveCX := CX;
SaveDX := DX;
SaveIP := IP;
SaveLess := LessThanFlag.Checked;
SaveEqual:= EqualFlag.Checked;
PendingInt := false;
IP := IntAdrs;
end;
{ Okay, do the instruction here. }
Opcode := ReadMem(IP);
Operation := Opcode shr 5;
Reg := (Opcode shr 3) and $3;
RegMem := Opcode and $7;
InstrSize := 1;
case Reg of
0: Op1 := @AX;
1: Op1 := @BX;
2: Op1 := @CX;
3: Op1 := @DX;
end;
case RegMem of
0: Op2v := AX;
1: Op2v := BX;
2: Op2v := CX;
3: Op2v := DX;
4: Op2v := ReadMem(BX) + (ReadMem(BX+1) shl 8);
5: begin {[1000+bx]}
offset := BX + ReadMem(IP+1) + ReadMem(IP+2) shl 8;
Op2v := ReadMem(offset) + ReadMem(offset+1) shl 8;
InstrSize := 3;
end;
6: begin {[1000]}
offset := ReadMem(IP+1) + ReadMem(IP+2) shl 8;
Op2v := ReadMem(offset) + ReadMem(offset+1) shl 8;
InstrSize := 3;
end;
7: begin {1000}
Op2v := ReadMem(IP+1) + ReadMem(IP+2) shl 8;
InstrSize := 3;
end;
end;
case Operation of
1: Op1^ := Op1^ or Op2v;
2: Op1^ := Op1^ and Op2v;
3: begin
LessThanFlag.Checked := Op1^ < Op2v;
EqualFlag.Checked := Op1^ = Op2v;
end;
4: Op1^ := Op1^ - Op2v;
5: Op1^ := Op1^ + Op2v;
6: Op1^ := Op2v;
7: Store(regmem, ReadMem(IP+1) + ReadMem(IP+2) shl 8, Op1^);
0: case Reg of
2: Store(regmem,
ReadMem(IP+1) + ReadMem(IP+2) shl 8,
not Op2v);
1: begin {jumps}
InstrSize := 0;
case RegMem of
0: if EqualFlag.Checked then
IP := ReadMem(IP+1) +
ReadMem(IP+2) shl 8
else InstrSize := 3;
1: if not EqualFlag.Checked then
IP := ReadMem(IP+1) +
ReadMem(IP+2) shl 8
else InstrSize := 3;
2: if LessThanFlag.Checked then
IP := ReadMem(IP+1) +
ReadMem(IP+2) shl 8
else InstrSize := 3;
3: if LessThanFlag.Checked or
EqualFlag.Checked then
IP := ReadMem(IP+1) +
ReadMem(IP+2) shl 8
else InstrSize := 3;
4: if not (LessThanFlag.Checked or
EqualFlag.Checked) then
IP := ReadMem(IP+1) +
ReadMem(IP+2) shl 8
else InstrSize := 3;
5: if not LessThanFlag.Checked then
IP := ReadMem(IP+1) +
ReadMem(IP+2) shl 8
else InstrSize := 3;
6: IP := ReadMem(IP+1) + ReadMem(IP+2) shl 8;
7: begin
ErrorMsg('Illegal instruction',
IntToHex(IP,4));
Halted := true;
end;
end;
end;
3: begin
ErrorMsg('Illegal instruction',IntToHex(IP,4));
Halted := true;
end;
0: case (RegMem) of
0,1,2:begin
ErrorMsg('Illegal instruction',IntToHex(IP,4));
Halted := true;
InstrSize := 0;
end;
3: begin
ErrorMsg('BRK encountered',IntToHex(IP,4));
Halted := true;
InstrSize := 1;
end;
4: if (not InInt) then
begin
ErrorMsg('IRET encountered outside interrupt',
IntToHex(IP,4));
Halted := true;
InstrSize := 0;
end
else begin
AX := SaveAX;
BX := SaveBX;
CX := SaveCX;
DX := SaveDX;
IP := SaveIP;
LessThanFlag.Checked := SaveLess;
EqualFlag.Checked := SaveEqual;
InstrSize := 0;
InInt := false;
end;
5: begin
ErrorMsg('Halt encountered',IntToHex(IP,4));
Halted := true;
InstrSize := 0;
end;
6: begin
InputForm.ShowModal;
AX := InputValue;
InstrSize := 1;
end;
7: begin
Output.Items.Add(IntToHex(AX,4));
InstrSize := 1;
end;
end;
end;
end;
IP := IP + InstrSize;
end;
end;
procedure StopPgm;
begin
with SIMx86Form do begin
IPValue.Enabled := true;
DisAsmAdrs.Enabled := true;
SpinButton.Enabled := true;
RunBtn.Enabled := true;
StepBtn.Enabled := true;
AXValue.Enabled := true;
BXValue.Enabled := true;
CXValue.Enabled := true;
DXValue.Enabled := true;
LessThanFlag.Enabled := true;
EqualFlag.Enabled := true;
HaltBtn.Enabled := false;
RunningLite.Color := clGray;
MainMenu.Items[0].Enabled := true;
MainMenu.Items[1].Enabled := true;
PendingInt := false;
Instruction.Caption := Disassemble(IP);
end;
end;
{ If the users presses the "RUN" button, the following code kicks in }
{ the emulator. }
procedure TSIMx86Form.RunBtnClick(Sender: TObject);
begin
IPValue.Enabled := false;
DisAsmAdrs.Enabled := false;
SpinButton.Enabled := false;
RunBtn.Enabled := false;
StepBtn.Enabled := false;
AXValue.Enabled := false;
BXValue.Enabled := false;
CXValue.Enabled := false;
DXValue.Enabled := false;
LessThanFlag.Enabled := false;
EqualFlag.Enabled := false;
HaltBtn.Enabled := true;
RunningLite.Color := clRed;
PendingInt := false;
MainMenu.Items[0].Enabled := false;
MainMenu.Items[1].Enabled := false;
Halted := false;
Running := true;
InInt := false;
while not Halted do begin
Application.ProcessMessages;
OneInstr;
end;
Running := false;
RunningLite.Color := clGray;
StopPgm;
IPValue.Text := IntToHex(IP,4);
AXValue.Text := IntToHex(AX,4);
BXValue.Text := IntToHex(BX,4);
CXValue.Text := IntToHex(CX,4);
DXValue.Text := IntToHex(DX,4);
end;
procedure TSIMx86Form.HaltBtnClick(Sender: TObject);
begin
StopPgm;
Halted := true;
end;
{ If the user presses the reset button, the following method resets }
{ the machine. }
procedure TSIMx86Form.ResetBtnClick(Sender: TObject);
begin
AX := 0;
BX := 0;
CX := 0;
DX := 0;
AXValue.Text := '0000';
BXValue.Text := '0000';
CXValue.Text := '0000';
DXValue.Text := '0000';
if (ResetVect.Color <> clRed) then
begin
IP := HexToWord(ResetVect.Text);
IPValue.Text := ResetVect.Text;
end
else begin
IP := 0;
IPValue.Text := '0000';
end;
LessThanFlag.Checked := false;
EqualFlag.Checked := false;
PendingInt := false;
StopPgm;
Halted := true;
Output.Items.Clear;
Input.Items.Clear;
Instruction.Caption := Disassemble(IP);
end;
procedure TSIMx86Form.InterruptBtnClick(Sender: TObject);
begin
PendingInt := true;
end;
procedure TSIMx86Form.IntVectChange(Sender: TObject);
begin
CheckHex(IntVect);
if (IntVect.Color <> clRed) then
begin
IntAdrs := HexToWord(IntVect.Text);
end;
end;
procedure TSIMx86Form.IPValueChange(Sender: TObject);
begin
CheckHex(IPValue);
if IPValue.Color <> clRed then
begin
IP := HexToWord(IPValue.Text);
end;
Instruction.Caption := Disassemble(IP);
end;
procedure TSIMx86Form.StepBtnClick(Sender: TObject);
begin
OneInstr;
IPValue.Text := IntToHex(IP,4);
AXValue.Text := IntToHex(AX,4);
BXValue.Text := IntToHex(BX,4);
CXValue.Text := IntToHex(CX,4);
DXValue.Text := IntToHex(DX,4);
Instruction.Caption := Disassemble(IP);
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -