From 0988f4c820729291f93e15587296266abfa5c7db Mon Sep 17 00:00:00 2001 From: Leonmmcoset Date: Fri, 27 Mar 2026 21:32:18 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E7=94=A8=E6=88=B7=E6=80=81?= =?UTF-8?q?=E7=A8=8B=E5=BA=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- BuildTime.txt | 2 +- CMLeonOS.csproj | 3 + GitCommit.txt | 2 +- Kernel.cs | 8 +- docs/cmleonos/docs/.vuepress/config.js | 2 +- docs/cmleonos/docs/commands.md | 38 +++++++++ docs/cmleonos/docs/syscall.md | 58 ++++++++++++++ sh.exe | Bin 0 -> 3435 bytes shell/CommandList.cs | 6 ++ shell/Commands/ExportTestExeCommand.cs | 49 ++++++++++++ shell/Commands/Help/Help.cs | 12 +++ shell/Commands/Script/RunbinCommand.cs | 105 +++++++++++++++++++++++++ shell/Shell.cs | 13 ++- 13 files changed, 293 insertions(+), 5 deletions(-) create mode 100644 docs/cmleonos/docs/syscall.md create mode 100644 sh.exe create mode 100644 shell/Commands/ExportTestExeCommand.cs create mode 100644 shell/Commands/Script/RunbinCommand.cs diff --git a/BuildTime.txt b/BuildTime.txt index 2263405..458997f 100644 --- a/BuildTime.txt +++ b/BuildTime.txt @@ -1 +1 @@ -2026-03-26 21:30:36 \ No newline at end of file +2026-03-27 21:26:04 \ No newline at end of file diff --git a/CMLeonOS.csproj b/CMLeonOS.csproj index b28be86..7ec7fcf 100644 --- a/CMLeonOS.csproj +++ b/CMLeonOS.csproj @@ -65,6 +65,7 @@ + @@ -134,6 +135,7 @@ + @@ -153,6 +155,7 @@ + diff --git a/GitCommit.txt b/GitCommit.txt index e639942..41717d4 100644 --- a/GitCommit.txt +++ b/GitCommit.txt @@ -1 +1 @@ -cd6fee6 \ No newline at end of file +7a7d44e \ No newline at end of file diff --git a/Kernel.cs b/Kernel.cs index c280808..c84bde9 100644 --- a/Kernel.cs +++ b/Kernel.cs @@ -29,6 +29,7 @@ using Cosmos.System.Graphics.Fonts; using Cosmos.System.Network.Config; using Cosmos.System.Network.IPv4; using Cosmos.System.Network.IPv4.UDP.DHCP; +using Cosmos.System.Emulation; using System; using System.Collections.Generic; using System.IO; @@ -144,6 +145,11 @@ namespace CMLeonOS UserSystem.Initialize(); userSystem = new UserSystem(); _logger.Success("Kernel", "User system initialized"); + + // 初始化指令集 + _logger.Info("Kernel", "Initializing instruction set"); + FGMSECInstructionSet.Install(); + _logger.Success("Kernel", "Instruction set initialized"); // 读取 Git Commit hash if (gitCommitFile != null && gitCommitFile.Length > 0) @@ -310,7 +316,7 @@ namespace CMLeonOS } else{ Console.Clear(); - Console.BackgroundColor = ConsoleColor.Red; + Console.BackgroundColor = ConsoleColor.Blue; Console.ForegroundColor = ConsoleColor.White; Console.Clear(); Console.Beep(); diff --git a/docs/cmleonos/docs/.vuepress/config.js b/docs/cmleonos/docs/.vuepress/config.js index 52800ad..27488b9 100644 --- a/docs/cmleonos/docs/.vuepress/config.js +++ b/docs/cmleonos/docs/.vuepress/config.js @@ -10,7 +10,7 @@ export default defineUserConfig({ theme: defaultTheme({ // logo: 'https://vuejs.press/images/hero.png', - navbar: ['/', '/get-started', '/lua', '/commands'], + navbar: ['/', '/get-started', '/lua', '/commands', '/syscall'], }), diff --git a/docs/cmleonos/docs/commands.md b/docs/cmleonos/docs/commands.md index 6a856b6..814027c 100644 --- a/docs/cmleonos/docs/commands.md +++ b/docs/cmleonos/docs/commands.md @@ -764,6 +764,24 @@ branswe branswe script.brs ``` +### runbin +运行 MSE 二进制程序文件(由 ManagedSoftwareExecution 执行)。 + +**用法:** +```bash +runbin +``` + +**示例:** +```bash +runbin 0:\apps\demo.bin +``` + +**说明:** +- `runbin` 会读取指定二进制文件并按指令逐条执行 +- 当前内置 3 个系统调用(syscall 0/1/2) +- 详细 syscall 规范见 [Syscall 文档](/syscall.html) + ## 实用工具命令 ### calc @@ -856,6 +874,26 @@ exportbackground 0:\mywallpaper.bmp - 如果不指定输出路径,默认导出到 0:\background.bmp - 导出的壁纸为BMP格式 + +### exporttestexe +导出测试可执行文件到指定路径。 + +**用法:** +```bash +exporttestexe [output_path] +``` + +**示例:** +```bash +exporttestexe +exporttestexe 0:\test.exe +``` + +**说明:** +- 如果不指定输出路径,默认导出到 0:\test.exe +- 导出的可执行文件为MSE格式 + + ### beep 播放系统提示音。 diff --git a/docs/cmleonos/docs/syscall.md b/docs/cmleonos/docs/syscall.md new file mode 100644 index 0000000..c71acd9 --- /dev/null +++ b/docs/cmleonos/docs/syscall.md @@ -0,0 +1,58 @@ +# MSE Syscall 文档 + +本文档说明 `runbin` 命令当前支持的系统调用(syscall)约定。 + +## 前置条件 + +- 指令集初始化已在内核完成(`FGMSECInstructionSet.Install()`) +- 使用 `runbin ` 运行二进制程序 + +## 调用约定 + +- 当前可用 syscall 数量:`3` +- 索引范围:`0`、`1`、`2` + +## syscall 0:输出字符串 + +**功能:** +将内存中的以 `\0` 结尾字符串输出到控制台。 + +**参数:** +- `R3`:字符串起始地址 + +**行为:** +- 从 `R3` 指向地址开始逐字符读取 +- 遇到 `\0` 终止输出 +- 不自动换行 + +## syscall 1:读取一行输入 + +**功能:** +从控制台读取一行文本,并写入可执行程序内存。 + +**行为:** +- 调用 `Console.ReadLine()` +- 自动在末尾追加 `\0` +- 将结果写入程序内存 + +**返回值:** +- `R3`:写入字符串的起始地址 + +## syscall 2:清屏 + +**功能:** +清空控制台屏幕。 + +**行为:** +- 调用 `Console.Clear()` + +## 最小流程示例 + +1. 准备符合 FGMSEC 指令集的二进制文件 +2. 在 Shell 执行 `runbin ` +3. 程序通过 syscall 与控制台交互(输出、输入、清屏) + +## 注意事项 + +- 如果程序调用了未实现的 syscall,会导致运行失败 +- 输入输出行为与控制台一致,建议程序自行处理提示文本与换行 diff --git a/sh.exe b/sh.exe new file mode 100644 index 0000000000000000000000000000000000000000..8eab569b1b210ac6eab1fccf91ec5c5b30f90462 GIT binary patch literal 3435 zcmb`Ixo%WJ6h!CQV0N3$fSu4t1SD*NgoFUe0RbcqkU&V79f^G>;uFaD0Ym^9AApdE zAm$s0$p?g~Gt)ILp6u};ai#L>u3L9`w|kz)$2$MPt}DmA3er6go(Q*u#{za!xF*~d z?h6?HyMp84t_Wxzv5`F!h$a7ma7Q2xBR4tGy3TU7&s80H$xklw5L*Od;aHy$=7qWX z%)W`=Ct#^7+7r{(o)m`g&1N$P-uWPYy=XfZN_gfIq z;^+OCwR7ORTzSq4U8zrU6JxFWpm$~fF!#WoGcCfXy=Q)UB{y{dz1ei2e@jpNwkXU5!dV%g(w{~plNGyWoQ zrf4uYe9i|q>@F1f>5q8l^EZw@@R5I?fN_@CVt29ov%l>99sAvxWxq|&Uv-Vvd?)x# z!A}RjIrxvkZwY=j_{reE20s=2-r%g(wh_O+uW9DBwpn|2 z1ufrg$9>V-`i;_e*YvX_=evUo-uoujNL! z{e~J~{iPv#YhI0@c{hUQ(-2L&uWuu0eU6{wz07?V=Qa1k`S&QV&ZapnF7IM{R@O__ zv+;ghhjaJ&k)QkEea6(;H7ni2?1=*ImGAmwzgENV)W45jjXsZjpy4~{-l*wbSPy!u zYwqM~_qg8OhI@>;uMb-LofaZr&J9h@AY;wDFM6TxuAW%(Yv4&-Z7>5k`H00lr`K8! zG&pL1&QZT5&3m~#tKK=HmHoxlx}F37gKX^@?LOW}n6-!_rl<2$oM&Mly*QVB+|w=} z7Fo`w*LUUlW;u?#Y`t^XKc*b!$d|dT;kBvL%c1AsJ12g*+~jdA?eH#+r6=;OR+GCp Jc%NZ4{{U%@G&TSL literal 0 HcmV?d00001 diff --git a/shell/CommandList.cs b/shell/CommandList.cs index 9c343e1..332f143 100644 --- a/shell/CommandList.cs +++ b/shell/CommandList.cs @@ -239,6 +239,9 @@ namespace CMLeonOS.shell case "markit": shell.ProcessMarkit(args); break; + case "runbin": + shell.ProcessRunbin(args); + break; case "femboy": shell.ProcessFemboy(); break; @@ -257,6 +260,9 @@ namespace CMLeonOS.shell case "exportbackground": shell.ProcessExportBackground(args); break; + case "exporttestexe": + shell.ProcessExportTestExe(args); + break; default: shell.ShowError($"Unknown command: {command}"); break; diff --git a/shell/Commands/ExportTestExeCommand.cs b/shell/Commands/ExportTestExeCommand.cs new file mode 100644 index 0000000..3d6058f --- /dev/null +++ b/shell/Commands/ExportTestExeCommand.cs @@ -0,0 +1,49 @@ +// The CMLeonOS Project (https://github.com/Leonmmcoset/CMLeonOS) +// Copyright (C) 2025-present LeonOS 2 Developer Team +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +using System; +using System.IO; +using IL2CPU.API.Attribs; + +namespace CMLeonOS.Commands +{ + public static class ExportTestExeCommand + { + [ManifestResourceStream(ResourceName = "CMLeonOS.sh.exe")] + private static byte[] testExeBytes; + + public static void ExportTestExe(string outputPath) + { + try + { + if (testExeBytes == null || testExeBytes.Length == 0) + { + Console.WriteLine("Error: No test.exe found in embedded resources."); + return; + } + + string destinationPath = string.IsNullOrEmpty(outputPath) ? @"0:\test.exe" : outputPath; + + File.WriteAllBytes(destinationPath, testExeBytes); + Console.WriteLine($"Test.exe exported successfully to: {destinationPath}"); + } + catch (Exception ex) + { + Console.WriteLine($"Error exporting test.exe: {ex.Message}"); + } + } + } +} \ No newline at end of file diff --git a/shell/Commands/Help/Help.cs b/shell/Commands/Help/Help.cs index 73615de..4151f53 100644 --- a/shell/Commands/Help/Help.cs +++ b/shell/Commands/Help/Help.cs @@ -86,6 +86,18 @@ namespace CMLeonOS.Commands Description = "Simple calculator" }, new CommandInfo + { + Command = "exporttestexe", + Parameters = "", + Description = "Export test.exe to specified path" + }, + new CommandInfo + { + Command = "exportbackground", + Parameters = "", + Description = "Export background to specified path" + }, + new CommandInfo { Command = "calcgui", Parameters = "", diff --git a/shell/Commands/Script/RunbinCommand.cs b/shell/Commands/Script/RunbinCommand.cs new file mode 100644 index 0000000..e4fde86 --- /dev/null +++ b/shell/Commands/Script/RunbinCommand.cs @@ -0,0 +1,105 @@ +using Cosmos.System.Emulation; +using System; +using System.Collections.Generic; +using System.IO; + +namespace CMLeonOS.Commands.Script +{ + public static class RunbinCommand + { + public static void Execute(string args, CMLeonOS.FileSystem fileSystem, Action showError) + { + string[] parts = args.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); + if (parts.Length < 1) + { + var commandInfos = new List + { + new UsageGenerator.CommandInfo + { + Command = "", + Description = "Run a MSE executable binary file", + IsOptional = false + } + }; + showError(UsageGenerator.GenerateUsage("runbin", commandInfos)); + return; + } + + string inputPath = parts[0]; + string fullPath = fileSystem.GetFullPath(inputPath); + + if (!File.Exists(fullPath)) + { + showError($"Error: File not found: {fullPath}"); + return; + } + + try + { + byte[] data = File.ReadAllBytes(fullPath); + if (data == null || data.Length == 0) + { + showError("Error: Executable file is empty."); + return; + } + + FGMSECInstructionSet set = new FGMSECInstructionSet(); + Executable exec = new Executable(data, set, 3); + + AddDefaultSystemCalls(exec); + exec.ReadData(); + + while (exec.running) + { + exec.NextInstruction(); + } + } + catch (Exception ex) + { + showError($"runbin error: {ex.Message}"); + } + } + + private static void AddDefaultSystemCalls(Executable exec) + { + // syscall 0: print null-terminated string at address in R3 + exec.AddSystemCall((Executable caller) => + { + int addr = (int)((FGMSECInstructionSet)caller.usingInstructionSet).CPU.GetRegData(3); + char c = (char)caller.Memory.ReadChar(addr); + while (c != 0) + { + Console.Write(c); + addr++; + c = (char)caller.Memory.ReadChar(addr); + } + }); + + // syscall 1: read line and return address in R3 + exec.AddSystemCall((Executable caller) => + { + string input = Console.ReadLine() ?? string.Empty; + input += '\0'; + int addr = caller.Memory.Data.Count; + int caddr = 0; + for (int i = 0; i < input.Length; i++) + { + char c = input[i]; + if (!caller.Memory.AddChar(c)) + { + caller.Memory.WriteChar(caddr, c); + addr = 0; + caddr++; + } + } + ((FGMSECInstructionSet)caller.usingInstructionSet).CPU.SetRegData(3, (uint)addr); + }); + + // syscall 2: clear console + exec.AddSystemCall((Executable caller) => + { + Console.Clear(); + }); + } + } +} diff --git a/shell/Shell.cs b/shell/Shell.cs index 9d5ec7c..c9e4f22 100644 --- a/shell/Shell.cs +++ b/shell/Shell.cs @@ -427,6 +427,7 @@ namespace CMLeonOS "ping", "wget", "ftp", "tcpserver", "tcpclient", "lua", "lua2cla", "cla", "branswe", "beep", "env", "whoami", "uptime", "alias", "unalias", "base64", "testgui", "ps", "kill", "hex", "exportbackground", "logs" + , "runbin" }; } @@ -1108,6 +1109,11 @@ namespace CMLeonOS Commands.MarkitCommand.Execute(args, this, fileSystem); } + public void ProcessRunbin(string args) + { + Commands.Script.RunbinCommand.Execute(args, fileSystem, ShowError); + } + public void CreateFTP() { Console.WriteLine("===================================="); @@ -1842,5 +1848,10 @@ namespace CMLeonOS ShowError($"DNS lookup error: {ex.Message}"); } } + + public void ProcessExportTestExe(string args) + { + Commands.ExportTestExeCommand.ExportTestExe(args); + } } -} \ No newline at end of file +}