Cinux · kprintf 重构与引导期 SSE:在大步前进前夯实两个地基
Cinux · kprintf 重构与引导期 SSE:在大步前进前夯实两个地基如果您是想尝试 Cinux并对一些驱动、前沿细节的实现感兴趣的朋友请移步到下面的仓库https://github.com/Awesome-Embedded-Learning-Studio/Cinux如果您对手写一个现代 C 操作系统感兴趣的朋友请到这里https://github.com/Awesome-Embedded-Learning-Studio/Cinux-Book或者直接访问文档站开始阅读https://awesome-embedded-learning-studio.github.io/Cinux-Book/如果上面的内容对您的学习和实际的开发哪怕有一丝帮助都是笔者极大的荣幸喜欢的话麻烦小小的赏一个 ⭐QAQ。自己的知识仍不精湛文章必然还有很多错误还请各位大佬批评斧正得先跟你交个底:这一章的 tag 在仓库里叫012_driver_serial,名字带个 serial,但它的真实改动里一行串口驱动的新代码都没有。serial 的底层输出(IO 到 COM1)早在更早就就位了,kprintf 一直靠它吐字。这一章真正干的两件事,是把 kprintf 这个「内核唯一的诊断通道」从里到外重做了一遍,顺手修掉了一个只在-O2下才会让内核连 IDT 都加载不出来的崩溃。它是个插曲——在大步前进之前,先把两个地基夯实。这一章我们要点亮什么两件看得见的事。第一件,kprintf 终于像个 printf 了。之前那篇的 kprintf 其实已经能%d/%u/%x/%X/%p,也有%Nd/%0Nd的宽度与零补;这一章真正补的是左对齐(%-)、把负数零补的坑修对(-00042而不是000-42),并顺手把引擎抽成 header-only 模板让它能在 host 上单测。于是你能写出kprintf(%-8x, 0xdead)这种带对齐的诊断输出,而不必自己手拼字符串。第二件,稍微惊悚一点:-O2(Release)构建的内核,以前根本起不来。它在加载 IDT 的当口安静地 Triple Fault,QEMU 直接退出,连一句遗言都不留。这一章把它修了,从那以后无论 Debug 还是 Release,内核都能稳稳跑到 idle loop。为什么现在需要它先说为什么是现在。前一篇之后内核已经能响应时钟中断,接下来那篇就要往屏幕上画字、动 framebuffer,用户态、文件系统也在不远处。可一旦系统复杂起来,调试就全压在 kprintf 一根线上——它就是我们的眼睛。这时候如果 kprintf 连个对齐都打不好、连个指针都格式化不利索,后面每一处排查都会被它拖累。所以在往系统里堆新东西之前,先花一章把 kprintf 做扎实,是一笔稳赚的投资。重构的过程中,一个潜伏的 bug 被顺带逼了出来。我们想把 kprintf 的格式化引擎抽出来做单元测试,测试要在 host 上用-O2编译(因为那才是发布内核会跑的优化级别)。结果一编——内核在idt_init里 Triple Fault 了。这不是 kprintf 的锅,但它像一面镜子,照出了一个从更早那篇起就一直藏在那儿、只是之前没被-O2照到的硬件初始化缺陷:引导期从没初始化 SSE。这就是这一章为什么是「两个地基」:一个是软件地基(kprintf),一个是硬件地基(SSE),它俩凑在一个 tag 里,因为正是在给 kprintf 做-O2单测的时候,后者才暴露。设计图kprintf 重构后的形状,核心是「格式化引擎」和「输出后端」彻底分家,中间靠一个回调连起来:┌─────────────────────────────────────┐ │ vkprintf_implOutputFn(out,fmt,va) │ ← 硬件无关,header-only 模板 │ 纯逻辑:解析 % 宽度 对齐,格式化数字 │ kernel/lib/private/vkprintf_impl.hpp └───────────────┬─────────────────────┘ │ 每产出一个字符 → out(c) ▼ ┌─────────────────────────────────────┐ │ 回调 lambda │ │ [](char c){ g_serial.putc(c); } │ ← big kernel:喂给串口 └───────────────┬─────────────────────┘ ▼ ┌─────────────────────────────────────┐ │ 输出后端 │ │ big kernel: Serial(COM1) │ host 单测: std::string │ (后面那篇之后还会多一路: framebuffer) │ └─────────────────────────────────────┘同一个引擎,big kernel 喂给串口,host 单测喂给一个std::string。后面那篇之后还会多一路屏幕——到那时你就明白这层回调当初为什么要抽出来了。SSE 那条线是另一回事,它埋在 boot 流程最开头:mini kernel boot.S _start │ cli │ ★ 设 CR4.OSFXSR(bit9) CR4.OSXMMEXCPT(bit10) clts ← 本章新增 │ ... 进入长模式、加载 big kernel ... ▼ big kernel main: kprintf_init → GDT → IDT(idt_init 内部清零,可能被 -O2 向量化为 SSE)关键在于这个 ★ 出现在内核最早的可执行指令处。它的意义下面讲 SSE 那节展开。代码路线kprintf:把格式化引擎抽出来,用回调解耦输出后端重构前,kprintf.cpp 是一坨:格式解析、数字转换、串口输出,全挤在一个函数里。这有两个坏处——格式逻辑没法脱离串口硬件做测试,而且将来想往屏幕也输出一份,就得把整坨抄一遍。重构把它们拆开了。引擎变成一个 header-only 的模板,藏在kernel/lib/private/vkprintf_impl.hpp:templatetypenameOutputFnvoidvkprintf_impl(OutputFnputc_fn,constchar*fmt,va_list args){// 纯逻辑:遍历 fmt,遇 % 解析标志/宽度/类型,产出的每个字符都交给 putc_fn...}它只认一个putc_fn回调,至于这个字符最终去串口还是去屏幕、去测试缓冲区,引擎一概不管。而 kprintf.cpp 瘦成了一层薄包装,就剩三个委托:staticSerialg_serial(SERIAL_COM1);// big kernel 的单例串口voidkprintf(constchar*fmt,...){va_list args;va_start(args,fmt);vkprintf_impl([](charc){g_serial.putc(c);},fmt,args);// 回调喂串口va_end(args);}kvprintf、kpanic同理,都是「vkprintf_impl 一个喂串口的 lambda」。你以后想加一份屏幕输出,不用碰引擎,只要再调一次vkprintf_impl、换一个喂 framebuffer 的 lambda 就行。这就是回调解耦的红利。格式能力清单:这次补全了哪些 specifier引擎支持的格式,正好够一个内核诊断用,也明确地不假装支持那些它没有的:%% 字面量百分号 %c 字符 %s 字符串(nullptr 会安全地打成 (null),不会崩) %d %u 有符号 / 无符号十进制 %x %X 小写 / 大写十六进制(不带 0x 前缀) %p 指针,固定 16 位大写十六进制 0x 前缀 宽度修饰 %Nd 右对齐空格补 | %0Nd 零补 | %-Nd 左对齐 | %-Ns 字符串左对齐%p强制 16 位是因为在 64 位下,指针就该长那样,0x000000000000dead一眼能对上位,比省略前导零更不容易看错。而%f浮点、%lld长度修饰、%.3f精度这些,引擎统统没有——内核里几乎用不到浮点,硬塞进去只会徒增体积和 bug 面。把边界划清楚,比假装无所不能有用得多。零补与左对齐:负数那个小坑宽度处理里有个容易写错的细节,值得拎出来讲。%-10d左对齐、%08x零补,这些直觉上没问题。坑在负数零补:%06d格式化-42,你要的结果是-00042,而不是000-42。也就是说,符号得待在最前面,后面才是零,再后面才是数字。引擎里专门为此分了一个支:boolhas_sign(len0buffer[0]-);if(!left_alignzero_padhas_sign){// 先吐符号,再零补到宽度,最后吐数字putc_fn(-);for(intidigits_len;iwidth-1;i)putc_fn(0);putc_fn(/* 数字部分 */);}这种小地方不专门处理,出来的字符串就是错的,而它还不会报错——你只会在日志里看到一个诡异的000-42,然后花半小时怀疑别处。把它写对、再用单测焊死,就省了这半小时。顺带一提,数字转换里还有个INT64_MIN的特判:0x8000000000000000取反会溢出,不能直接-value,得单独走一条路径。这是写 itoa 类函数的老朋友了,但漏掉的话,打印最小负数就会得到一个正数。为什么 host 单测能直接测内核格式化引擎这大概是这次重构最值钱的一笔。因为引擎是 header-only 模板、且只依赖一个回调,host 侧的单测只要 include 它、喂一个往std::string里追加的回调,就能直接测内核的格式化逻辑——完全不用模拟串口硬件:std::stringdo_printf(constchar*fmt,...){std::string out;va_list args;va_start(args,fmt);cinux::lib::detail::vkprintf_impl([](charc){out.push_back(c);},fmt,args);va_end(args);returnout;}TEST(kprintf: %08x zero-pad hex){ASSERT_EQ(do_printf(%08x,0xFFu),000000ff);}test_kprintf.cpp就这么写了四十来个用例,把每一个 specifier、每一种宽度对齐、nullptr字符串、负数零补、混合格式、甚至未知 specifier 的兜底,全测了一遍。以前要验证 kprintf 对不对,只能把内核跑起来盯着串口看;现在它和普通库函数一样可以ctest一键验证。更妙的是,这批测试正是用-O2编的——而 SSE 的崩溃,就是在这一刻被照出来的。SSE:一个只在 -O2 才炸的 Triple Fault故事来了。给 kprintf 写 host 单测时,顺带把整个内核测试也用 Release(-O2)编了一遍,结果小内核在 IDT 初始化阶段 Triple Fault,QEMU 直接退出。诡异的是-O0(Debug)下一切正常,而且之前 GDT、kprintf、C 运行时的测试全过。定位它靠的是两个老办法。第一个是debugcon 标记法:在idt_init的各个步骤之间,插一句outb $0xE9, 某字符,把执行进度打到 QEMU 的 debug 日志。结果日志停在idt_init的清零循环那一步,之后再无标记——崩溃点被精确钉死在「第一个会用上 SSE 指令的地方」。第二个是反汇编对比。-O2把那个把 IDT 结构体数组清零的循环,向量化成了一串 SSE 指令:; -O2 生成的 idt_init 清零循环 pxor %xmm0, %xmm0 ; ← 第一条 SSE 指令,崩在这 movaps %xmm0, (%rcx,%rdx,1) ; 16 字节对齐写入而-O0生成的是逐字节的普通 store,根本不碰 SSE。这就解释了为什么只有-O2崩。根因是控制寄存器。在崩溃前把 CR0、CR4 读出来打到 debugcon,看到CR4 0x...20——只有 PAE 位被置上,而 OSFXSR(bit 9)是 0。按 Intel SDM 的规定,SSE2 这类 128 位指令在CR4.OSFXSR 0时会触发#UD(非法操作码,向量 6)。于是链条就清楚了:boot 入口 → cli →(从未设 CR4.OSFXSR)→ ... → idt_init ↓ pxor %xmm0 ↓ CR4.OSFXSR 0 → #UD (vector 6) ↓ 可此刻 IDT 还没 lidt(limit 0),连 #UD 自己都找不到 handler ↓ Triple Fault → QEMU -no-reboot → exit(0)这里有个容易误解的地方:64 位长模式硬件上确实支持 SSE,这是架构强制要求的。但「硬件支持」不等于「OS 已启用」——CPU 仍然要检查CR4.OSFXSR,这位不设,128 位 SSE 指令就一律当非法指令处理。两者不冲突,只是很多人(包括我们之前的 boot 代码)默认以为进了长模式 SSE 就自动能用了,这是个常见误区。另一个细节:为什么是 Triple Fault 而不是看到一个#UD的异常输出?因为pxor崩在idt_init内部——IDT 正在被清零、还没lidt加载,此时 IDT 的 limit 还是 0。#UD 找不到 handler,又没法进一步处理,直接一路升级成 Triple Fault。这也解释了它为什么崩得那么「安静」:连异常处理都还没就绪,自然吐不出任何东西。修复:在内核最早的入口把 CR4 拨好修法很直接,但位置讲究。在kernel/mini/arch/x86_64/boot.S的_start,紧跟在cli之后,把 SSE 相关的控制位一次性设好:_start: cli /* Enable SSE: set CR4.OSFXSR (bit 9) and CR4.OSXMMEXCPT (bit 10) */ movq %cr4, %rax orq $(1 9), %rax /* OSFXSR: enable FXSAVE/FXRSTOR 管理 SSE 状态 */ orq $(1 10), %rax /* OSXMMEXCPT: 允许 SIMD 浮点异常传递为 #XF */ movq %rax, %cr4 clts /* 清 CR0.TS,不依赖 BIOS/KVM 的初始值 */为什么放在 mini kernel 的boot.S而不是 big kernel 的main?因为boot.S是整个内核链上最早的可执行点。-O2可能在任何函数里生成 SSE 指令,越早把这位置好,后面所有代码——包括 mini kernel 自己、包括它加载的 big kernel——就都安全了。clts顺手清掉CR0.TS也是同样的道理:不依赖 QEMU/BIOS 给 CR0 的初始值,把状态握在自己手里。(完整版的排查过程——debugcon 标记法的具体输出、CR0/CR4 的读出值、-O0vs-O2的指令对比表——我们另起一篇 debug-notes 收着,这里只走主线。)调试现场这一章真正的「调试现场」就是上面那段 SSE 排查,它已经融在代码路线里讲了。这里只补两条这次沉淀下来的、以后会反复用到的经验。一是debugcon(port 0xE9)标记法值得当成看家手艺。内核崩得没声音的时候,在关键路径上插outb 0xE9打标记,再读debug.log,是定位「崩在哪一步」最快的办法——比插 kprintf 强,因为 kprintf 本身可能还没初始化(这次就崩在 IDT 之前,串口虽然有,但更早的崩溃根本走不到 kprintf)。二是「-O0正常、-O2崩」这种信号,要先怀疑某个硬件特性没被初始化。优化级别一变,代码就崩,根因往往是编译器在-O2下用上了某种-O0不用的指令(SSE/AVX、向量化内存操作、特定的寻址方式),而这些指令依赖某个没设好的控制位或状态。下次再撞上「换个优化级别就崩」,先往这个方向想,别急着怀疑自己的逻辑。验证kprintf 的格式化逻辑,直接跑那批 host 单测,不依赖 QEMU:ctest --test-dir build-Rkprintf --output-on-failure四十来个用例覆盖了所有 specifier、宽度对齐、nullptr、负数零补、混合格式和未知 specifier 兜底。它们绿的,格式化引擎就是对的。SSE 的修复,验证方式反过来——得用-O2把内核编出来跑,确认它不再 Triple Fault:cmake-Bbuild-release-DCMAKE_BUILD_TYPERelease其余参数cmake--buildbuild-release--targetrun-kernel-test修复前这会在idt_init阶段QEMU unexpected exit code: 0;修复后能稳稳跑完全部 22 项内核测试并exit 0(经 isa-debug-exit 的正常退出)。顺带,run起来后你会先看到一段 kprintf 的格式回归输出——那是 main 里新加的那 19 行,把%08x、%-10s、%p这些实打实打了一遍:[KPRINTF] %08x: 0000dead [KPRINTF] %-10d: 42 | [KPRINTF] %p: 0x00001234ABCD5678 [KPRINTF] mix: test n99 hexcafebabe ptr0x0000000000000001下一站地基夯实了,该往上盖了。到现在为止,内核所有的输出还只走串口一条路——你得开着 QEMU 的串口窗口才看得见它在说什么。下一篇终于要把 framebuffer 接上,让内核能直接在屏幕上画字: framebuffer 驱动、字体、console。到那时,这一章给 kprintf 抽出来的那个回调式引擎,会迎来它的第二个输出后端——屏幕。我们早就为这一天留好了接口。顺带,下一篇还会把 drivers 目录理一理(serial、pit 各自挪进自己的子目录),那个一直被 tag 名挂着、却没在这一章出现的「serial driver 化」,到那时才算真正落地。参考Intel SDM Vol.3(System Programming,控制寄存器):CR4.OSFXSR(bit 9)、CR4.OSXMMEXCPT(bit 10)、CR0.TS/EM/MP。本地 PDFdocument/reference/intel/SDM-Vol3A-*.pdf,可用pdf-reader搜索 “OSFXSR”/“OSXMMEXCPT” 复核位号。Intel SDM Vol.2(指令参考):SSE2 指令(PXOR/MOVAPS)在CR4.OSFXSR 0时触发#UD的规则;CLTS、FXSAVE/FXRSTOR语义。OSDev — QEMU exit devices / isa-debug-exit:退出码(value1)|1恒为奇数,退出码 0 在-no-reboot下表示 Triple Fault。本 tag 源码:vkprintf_impl.hpp、kprintf.cpp、kprintf.hpp、boot.S、main.cpp;测试 test_kprintf.cpp;排查笔记 012-01-sse-init-crash-o2.md。

相关新闻

粉笔直播课适合申论冲刺高分吗?对比传统录播课

粉笔直播课适合申论冲刺高分吗?对比传统录播课

引言:申论冲刺阶段的真正难点 申论作为公务员考试中区分度最高的科目,长期被考生视为"会写不难,写好极难"的科目。进入冲刺阶段后,多数考生已经完成基础理论学习,但分数往往卡在 55—65 分区间难以突破。根…

2026/8/11 11:31:29 阅读更多 →
从宠物管理系统实战解析自动化与性能测试:Playwright、Pytest、JMeter应用

从宠物管理系统实战解析自动化与性能测试:Playwright、Pytest、JMeter应用

1. 项目概述:一份“宠物管理系统”的测试报告能告诉我们什么? 最近刚带着团队做完一个“宠物管理系统”的测试项目,从功能、接口到性能,跑了个遍,最后产出了一份完整的测试报告。这活儿干完,我最大的感触是…

2026/8/8 6:24:04 阅读更多 →
基于强化学习的动态权重LSTM-GRU光伏功率预测方法

基于强化学习的动态权重LSTM-GRU光伏功率预测方法

1. 项目背景与核心价值光伏功率预测在新能源并网调度中扮演着关键角色。传统时间序列预测方法往往采用静态模型结构,难以适应光伏发电受天气、季节等因素影响产生的非线性波动特性。我们提出的动态权重组合方法,通过强化学习机制实时调整LSTM与GRU两种神…

2026/8/11 0:23:39 阅读更多 →

最新新闻

终极指南:如何用PKHeX自动合法性插件高效解决宝可梦数据合规难题

终极指南:如何用PKHeX自动合法性插件高效解决宝可梦数据合规难题

终极指南:如何用PKHeX自动合法性插件高效解决宝可梦数据合规难题 【免费下载链接】PKHeX-Plugins Plugins for PKHeX 项目地址: https://gitcode.com/gh_mirrors/pk/PKHeX-Plugins 宝可梦玩家经常面临数据合规性挑战,PKHeX自动合法性插件&#xf…

2026/8/11 11:54:24 阅读更多 →
基于V8隔离的代理优先浏览器Kitesurf:架构、原理与实战指南

基于V8隔离的代理优先浏览器Kitesurf:架构、原理与实战指南

最近在探索浏览器架构与云原生应用开发时,发现了一个非常有意思的开源项目——Kitesurf。它并非我们日常使用的Chrome或Edge,而是一个运行在V8隔离环境中的“代理优先”浏览器。这个概念听起来有些抽象,但如果你对Cloudflare Workers、无服务…

2026/8/11 11:54:24 阅读更多 →
DRG存档编辑器终极指南:3分钟掌握深岩银河游戏全内容解锁技巧

DRG存档编辑器终极指南:3分钟掌握深岩银河游戏全内容解锁技巧

DRG存档编辑器终极指南:3分钟掌握深岩银河游戏全内容解锁技巧 【免费下载链接】DRG-Save-Editor Rock and stone! 项目地址: https://gitcode.com/gh_mirrors/dr/DRG-Save-Editor 还在为《深岩银河》的资源短缺而烦恼?想要快速体验所有职业和装备…

2026/8/11 11:54:24 阅读更多 →
网盘下载新体验:LinkSwift直链助手让文件传输飞起来

网盘下载新体验:LinkSwift直链助手让文件传输飞起来

网盘下载新体验:LinkSwift直链助手让文件传输飞起来 【免费下载链接】Online-disk-direct-link-download-assistant 一个基于 JavaScript 的网盘文件下载地址获取工具。基于【网盘直链下载助手】修改 ,支持 百度网盘 / 阿里云盘 / 中国移动云盘 / 天翼云…

2026/8/11 11:54:23 阅读更多 →
高校一卡通餐厅系统Python架构设计与高并发优化

高校一卡通餐厅系统Python架构设计与高并发优化

1. 项目概述:高校一卡通餐厅系统的技术选型与价值 高校学生一卡通系统是校园信息化建设的核心基础设施,而餐厅消费模块作为使用频率最高的场景之一,其稳定性与扩展性直接影响数万师生的日常体验。传统基于PHP或Java EE的一卡通系统往往面临架…

2026/8/11 11:54:23 阅读更多 →
网络钓鱼已进化:你的“官方”体验可能全是假的

网络钓鱼已进化:你的“官方”体验可能全是假的

你是否接到过这样的电话?对方能准确报出你的姓名、贷款金额甚至逾期天数,语气严厉地要求你立即还款,并附上一个看似正规的协商还款链接。或者,你在某知名媒体公众号上看到一篇标题为“即将抵达!请市民做好准备&#xf…

2026/8/11 11:53:23 阅读更多 →

日新闻

如何用Video2X实现专业级视频画质提升:AI视频增强完整指南

如何用Video2X实现专业级视频画质提升:AI视频增强完整指南

如何用Video2X实现专业级视频画质提升:AI视频增强完整指南 【免费下载链接】video2x A machine learning-based video super resolution and frame interpolation framework. Est. Hack the Valley II, 2018. 项目地址: https://gitcode.com/GitHub_Trending/vi/v…

2026/8/11 0:00:02 阅读更多 →
前后端分离项目中控制台与接口工具数据差异排查指南

前后端分离项目中控制台与接口工具数据差异排查指南

1. 问题现象解析:控制台与Apifox的数据差异 最近在调试一个前后端分离项目时,遇到了一个典型问题:后端服务在本地开发环境控制台能正常输出查询数据,但通过Apifox测试时却返回空结果。这种"控制台有数据,接口工具…

2026/8/11 0:00:03 阅读更多 →
AI编程实战:从Claude Code踩坑到游戏开发入门

AI编程实战:从Claude Code踩坑到游戏开发入门

1. 从“AI能帮我做游戏”到“AI让我重新学编程”最近身边不少朋友,尤其是一些非技术背景、但对游戏开发有浓厚兴趣的朋友,都在问我同一个问题:“听说现在用Claude Code这种AI编程工具,小白也能做游戏了,是真的吗&#…

2026/8/11 0:00:03 阅读更多 →

周新闻

5分钟告别提取码焦虑:baidupankey如何智能破解百度网盘资源锁

5分钟告别提取码焦虑:baidupankey如何智能破解百度网盘资源锁

5分钟告别提取码焦虑:baidupankey如何智能破解百度网盘资源锁 【免费下载链接】baidupankey 在线查询网盘提取码(维护中 rm repo) 项目地址: https://gitcode.com/gh_mirrors/ba/baidupankey 你是否曾经在深夜寻找一份重要资料&#x…

2026/8/11 1:08:05 阅读更多 →
如何快速生成中国车牌图片:Python开源工具完整指南

如何快速生成中国车牌图片:Python开源工具完整指南

如何快速生成中国车牌图片:Python开源工具完整指南 【免费下载链接】chinese_license_plate_generator 中国车牌生成器 项目地址: https://gitcode.com/gh_mirrors/ch/chinese_license_plate_generator 中国车牌生成器是一个基于Python的开源项目&#xff0c…

2026/8/11 1:08:05 阅读更多 →
收藏!小白程序员轻松入门大模型,从Harness工程开始实践

收藏!小白程序员轻松入门大模型,从Harness工程开始实践

文章强调学习大模型不应只关注模型本身,而应重视模型外的系统搭建,即Harness。提出AgentModelHarness的实用公式,详细介绍Harness的四个层次:持久化层、执行层、控制层和观察与验证层。文章还探讨了上下文工程、工具设计、AGENTS.…

2026/8/11 1:08:05 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/10 17:07:33 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/11 1:08:06 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/10 17:07:33 阅读更多 →