mirror of
https://github.com/danbulant/Cosmos
synced 2026-05-20 21:08:51 +00:00
This commit is contained in:
parent
f605ecb385
commit
3b73bb7140
8 changed files with 22 additions and 687 deletions
|
|
@ -17,9 +17,9 @@ namespace Cosmos.Debug.DebugStub {
|
|||
ESI = PushAllPtr.Value;
|
||||
WriteBytesToComPort(32);
|
||||
ESI = CallerESP.Address;
|
||||
WriteBytesToComPort(4);
|
||||
Call("DebugStub_ComWrite32");
|
||||
ESI = CallerEIP.Address;
|
||||
WriteBytesToComPort(4);
|
||||
Call("DebugStub_ComWrite32");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -140,7 +140,7 @@ namespace Cosmos.Debug.DebugStub {
|
|||
|
||||
// Send Calling EIP.
|
||||
ESI = CallerEIP.Address;
|
||||
WriteBytesToComPort(4);
|
||||
Call("DebugStub_ComWrite32");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -157,7 +157,7 @@ namespace Cosmos.Debug.DebugStub {
|
|||
ESI = EBP;
|
||||
ESI = ESI + 12;
|
||||
ECX = ESI[0];
|
||||
WriteBytesToComPort(2);
|
||||
Call("DebugStub_ComWrite16");
|
||||
|
||||
// Address of string
|
||||
ESI = EBP[8];
|
||||
|
|
@ -184,7 +184,7 @@ namespace Cosmos.Debug.DebugStub {
|
|||
|
||||
// pointer value
|
||||
ESI = EBP[8];
|
||||
WriteBytesToComPort(4);
|
||||
Call("DebugStub_ComWrite32");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ namespace Cosmos.Debug.DebugStub {
|
|||
public override void Assemble() {
|
||||
EAX.Push();
|
||||
ESI = ESP;
|
||||
WriteBytesToComPort(2);
|
||||
Call("DebugStub_ComWrite16");
|
||||
// Is a local var, cant use Return(4). X# issues the return.
|
||||
// This also allow the function to preserve EAX.
|
||||
EAX.Pop();
|
||||
|
|
@ -58,7 +58,7 @@ namespace Cosmos.Debug.DebugStub {
|
|||
public override void Assemble() {
|
||||
EAX.Push();
|
||||
ESI = ESP;
|
||||
WriteBytesToComPort(4);
|
||||
Call("DebugStub_ComWrite32");
|
||||
// Is a local var, cant use Return(4). X# issues the return.
|
||||
// This also allow the function to preserve EAX.
|
||||
EAX.Pop();
|
||||
|
|
|
|||
|
|
@ -1,114 +0,0 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using Cosmos.Assembler;
|
||||
using Cosmos.Assembler.x86;
|
||||
|
||||
namespace Cosmos.Debug.DebugStub {
|
||||
public class Screen : Cosmos.Assembler.Code {
|
||||
|
||||
public Screen(Assembler.Assembler aAssembler) : base(aAssembler) {}
|
||||
|
||||
public override void Assemble() {
|
||||
new Comment("X#: Group DebugStub");
|
||||
|
||||
new Comment("X#: procedure Cls {");
|
||||
new Label("DebugStub_Cls");
|
||||
|
||||
new Comment("VidBase");
|
||||
|
||||
new Comment("X#: ESI = $B8000");
|
||||
new Mov{ DestinationReg = RegistersEnum.ESI, SourceValue = 0xB8000 };
|
||||
|
||||
new Comment("X#: BeginLoop:");
|
||||
new Label("DebugStub_Cls_BeginLoop");
|
||||
|
||||
new Comment("Text");
|
||||
|
||||
new Comment("X#: AL = $00");
|
||||
new Mov{ DestinationReg = RegistersEnum.AL, SourceValue = 0x00 };
|
||||
|
||||
new Comment("X#: ESI[0] = AL");
|
||||
new Mov{ DestinationReg = RegistersEnum.ESI, DestinationIsIndirect = true, DestinationDisplacement = 0, SourceReg = RegistersEnum.AL };
|
||||
|
||||
new Comment("X#: ESI + 1");
|
||||
new INC { DestinationReg = RegistersEnum.ESI };
|
||||
|
||||
new Comment("Colour");
|
||||
|
||||
new Comment("X#: AL = $0A");
|
||||
new Mov{ DestinationReg = RegistersEnum.AL, SourceValue = 0x0A };
|
||||
|
||||
new Comment("X#: ESI[0] = AL");
|
||||
new Mov{ DestinationReg = RegistersEnum.ESI, DestinationIsIndirect = true, DestinationDisplacement = 0, SourceReg = RegistersEnum.AL };
|
||||
|
||||
new Comment("X#: ESI + 1");
|
||||
new INC { DestinationReg = RegistersEnum.ESI };
|
||||
|
||||
new Comment("End of Video Area");
|
||||
|
||||
new Comment("VidBase + 25 * 80 * 2 = B8FA0");
|
||||
|
||||
new Comment("X#: If (ESI < $B8FA0) goto BeginLoop");
|
||||
new Compare { DestinationReg = RegistersEnum.ESI, SourceValue = 0xB8FA0 };
|
||||
new ConditionalJump { Condition = ConditionalTestEnum.LessThan, DestinationLabel = "DebugStub_Cls_BeginLoop" };
|
||||
|
||||
new Comment("X#: }");
|
||||
new Label("DebugStub_Cls_Exit");
|
||||
new Return();
|
||||
|
||||
new Comment("X#: procedure DisplayWaitMsg {");
|
||||
new Label("DebugStub_DisplayWaitMsg");
|
||||
|
||||
new Comment("http://wiki.osdev.org/Text_UI");
|
||||
|
||||
new Comment("Later can cycle for x changes of second register:");
|
||||
|
||||
new Comment("http://wiki.osdev.org/Time_And_Date");
|
||||
|
||||
new Comment("X#: ESI = @..DebugWaitMsg");
|
||||
new Mov { DestinationReg = RegistersEnum.ESI , SourceRef = Cosmos.Assembler.ElementReference.New("DebugWaitMsg") };
|
||||
|
||||
new Comment("VidBase");
|
||||
|
||||
new Comment("X#: EDI = $B8000");
|
||||
new Mov{ DestinationReg = RegistersEnum.EDI, SourceValue = 0xB8000 };
|
||||
|
||||
new Comment("10 lines down, 20 cols in (10 * 80 + 20) * 2)");
|
||||
|
||||
new Comment("X#: EDI + 1640");
|
||||
new Add { DestinationReg = RegistersEnum.EDI, SourceValue = 1640 };
|
||||
|
||||
new Comment("Read and copy string till 0 terminator");
|
||||
|
||||
new Comment("X#: ReadChar:");
|
||||
new Label("DebugStub_DisplayWaitMsg_ReadChar");
|
||||
|
||||
new Comment("X#: AL = ESI[0]");
|
||||
new Mov{ DestinationReg = RegistersEnum.AL, SourceReg = RegistersEnum.ESI, SourceIsIndirect = true, SourceDisplacement = 0 };
|
||||
|
||||
new Comment("X#: if (AL = 0) goto AfterMsg");
|
||||
new Compare { DestinationReg = RegistersEnum.AL, SourceValue = 0 };
|
||||
new ConditionalJump { Condition = ConditionalTestEnum.Zero, DestinationLabel = "DebugStub_DisplayWaitMsg_AfterMsg" };
|
||||
|
||||
new Comment("X#: ESI + 1");
|
||||
new INC { DestinationReg = RegistersEnum.ESI };
|
||||
|
||||
new Comment("X#: EDI[0] = AL");
|
||||
new Mov{ DestinationReg = RegistersEnum.EDI, DestinationIsIndirect = true, DestinationDisplacement = 0, SourceReg = RegistersEnum.AL };
|
||||
|
||||
new Comment("X#: EDI + 2");
|
||||
new Add { DestinationReg = RegistersEnum.EDI, SourceValue = 2 };
|
||||
|
||||
new Comment("X#: Goto ReadChar");
|
||||
new Jump { DestinationLabel = "DebugStub_DisplayWaitMsg_ReadChar" };
|
||||
|
||||
new Comment("X#: AfterMsg:");
|
||||
new Label("DebugStub_DisplayWaitMsg_AfterMsg");
|
||||
|
||||
new Comment("X#: }");
|
||||
new Label("DebugStub_DisplayWaitMsg_Exit");
|
||||
new Return();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -8,12 +8,12 @@ BeginLoop:
|
|||
# Text
|
||||
AL = $00
|
||||
ESI[0] = AL
|
||||
ESI + 1
|
||||
ESI++
|
||||
|
||||
# Colour
|
||||
AL = $0A
|
||||
ESI[0] = AL
|
||||
ESI + 1
|
||||
ESI++
|
||||
|
||||
# End of Video Area
|
||||
# VidBase + 25 * 80 * 2 = B8FA0
|
||||
|
|
@ -36,7 +36,7 @@ procedure DisplayWaitMsg {
|
|||
ReadChar:
|
||||
AL = ESI[0]
|
||||
if (AL = 0) goto AfterMsg
|
||||
ESI + 1
|
||||
ESI++
|
||||
EDI[0] = AL
|
||||
EDI + 2
|
||||
Goto ReadChar
|
||||
|
|
|
|||
|
|
@ -1,427 +0,0 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using Cosmos.Assembler;
|
||||
using Cosmos.Assembler.x86;
|
||||
|
||||
namespace Cosmos.Debug.DebugStub {
|
||||
public class Serial : Cosmos.Assembler.Code {
|
||||
|
||||
public Serial(Assembler.Assembler aAssembler) : base(aAssembler) {}
|
||||
|
||||
public override void Assemble() {
|
||||
new Comment("X#: Group DebugStub");
|
||||
|
||||
new Comment("mComPortAddresses = 0x3F8, 0x2F8, 0x3E8, 0x2E8;");
|
||||
|
||||
new Comment("Currently hardcoded to COM1.");
|
||||
|
||||
new Comment("X#: var .ComAddr = $03F8");
|
||||
mAssembler.DataMembers.Add(new DataMember("DebugStub_ComAddr", 0x03F8));
|
||||
|
||||
new Comment("All information relating to our serial usage should be documented in this comment.");
|
||||
|
||||
new Comment("http://wiki.osdev.org/Serial_ports");
|
||||
|
||||
new Comment("");
|
||||
|
||||
new Comment("We do not use IRQs for debugstub serial. This is becuase DebugStub (DS)");
|
||||
|
||||
new Comment("MUST be:");
|
||||
|
||||
new Comment("- As simple as possible");
|
||||
|
||||
new Comment("- Interact as minimal as possible wtih normal Cosmos code because");
|
||||
|
||||
new Comment("the debugstub must *always* work even if the normal code is fubarred");
|
||||
|
||||
new Comment("");
|
||||
|
||||
new Comment("The serial port that is used for DS should be 'hidden' from Cosmos main");
|
||||
|
||||
new Comment("so that Cosmos main pretends it does not exist.");
|
||||
|
||||
new Comment("");
|
||||
|
||||
new Comment("IRQs would create a clash/mix of code.");
|
||||
|
||||
new Comment("This does make the serial code in DebugStub inefficient, but its well worth");
|
||||
|
||||
new Comment("the benefits received by following these rules.");
|
||||
|
||||
new Comment("");
|
||||
|
||||
new Comment("Baud rate is set to 115200. Likely our code could not exceed this rate");
|
||||
|
||||
new Comment("anyways the way it is written and there are compatibility issues on some");
|
||||
|
||||
new Comment("hardware above this rate.");
|
||||
|
||||
new Comment("");
|
||||
|
||||
new Comment("We assume a minimum level of a 16550A, which should be no problem on any");
|
||||
|
||||
new Comment("common hardware today. VMWare emulates the 16550A");
|
||||
|
||||
new Comment("");
|
||||
|
||||
new Comment("We do not handle flow control for outbound data (DS --> DC).");
|
||||
|
||||
new Comment("The DebugConnector (DC, the code in the Visual Studio side) however is threaded");
|
||||
|
||||
new Comment("and easily should be able to receive data faster than we can send it.");
|
||||
|
||||
new Comment("Most things are transactional with data being sent only when asked for, but");
|
||||
|
||||
new Comment("with tracing we do send a data directly.");
|
||||
|
||||
new Comment("");
|
||||
|
||||
new Comment("Currently there is no inbound flow control either (DC --> DS)");
|
||||
|
||||
new Comment("For now we assume all commands in bound are 16 bytes or less to ensure");
|
||||
|
||||
new Comment("that they fit in the FIFO. Commands in DS must wait for a command ID ACK");
|
||||
|
||||
new Comment("before sending another command.");
|
||||
|
||||
new Comment("See notes in ProcessCommand.");
|
||||
|
||||
new Comment("");
|
||||
|
||||
new Comment("http:#www.nondot.org/sabre/os/files/Communication/ser_port.txt");
|
||||
|
||||
new Comment("Todo Auto params");
|
||||
|
||||
new Comment("Todo ebp frame ptr auto etc");
|
||||
|
||||
new Comment("X#: procedure InitSerial {");
|
||||
new Label("DebugStub_InitSerial");
|
||||
|
||||
new Comment("X#: DX = .ComAddr");
|
||||
new Mov { DestinationReg = RegistersEnum.DX , SourceRef = Cosmos.Assembler.ElementReference.New("DebugStub_ComAddr"), SourceIsIndirect = true };
|
||||
|
||||
new Comment("Disable interrupts");
|
||||
|
||||
new Comment("X#: BX = DX");
|
||||
new Mov{ DestinationReg = RegistersEnum.BX, SourceReg = RegistersEnum.DX };
|
||||
|
||||
new Comment("X#: DX + 1");
|
||||
new INC { DestinationReg = RegistersEnum.DX };
|
||||
|
||||
new Comment("X#: AL = 0");
|
||||
new Mov{ DestinationReg = RegistersEnum.AL, SourceValue = 0 };
|
||||
|
||||
new Comment("X#: Port[DX] = AL");
|
||||
new Out { DestinationReg = RegistersEnum.AL};
|
||||
|
||||
new Comment("Enable DLAB (set baud rate divisor)");
|
||||
|
||||
new Comment("X#: DX = BX");
|
||||
new Mov{ DestinationReg = RegistersEnum.DX, SourceReg = RegistersEnum.BX };
|
||||
|
||||
new Comment("X#: DX + 3");
|
||||
new Add { DestinationReg = RegistersEnum.DX, SourceValue = 3 };
|
||||
|
||||
new Comment("X#: AL = $80");
|
||||
new Mov{ DestinationReg = RegistersEnum.AL, SourceValue = 0x80 };
|
||||
|
||||
new Comment("X#: Port[DX] = AL");
|
||||
new Out { DestinationReg = RegistersEnum.AL};
|
||||
|
||||
new Comment("0x01, 0x00 - 115200");
|
||||
|
||||
new Comment("0x02, 0x00 - 57600");
|
||||
|
||||
new Comment("0x03, 0x00 - 38400");
|
||||
|
||||
new Comment("");
|
||||
|
||||
new Comment("Set divisor (lo byte)");
|
||||
|
||||
new Comment("X#: DX = BX");
|
||||
new Mov{ DestinationReg = RegistersEnum.DX, SourceReg = RegistersEnum.BX };
|
||||
|
||||
new Comment("X#: AL = $01");
|
||||
new Mov{ DestinationReg = RegistersEnum.AL, SourceValue = 0x01 };
|
||||
|
||||
new Comment("X#: Port[DX] = AL");
|
||||
new Out { DestinationReg = RegistersEnum.AL};
|
||||
|
||||
new Comment("hi byte");
|
||||
|
||||
new Comment("X#: DX = BX");
|
||||
new Mov{ DestinationReg = RegistersEnum.DX, SourceReg = RegistersEnum.BX };
|
||||
|
||||
new Comment("X#: DX + 1");
|
||||
new INC { DestinationReg = RegistersEnum.DX };
|
||||
|
||||
new Comment("X#: AL = $00");
|
||||
new Mov{ DestinationReg = RegistersEnum.AL, SourceValue = 0x00 };
|
||||
|
||||
new Comment("X#: Port[DX] = AL");
|
||||
new Out { DestinationReg = RegistersEnum.AL};
|
||||
|
||||
new Comment("8N1");
|
||||
|
||||
new Comment("X#: DX = BX");
|
||||
new Mov{ DestinationReg = RegistersEnum.DX, SourceReg = RegistersEnum.BX };
|
||||
|
||||
new Comment("X#: DX + 3");
|
||||
new Add { DestinationReg = RegistersEnum.DX, SourceValue = 3 };
|
||||
|
||||
new Comment("X#: AL = $03");
|
||||
new Mov{ DestinationReg = RegistersEnum.AL, SourceValue = 0x03 };
|
||||
|
||||
new Comment("X#: Port[DX] = AL");
|
||||
new Out { DestinationReg = RegistersEnum.AL};
|
||||
|
||||
new Comment("Enable FIFO, clear them");
|
||||
|
||||
new Comment("Set 14-byte threshold for IRQ.");
|
||||
|
||||
new Comment("We dont use IRQ, but you cant set it to 0");
|
||||
|
||||
new Comment("either. IRQ is enabled/diabled separately");
|
||||
|
||||
new Comment("X#: DX = BX");
|
||||
new Mov{ DestinationReg = RegistersEnum.DX, SourceReg = RegistersEnum.BX };
|
||||
|
||||
new Comment("X#: DX + 2");
|
||||
new Add { DestinationReg = RegistersEnum.DX, SourceValue = 2 };
|
||||
|
||||
new Comment("X#: AL = $C7");
|
||||
new Mov{ DestinationReg = RegistersEnum.AL, SourceValue = 0xC7 };
|
||||
|
||||
new Comment("X#: Port[DX] = AL");
|
||||
new Out { DestinationReg = RegistersEnum.AL};
|
||||
|
||||
new Comment("0x20 AFE Automatic Flow control Enable - 16550 (VMWare uses 16550A) is most common and does not support it");
|
||||
|
||||
new Comment("0x02 RTS");
|
||||
|
||||
new Comment("0x01 DTR");
|
||||
|
||||
new Comment("Send 0x03 if no AFE");
|
||||
|
||||
new Comment("X#: DX = BX");
|
||||
new Mov{ DestinationReg = RegistersEnum.DX, SourceReg = RegistersEnum.BX };
|
||||
|
||||
new Comment("X#: DX + 4");
|
||||
new Add { DestinationReg = RegistersEnum.DX, SourceValue = 4 };
|
||||
|
||||
new Comment("X#: AL = $03");
|
||||
new Mov{ DestinationReg = RegistersEnum.AL, SourceValue = 0x03 };
|
||||
|
||||
new Comment("X#: Port[DX] = AL");
|
||||
new Out { DestinationReg = RegistersEnum.AL};
|
||||
|
||||
new Comment("X#: }");
|
||||
new Label("DebugStub_InitSerial_Exit");
|
||||
new Return();
|
||||
|
||||
new Comment("Modifies: AL, DX");
|
||||
|
||||
new Comment("X#: procedure ComReadAL {");
|
||||
new Label("DebugStub_ComReadAL");
|
||||
|
||||
new Comment("X#: DX = .ComAddr");
|
||||
new Mov { DestinationReg = RegistersEnum.DX , SourceRef = Cosmos.Assembler.ElementReference.New("DebugStub_ComAddr"), SourceIsIndirect = true };
|
||||
|
||||
new Comment("X#: DX + 5");
|
||||
new Add { DestinationReg = RegistersEnum.DX, SourceValue = 5 };
|
||||
|
||||
new Comment("Wait for port to be ready");
|
||||
|
||||
new Comment("X#: Wait:");
|
||||
new Label("DebugStub_ComReadAL_Wait");
|
||||
|
||||
new Comment("X#: AL = Port[DX]");
|
||||
new IN { DestinationReg = RegistersEnum.AL};
|
||||
|
||||
new Comment("X#: AL ?& $01");
|
||||
new Test { DestinationReg = RegistersEnum.AL, SourceValue = 0x01 };
|
||||
|
||||
new Comment("X#: if 0 goto Wait");
|
||||
new ConditionalJump { Condition = ConditionalTestEnum.Zero, DestinationLabel = "DebugStub_ComReadAL_Wait" };
|
||||
|
||||
new Comment("X#: DX = .ComAddr");
|
||||
new Mov { DestinationReg = RegistersEnum.DX , SourceRef = Cosmos.Assembler.ElementReference.New("DebugStub_ComAddr"), SourceIsIndirect = true };
|
||||
|
||||
new Comment("Read byte");
|
||||
|
||||
new Comment("X#: AL = Port[DX]");
|
||||
new IN { DestinationReg = RegistersEnum.AL};
|
||||
|
||||
new Comment("X#: }");
|
||||
new Label("DebugStub_ComReadAL_Exit");
|
||||
new Return();
|
||||
|
||||
new Comment("Input: EDI");
|
||||
|
||||
new Comment("Output: [EDI]");
|
||||
|
||||
new Comment("Modified: AL, DX, EDI (+1)");
|
||||
|
||||
new Comment("");
|
||||
|
||||
new Comment("Reads a byte into [EDI] and does EDI + 1");
|
||||
|
||||
new Comment("X#: procedure ComRead8 {");
|
||||
new Label("DebugStub_ComRead8");
|
||||
|
||||
new Comment("X#: Call .ComReadAL");
|
||||
new Call { DestinationLabel = "DebugStub_ComReadAL" };
|
||||
|
||||
new Comment("X#: EDI[0] = AL");
|
||||
new Mov{ DestinationReg = RegistersEnum.EDI, DestinationIsIndirect = true, DestinationDisplacement = 0, SourceReg = RegistersEnum.AL };
|
||||
|
||||
new Comment("X#: EDI + 1");
|
||||
new INC { DestinationReg = RegistersEnum.EDI };
|
||||
|
||||
new Comment("X#: }");
|
||||
new Label("DebugStub_ComRead8_Exit");
|
||||
new Return();
|
||||
|
||||
new Comment("X#: procedure ComRead16 {");
|
||||
new Label("DebugStub_ComRead16");
|
||||
|
||||
new Comment("X#: Call .ComRead8");
|
||||
new Call { DestinationLabel = "DebugStub_ComRead8" };
|
||||
|
||||
new Comment("X#: Call .ComRead8");
|
||||
new Call { DestinationLabel = "DebugStub_ComRead8" };
|
||||
|
||||
new Comment("X#: }");
|
||||
new Label("DebugStub_ComRead16_Exit");
|
||||
new Return();
|
||||
|
||||
new Comment("X#: procedure ComRead32 {");
|
||||
new Label("DebugStub_ComRead32");
|
||||
|
||||
new Comment("X#: Call .ComRead8");
|
||||
new Call { DestinationLabel = "DebugStub_ComRead8" };
|
||||
|
||||
new Comment("X#: Call .ComRead8");
|
||||
new Call { DestinationLabel = "DebugStub_ComRead8" };
|
||||
|
||||
new Comment("X#: Call .ComRead8");
|
||||
new Call { DestinationLabel = "DebugStub_ComRead8" };
|
||||
|
||||
new Comment("X#: Call .ComRead8");
|
||||
new Call { DestinationLabel = "DebugStub_ComRead8" };
|
||||
|
||||
new Comment("X#: }");
|
||||
new Label("DebugStub_ComRead32_Exit");
|
||||
new Return();
|
||||
|
||||
new Comment("Input: AL");
|
||||
|
||||
new Comment("Output: None");
|
||||
|
||||
new Comment("Modifies: EDX, ESI");
|
||||
|
||||
new Comment("X#: procedure ComWriteAL {");
|
||||
new Label("DebugStub_ComWriteAL");
|
||||
|
||||
new Comment("X#: +EAX");
|
||||
new Push { DestinationReg = RegistersEnum.EAX};
|
||||
|
||||
new Comment("X#: ESI = ESP");
|
||||
new Mov{ DestinationReg = RegistersEnum.ESI, SourceReg = RegistersEnum.ESP };
|
||||
|
||||
new Comment("X#: Call .ComWrite8");
|
||||
new Call { DestinationLabel = "DebugStub_ComWrite8" };
|
||||
|
||||
new Comment("Is a local var, cant use Return(4). X# issues the return.");
|
||||
|
||||
new Comment("This also allows the function to preserve EAX.");
|
||||
|
||||
new Comment("X#: -EAX");
|
||||
new Pop { DestinationReg = RegistersEnum.EAX};
|
||||
|
||||
new Comment("X#: }");
|
||||
new Label("DebugStub_ComWriteAL_Exit");
|
||||
new Return();
|
||||
|
||||
new Comment("X#: procedure ComWrite8 {");
|
||||
new Label("DebugStub_ComWrite8");
|
||||
|
||||
new Comment("Input: ESI");
|
||||
|
||||
new Comment("Output: None");
|
||||
|
||||
new Comment("Modifies: EAX, EDX");
|
||||
|
||||
new Comment("");
|
||||
|
||||
new Comment("Sends byte at [ESI] to com port and does esi + 1");
|
||||
|
||||
new Comment("");
|
||||
|
||||
new Comment("This sucks to use the stack, but x86 can only read and write ports from AL and");
|
||||
|
||||
new Comment("we need to read a port before we can write out the value to another port.");
|
||||
|
||||
new Comment("The overhead is a lot, but compared to the speed of the serial and the fact");
|
||||
|
||||
new Comment("that we wait on the serial port anyways, its a wash.");
|
||||
|
||||
new Comment("");
|
||||
|
||||
new Comment("This could be changed to use interrupts, but that then complicates");
|
||||
|
||||
new Comment("the code and causes interaction with other code. DebugStub should be");
|
||||
|
||||
new Comment("as isolated as possible from any other code.");
|
||||
|
||||
new Comment("Sucks again to use DX just for this, but x86 only supports");
|
||||
|
||||
new Comment("8 bit address for literals on ports");
|
||||
|
||||
new Comment("X#: DX = .ComAddr");
|
||||
new Mov { DestinationReg = RegistersEnum.DX , SourceRef = Cosmos.Assembler.ElementReference.New("DebugStub_ComAddr"), SourceIsIndirect = true };
|
||||
|
||||
new Comment("X#: DX + 5");
|
||||
new Add { DestinationReg = RegistersEnum.DX, SourceValue = 5 };
|
||||
|
||||
new Comment("Wait for serial port to be ready");
|
||||
|
||||
new Comment("Bit 5 (0x20) test for Transmit Holding Register to be empty.");
|
||||
|
||||
new Comment("X#: Wait:");
|
||||
new Label("DebugStub_ComWrite8_Wait");
|
||||
|
||||
new Comment("X#: AL = Port[DX]");
|
||||
new IN { DestinationReg = RegistersEnum.AL};
|
||||
|
||||
new Comment("X#: AL ?& $20");
|
||||
new Test { DestinationReg = RegistersEnum.AL, SourceValue = 0x20 };
|
||||
|
||||
new Comment("X#: if 0 goto Wait");
|
||||
new ConditionalJump { Condition = ConditionalTestEnum.Zero, DestinationLabel = "DebugStub_ComWrite8_Wait" };
|
||||
|
||||
new Comment("Set address of port");
|
||||
|
||||
new Comment("X#: DX = $03F8");
|
||||
new Mov{ DestinationReg = RegistersEnum.DX, SourceValue = 0x03F8 };
|
||||
|
||||
new Comment("Get byte to send");
|
||||
|
||||
new Comment("X#: AL = ESI[0]");
|
||||
new Mov{ DestinationReg = RegistersEnum.AL, SourceReg = RegistersEnum.ESI, SourceIsIndirect = true, SourceDisplacement = 0 };
|
||||
|
||||
new Comment("Send the byte");
|
||||
|
||||
new Comment("X#: Port[DX] = AL");
|
||||
new Out { DestinationReg = RegistersEnum.AL};
|
||||
|
||||
new Comment("X#: ESI + 1");
|
||||
new INC { DestinationReg = RegistersEnum.ESI };
|
||||
|
||||
new Comment("X#: }");
|
||||
new Label("DebugStub_ComWrite8_Exit");
|
||||
new Return();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -121,7 +121,7 @@ Wait:
|
|||
procedure ComRead8 {
|
||||
Call .ComReadAL
|
||||
EDI[0] = AL
|
||||
EDI + 1
|
||||
EDI++
|
||||
}
|
||||
procedure ComRead16 {
|
||||
Call .ComRead8
|
||||
|
|
@ -183,3 +183,13 @@ Wait:
|
|||
|
||||
ESI + 1
|
||||
}
|
||||
procedure ComWrite16 {
|
||||
Call .ComWrite8
|
||||
Call .ComWrite8
|
||||
}
|
||||
procedure ComWrite32 {
|
||||
Call .ComWrite8
|
||||
Call .ComWrite8
|
||||
Call .ComWrite8
|
||||
Call .ComWrite8
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,134 +0,0 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using Cosmos.Assembler;
|
||||
using Cosmos.Assembler.x86;
|
||||
|
||||
namespace Cosmos.Debug.DebugStub {
|
||||
public class TracerEntry : Cosmos.Assembler.Code {
|
||||
|
||||
public TracerEntry(Assembler.Assembler aAssembler) : base(aAssembler) {}
|
||||
|
||||
public override void Assemble() {
|
||||
new Comment("We need to make sure Int3 can never run more than one instance at a time.");
|
||||
|
||||
new Comment("We are not threaded yet, when we are we have to change stuff to thread vars and a lot of other stuff.");
|
||||
|
||||
new Comment("Two Int3 calls currently can never happen at the same time normally, but IRQs can happen while the DebugStub is");
|
||||
|
||||
new Comment("running. We also need to make sure IRQs are allowed to run during DebugStub as DebugStub can wait for");
|
||||
|
||||
new Comment("a long time on commands.");
|
||||
|
||||
new Comment("So we need to disable interrupts immediately and set a flag, then reenable interrupts if they were enabled");
|
||||
|
||||
new Comment("when we disabled them. Later this can be replaced by some kind of critical section / lock around this code.");
|
||||
|
||||
new Comment("Currently IRQs are disabled - we need to fix DS before we can reenable them and add support for critical sections / locks here.");
|
||||
|
||||
new Comment("-http:#www.codemaestro.com/reviews/8");
|
||||
|
||||
new Comment("-http:#en.wikipedia.org/wiki/Spinlock - Uses a register which is a problem for us");
|
||||
|
||||
new Comment("-http:#wiki.osdev.org/Spinlock");
|
||||
|
||||
new Comment("-Looks good and also allows testing intead of waiting");
|
||||
|
||||
new Comment("-Wont require us to disable / enable IRQs");
|
||||
|
||||
new Comment("Comment");
|
||||
|
||||
new Comment("X#: Group DebugStub");
|
||||
|
||||
new Comment("X#: InterruptHandler TracerEntry {");
|
||||
new Label("DebugStub_TracerEntry");
|
||||
|
||||
new Comment("This code is temporarily disabled as IRQs are not enabled right now.");
|
||||
|
||||
new Comment("LockOrExit");
|
||||
|
||||
new Comment("EBP is restored by PopAll, but SendFrame uses it. Could");
|
||||
|
||||
new Comment("get it from the PushAll data, but this is easier.");
|
||||
|
||||
new Comment("X#: .CallerEBP = EBP");
|
||||
new Mov { DestinationRef = Cosmos.Assembler.ElementReference.New("DebugStub_CallerEBP"), DestinationIsIndirect = true , SourceReg = RegistersEnum.EBP };
|
||||
|
||||
new Comment("Could get ESP from PushAll but this is easier.");
|
||||
|
||||
new Comment("Also allows us to use the stack before PushAll if we ever need it.");
|
||||
|
||||
new Comment("We cant modify any registers since we havent done PushAll yet");
|
||||
|
||||
new Comment("Maybe we could do a sub(4) on memory direct..");
|
||||
|
||||
new Comment("But for now we remove from ESP which the Int3 produces,");
|
||||
|
||||
new Comment("store ESP, then restore ESP so we don't cause stack corruption.");
|
||||
|
||||
new Comment("12 bytes for EFLAGS, CS, EIP");
|
||||
|
||||
new Comment("X#: ESP + 12");
|
||||
new Add { DestinationReg = RegistersEnum.ESP, SourceValue = 12 };
|
||||
|
||||
new Comment("X#: .CallerESP = ESP");
|
||||
new Mov { DestinationRef = Cosmos.Assembler.ElementReference.New("DebugStub_CallerESP"), DestinationIsIndirect = true , SourceReg = RegistersEnum.ESP };
|
||||
|
||||
new Comment("X#: ESP - 12");
|
||||
new Sub { DestinationReg = RegistersEnum.ESP, SourceValue = 12 };
|
||||
|
||||
new Comment("X#: PushAll");
|
||||
new Pushad();
|
||||
|
||||
new Comment("Save current ESP so we can look at the results of PushAll later");
|
||||
|
||||
new Comment("X#: .PushAllPtr = ESP");
|
||||
new Mov { DestinationRef = Cosmos.Assembler.ElementReference.New("DebugStub_PushAllPtr"), DestinationIsIndirect = true , SourceReg = RegistersEnum.ESP };
|
||||
|
||||
new Comment("Get current ESP and add 32. This will skip over the PushAll and point");
|
||||
|
||||
new Comment("us at the call data from Int3.");
|
||||
|
||||
new Comment("X#: EBP = ESP");
|
||||
new Mov{ DestinationReg = RegistersEnum.EBP, SourceReg = RegistersEnum.ESP };
|
||||
|
||||
new Comment("X#: EBP + 32");
|
||||
new Add { DestinationReg = RegistersEnum.EBP, SourceValue = 32 };
|
||||
|
||||
new Comment("Caller EIP");
|
||||
|
||||
new Comment("X#: EAX = EBP[0]");
|
||||
new Mov{ DestinationReg = RegistersEnum.EAX, SourceReg = RegistersEnum.EBP, SourceIsIndirect = true, SourceDisplacement = 0 };
|
||||
|
||||
new Comment("EIP is pointer to op after our call. Int3 is 1 byte so we subtract 1.");
|
||||
|
||||
new Comment("Note - when we used call it was 5 (size of our call + address)");
|
||||
|
||||
new Comment("so we get the EIP as IL2CPU records it. Its also useful for when we");
|
||||
|
||||
new Comment("wil be changing ops that call this stub.");
|
||||
|
||||
new Comment("X#: EAX - 1");
|
||||
new Dec { DestinationReg = RegistersEnum.EAX };
|
||||
|
||||
new Comment("Store it for later use.");
|
||||
|
||||
new Comment("X#: .CallerEIP = EAX");
|
||||
new Mov { DestinationRef = Cosmos.Assembler.ElementReference.New("DebugStub_CallerEIP"), DestinationIsIndirect = true , SourceReg = RegistersEnum.EAX };
|
||||
|
||||
new Comment("X#: Call .Executing");
|
||||
new Call { DestinationLabel = "DebugStub_Executing" };
|
||||
|
||||
new Comment("X#: PopAll");
|
||||
new Popad();
|
||||
|
||||
new Comment("Temp disabled, see comment on LockOrExit above");
|
||||
|
||||
new Comment("Unlock");
|
||||
|
||||
new Comment("X#: }");
|
||||
new Label("DebugStub_TracerEntry_Exit");
|
||||
new IRET();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -53,7 +53,7 @@ InterruptHandler TracerEntry {
|
|||
# Note - when we used call it was 5 (size of our call + address)
|
||||
# so we get the EIP as IL2CPU records it. Its also useful for when we
|
||||
# wil be changing ops that call this stub.
|
||||
EAX - 1
|
||||
EAX--
|
||||
|
||||
# Store it for later use.
|
||||
.CallerEIP = EAX
|
||||
|
|
|
|||
Loading…
Reference in a new issue