mirror of
https://github.com/Leonmmcoset/CMLeonOS.git
synced 2026-04-21 10:53:59 +00:00
实现用户态程序
This commit is contained in:
@@ -1 +1 @@
|
||||
2026-03-26 21:30:36
|
||||
2026-03-27 21:26:04
|
||||
@@ -65,6 +65,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="font.psf" />
|
||||
<None Remove="sh.exe" />
|
||||
<None Remove="Solarize.12x29.psf" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -134,6 +135,7 @@
|
||||
<EmbeddedResource Include="Gui\Resources\Wallpaper_1280_800.bmp" />
|
||||
<EmbeddedResource Include="GitCommit.txt" />
|
||||
<EmbeddedResource Include="BuildTime.txt" />
|
||||
<EmbeddedResource Include="sh.exe" />
|
||||
<EmbeddedResource Include="LuaApps\*.lua" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -153,6 +155,7 @@
|
||||
<PackageReference Include="CosmosFtpServer" Version="1.0.9" />
|
||||
<PackageReference Include="CosmosHttp" Version="1.0.4" />
|
||||
<PackageReference Include="IL2CPU.API" Version="0.1.0-localbuild20260225062300" />
|
||||
<PackageReference Include="ManagedSoftwareExecution" Version="1.2.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="PreBuild" BeforeTargets="PreBuildEvent">
|
||||
|
||||
@@ -1 +1 @@
|
||||
cd6fee6
|
||||
7a7d44e
|
||||
@@ -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;
|
||||
@@ -145,6 +146,11 @@ namespace CMLeonOS
|
||||
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();
|
||||
|
||||
@@ -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'],
|
||||
}),
|
||||
|
||||
|
||||
|
||||
@@ -764,6 +764,24 @@ branswe <file>
|
||||
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
|
||||
@@ -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
|
||||
播放系统提示音。
|
||||
|
||||
|
||||
58
docs/cmleonos/docs/syscall.md
Normal file
58
docs/cmleonos/docs/syscall.md
Normal 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,会导致运行失败
|
||||
- 输入输出行为与控制台一致,建议程序自行处理提示文本与换行
|
||||
@@ -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;
|
||||
|
||||
49
shell/Commands/ExportTestExeCommand.cs
Normal file
49
shell/Commands/ExportTestExeCommand.cs
Normal 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}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -86,6 +86,18 @@ namespace CMLeonOS.Commands
|
||||
Description = "Simple calculator"
|
||||
},
|
||||
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",
|
||||
Parameters = "",
|
||||
|
||||
105
shell/Commands/Script/RunbinCommand.cs
Normal file
105
shell/Commands/Script/RunbinCommand.cs
Normal 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();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user