/// <summary> /// Executes an x86 Instruction to call the specified Library/API Ordinal with the specified arguments /// </summary> /// <param name="exportedModuleSegment"></param> /// <param name="apiOrdinal"></param> /// <param name="apiArguments"></param> protected void ExecuteApiTest(ushort exportedModuleSegment, ushort apiOrdinal, IEnumerable <ushort> apiArguments) { if (!mbbsEmuProtectedModeMemoryCore.HasSegment(STACK_SEGMENT)) { mbbsEmuProtectedModeMemoryCore.AddSegment(STACK_SEGMENT); } if (mbbsEmuProtectedModeMemoryCore.HasSegment(CODE_SEGMENT)) { mbbsEmuProtectedModeMemoryCore.RemoveSegment(CODE_SEGMENT); } var apiTestCodeSegment = new Segment { Ordinal = CODE_SEGMENT, //Create a new CODE Segment with a //simple ASM call for CALL FAR librarySegment:apiOrdinal Data = new byte[] { 0x9A, (byte)(apiOrdinal & 0xFF), (byte)(apiOrdinal >> 8), (byte)(exportedModuleSegment & 0xFF), (byte)(exportedModuleSegment >> 8), }, Flag = (ushort)EnumSegmentFlags.Code }; mbbsEmuProtectedModeMemoryCore.AddSegment(apiTestCodeSegment); mbbsEmuCpuRegisters.CS = CODE_SEGMENT; mbbsEmuCpuRegisters.IP = 0; //Push Arguments to Stack foreach (var a in apiArguments.Reverse()) { mbbsEmuCpuCore.Push(a); } //Process Instruction, e.g. call the method mbbsEmuCpuCore.Tick(); if (isCdeclOrdinal(apiOrdinal)) { foreach (var a in apiArguments) { mbbsEmuCpuCore.Pop(); } } }
public void EndOfSegmentString() { ushort segment = 1; var memoryCore = new ProtectedModeMemoryCore(_logger); memoryCore.AddSegment(segment); var testString = new string('X', 5) + "\0"; var testStringOffset = (ushort)(ushort.MaxValue - testString.Length + 1); (memoryCore as IMemoryCore).SetArray(1, testStringOffset, Encoding.ASCII.GetBytes(testString)); var stringFromMemory = Encoding.ASCII.GetString((memoryCore as IMemoryCore).GetString(1, testStringOffset, stripNull: false)); stringFromMemory.Should().Be(testString); }
protected void CreateCodeSegment(InstructionList instructionList, ushort segmentOrdinal = 1) { mbbsEmuProtectedModeMemoryCore.AddSegment(segmentOrdinal, instructionList); }
private void CreateCodeSegment(InstructionList instructionList, ushort segmentOrdinal = 0x1000) { protectedModeMemoryCore.AddSegment(segmentOrdinal, instructionList); }
/// <summary> /// Constructor for MbbsModule /// /// Pass in an empty/blank moduleIdentifier for a Unit Test/Fake Module /// </summary> /// <param name="fileUtility"></param> /// <param name="clock"></param> /// <param name="logger"></param> /// <param name="moduleConfig"></param> /// <param name="memoryCore"></param> public MbbsModule(IFileUtility fileUtility, IClock clock, ILogger logger, ModuleConfiguration moduleConfig, ProtectedModeMemoryCore memoryCore = null) { _fileUtility = fileUtility; _logger = logger; _clock = clock; ModuleConfig = moduleConfig; ModuleIdentifier = moduleConfig.ModuleIdentifier; ModuleDlls = new List <MbbsDll>(); //Sanitize and setup Path if (string.IsNullOrEmpty(moduleConfig.ModulePath)) { moduleConfig.ModulePath = Directory.GetCurrentDirectory(); } if (!Path.EndsInDirectorySeparator(moduleConfig.ModulePath)) { moduleConfig.ModulePath += Path.DirectorySeparatorChar; } ModulePath = moduleConfig.ModulePath; // will be null in tests if (string.IsNullOrEmpty(ModuleIdentifier)) { Mdf = MdfFile.createForTest(); ModuleDlls.Add(new MbbsDll(fileUtility, logger) { File = NEFile.createForTest() }); } else { //Verify Module Path Exists if (!Directory.Exists(ModulePath)) { _logger.Error($"Unable to find the specified directory for the module {ModuleIdentifier.ToUpper()}: {ModulePath}"); _logger.Error("Please verify your Command Line Argument or the path specified in your Module JSON File and try again."); throw new DirectoryNotFoundException($"Unable to locate {ModulePath}"); } //Verify MDF File Exists var mdfFile = fileUtility.FindFile(ModulePath, $"{ModuleIdentifier}.MDF"); var fullMdfFilePath = Path.Combine(ModulePath, mdfFile); if (!File.Exists(fullMdfFilePath)) { _logger.Error($"Unable to locate {fullMdfFilePath}"); _logger.Error($"Please verify your Command Line Argument or the Module JSON File to ensure {ModuleIdentifier} is the correct Module Identifier and that the Module is installed properly."); throw new FileNotFoundException($"Unable to locate Module: {fullMdfFilePath}"); } Mdf = new MdfFile(fullMdfFilePath); LoadModuleDll(Mdf.DLLFiles[0].Trim()); if (Mdf.MSGFiles.Count > 0) { Msgs = new List <MsgFile>(Mdf.MSGFiles.Count); foreach (var m in Mdf.MSGFiles) { Msgs.Add(new MsgFile(_fileUtility, ModulePath, m)); } } } //Set Initial Values RtkickRoutines = new PointerDictionary <RealTimeRoutine>(); RtihdlrRoutines = new PointerDictionary <RealTimeRoutine>(); TaskRoutines = new PointerDictionary <RealTimeRoutine>(); GlobalCommandHandlers = new List <FarPtr>(); ExportedModuleDictionary = new Dictionary <ushort, IExportedModule>(6); ExecutionUnits = new Queue <ExecutionUnit>(2); Memory = memoryCore ?? new ProtectedModeMemoryCore(logger); ProtectedMemory = (ProtectedModeMemoryCore)Memory; //Declare PSP Segment var psp = new PSPStruct { NextSegOffset = 0x9FFF, EnvSeg = 0xFFFF }; ProtectedMemory.AddSegment(0x4000); Memory.SetArray(0x4000, 0, psp.Data); Memory.AllocateVariable("Int21h-PSP", sizeof(ushort)); Memory.SetWord("Int21h-PSP", 0x4000); //Find _INIT_ values if any foreach (var dll in ModuleDlls) { //If it's a Test, setup a fake _INIT_ if (string.IsNullOrEmpty(ModuleIdentifier)) { dll.EntryPoints["_INIT_"] = null; return; } //Setup _INIT_ Entrypoint FarPtr initEntryPointPointer; var initResidentName = dll.File.ResidentNameTable.FirstOrDefault(x => x.Name.StartsWith("_INIT__")); if (initResidentName == null) { //This only happens with MajorMUD -- I have no idea why it's a special little snowflake ¯\_(ツ)_/¯ _logger.Warn($"({moduleConfig.ModuleIdentifier}) Unable to locate _INIT_ in Resident Name Table, checking Non-Resident Name Table..."); var initNonResidentName = dll.File.NonResidentNameTable.FirstOrDefault(x => x.Name.StartsWith("_INIT__")); if (initNonResidentName == null) { _logger.Error($"Unable to locate _INIT__ entry in Resident Name Table for {dll.File.FileName}"); continue; } var initEntryPoint = dll.File.EntryTable.First(x => x.Ordinal == initNonResidentName.IndexIntoEntryTable); initEntryPointPointer = new FarPtr((ushort)(initEntryPoint.SegmentNumber + dll.SegmentOffset), initEntryPoint.Offset); } else { var initEntryPoint = dll.File.EntryTable.First(x => x.Ordinal == initResidentName.IndexIntoEntryTable); initEntryPointPointer = new FarPtr((ushort)(initEntryPoint.SegmentNumber + dll.SegmentOffset), initEntryPoint.Offset); } _logger.Debug($"({ModuleIdentifier}) Located _INIT__: {initEntryPointPointer}"); dll.EntryPoints["_INIT_"] = initEntryPointPointer; } }