实现用户态程序

This commit is contained in:
2026-03-27 21:32:18 +08:00
parent 7a7d44e9d8
commit 0988f4c820
13 changed files with 293 additions and 5 deletions

View File

@@ -1 +1 @@
2026-03-26 21:30:36 2026-03-27 21:26:04

View File

@@ -65,6 +65,7 @@
<ItemGroup> <ItemGroup>
<None Remove="font.psf" /> <None Remove="font.psf" />
<None Remove="sh.exe" />
<None Remove="Solarize.12x29.psf" /> <None Remove="Solarize.12x29.psf" />
</ItemGroup> </ItemGroup>
@@ -134,6 +135,7 @@
<EmbeddedResource Include="Gui\Resources\Wallpaper_1280_800.bmp" /> <EmbeddedResource Include="Gui\Resources\Wallpaper_1280_800.bmp" />
<EmbeddedResource Include="GitCommit.txt" /> <EmbeddedResource Include="GitCommit.txt" />
<EmbeddedResource Include="BuildTime.txt" /> <EmbeddedResource Include="BuildTime.txt" />
<EmbeddedResource Include="sh.exe" />
<EmbeddedResource Include="LuaApps\*.lua" /> <EmbeddedResource Include="LuaApps\*.lua" />
</ItemGroup> </ItemGroup>
@@ -153,6 +155,7 @@
<PackageReference Include="CosmosFtpServer" Version="1.0.9" /> <PackageReference Include="CosmosFtpServer" Version="1.0.9" />
<PackageReference Include="CosmosHttp" Version="1.0.4" /> <PackageReference Include="CosmosHttp" Version="1.0.4" />
<PackageReference Include="IL2CPU.API" Version="0.1.0-localbuild20260225062300" /> <PackageReference Include="IL2CPU.API" Version="0.1.0-localbuild20260225062300" />
<PackageReference Include="ManagedSoftwareExecution" Version="1.2.2" />
</ItemGroup> </ItemGroup>
<Target Name="PreBuild" BeforeTargets="PreBuildEvent"> <Target Name="PreBuild" BeforeTargets="PreBuildEvent">

View File

@@ -1 +1 @@
cd6fee6 7a7d44e

View File

@@ -29,6 +29,7 @@ using Cosmos.System.Graphics.Fonts;
using Cosmos.System.Network.Config; using Cosmos.System.Network.Config;
using Cosmos.System.Network.IPv4; using Cosmos.System.Network.IPv4;
using Cosmos.System.Network.IPv4.UDP.DHCP; using Cosmos.System.Network.IPv4.UDP.DHCP;
using Cosmos.System.Emulation;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
@@ -144,6 +145,11 @@ namespace CMLeonOS
UserSystem.Initialize(); UserSystem.Initialize();
userSystem = new UserSystem(); userSystem = new UserSystem();
_logger.Success("Kernel", "User system initialized"); _logger.Success("Kernel", "User system initialized");
// 初始化指令集
_logger.Info("Kernel", "Initializing instruction set");
FGMSECInstructionSet.Install();
_logger.Success("Kernel", "Instruction set initialized");
// 读取 Git Commit hash // 读取 Git Commit hash
if (gitCommitFile != null && gitCommitFile.Length > 0) if (gitCommitFile != null && gitCommitFile.Length > 0)
@@ -310,7 +316,7 @@ namespace CMLeonOS
} }
else{ else{
Console.Clear(); Console.Clear();
Console.BackgroundColor = ConsoleColor.Red; Console.BackgroundColor = ConsoleColor.Blue;
Console.ForegroundColor = ConsoleColor.White; Console.ForegroundColor = ConsoleColor.White;
Console.Clear(); Console.Clear();
Console.Beep(); Console.Beep();

View File

@@ -10,7 +10,7 @@ export default defineUserConfig({
theme: defaultTheme({ theme: defaultTheme({
// logo: 'https://vuejs.press/images/hero.png', // logo: 'https://vuejs.press/images/hero.png',
navbar: ['/', '/get-started', '/lua', '/commands'], navbar: ['/', '/get-started', '/lua', '/commands', '/syscall'],
}), }),

View File

@@ -764,6 +764,24 @@ branswe <file>
branswe script.brs branswe script.brs
``` ```
### runbin
运行 MSE 二进制程序文件(由 ManagedSoftwareExecution 执行)。
**用法:**
```bash
runbin <file>
```
**示例:**
```bash
runbin 0:\apps\demo.bin
```
**说明:**
- `runbin` 会读取指定二进制文件并按指令逐条执行
- 当前内置 3 个系统调用syscall 0/1/2
- 详细 syscall 规范见 [Syscall 文档](/syscall.html)
## 实用工具命令 ## 实用工具命令
### calc ### calc
@@ -856,6 +874,26 @@ exportbackground 0:\mywallpaper.bmp
- 如果不指定输出路径,默认导出到 0:\background.bmp - 如果不指定输出路径,默认导出到 0:\background.bmp
- 导出的壁纸为BMP格式 - 导出的壁纸为BMP格式
### exporttestexe
导出测试可执行文件到指定路径。
**用法:**
```bash
exporttestexe [output_path]
```
**示例:**
```bash
exporttestexe
exporttestexe 0:\test.exe
```
**说明:**
- 如果不指定输出路径,默认导出到 0:\test.exe
- 导出的可执行文件为MSE格式
### beep ### beep
播放系统提示音。 播放系统提示音。

View File

@@ -0,0 +1,58 @@
# MSE Syscall 文档
本文档说明 `runbin` 命令当前支持的系统调用syscall约定。
## 前置条件
- 指令集初始化已在内核完成(`FGMSECInstructionSet.Install()`
- 使用 `runbin <file>` 运行二进制程序
## 调用约定
- 当前可用 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 <file>`
3. 程序通过 syscall 与控制台交互(输出、输入、清屏)
## 注意事项
- 如果程序调用了未实现的 syscall会导致运行失败
- 输入输出行为与控制台一致,建议程序自行处理提示文本与换行

BIN
sh.exe Normal file

Binary file not shown.

View File

@@ -239,6 +239,9 @@ namespace CMLeonOS.shell
case "markit": case "markit":
shell.ProcessMarkit(args); shell.ProcessMarkit(args);
break; break;
case "runbin":
shell.ProcessRunbin(args);
break;
case "femboy": case "femboy":
shell.ProcessFemboy(); shell.ProcessFemboy();
break; break;
@@ -257,6 +260,9 @@ namespace CMLeonOS.shell
case "exportbackground": case "exportbackground":
shell.ProcessExportBackground(args); shell.ProcessExportBackground(args);
break; break;
case "exporttestexe":
shell.ProcessExportTestExe(args);
break;
default: default:
shell.ShowError($"Unknown command: {command}"); shell.ShowError($"Unknown command: {command}");
break; break;

View File

@@ -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 <https://www.gnu.org/licenses/>.
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}");
}
}
}
}

View File

@@ -86,6 +86,18 @@ namespace CMLeonOS.Commands
Description = "Simple calculator" Description = "Simple calculator"
}, },
new CommandInfo new CommandInfo
{
Command = "exporttestexe",
Parameters = "<output>",
Description = "Export test.exe to specified path"
},
new CommandInfo
{
Command = "exportbackground",
Parameters = "<output>",
Description = "Export background to specified path"
},
new CommandInfo
{ {
Command = "calcgui", Command = "calcgui",
Parameters = "", Parameters = "",

View File

@@ -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<string> showError)
{
string[] parts = args.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
if (parts.Length < 1)
{
var commandInfos = new List<UsageGenerator.CommandInfo>
{
new UsageGenerator.CommandInfo
{
Command = "<file>",
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();
});
}
}
}

View File

@@ -427,6 +427,7 @@ namespace CMLeonOS
"ping", "wget", "ftp", "tcpserver", "tcpclient", "lua", "lua2cla", "cla", "ping", "wget", "ftp", "tcpserver", "tcpclient", "lua", "lua2cla", "cla",
"branswe", "beep", "env", "whoami", "uptime", "alias", "branswe", "beep", "env", "whoami", "uptime", "alias",
"unalias", "base64", "testgui", "ps", "kill", "hex", "exportbackground", "logs" "unalias", "base64", "testgui", "ps", "kill", "hex", "exportbackground", "logs"
, "runbin"
}; };
} }
@@ -1108,6 +1109,11 @@ namespace CMLeonOS
Commands.MarkitCommand.Execute(args, this, fileSystem); Commands.MarkitCommand.Execute(args, this, fileSystem);
} }
public void ProcessRunbin(string args)
{
Commands.Script.RunbinCommand.Execute(args, fileSystem, ShowError);
}
public void CreateFTP() public void CreateFTP()
{ {
Console.WriteLine("===================================="); Console.WriteLine("====================================");
@@ -1842,5 +1848,10 @@ namespace CMLeonOS
ShowError($"DNS lookup error: {ex.Message}"); ShowError($"DNS lookup error: {ex.Message}");
} }
} }
public void ProcessExportTestExe(string args)
{
Commands.ExportTestExeCommand.ExportTestExe(args);
}
} }
} }