<?xml version="1.0" encoding="UTF-8"?><?xml-stylesheet href="/scripts/pretty-feed-v3.xsl" type="text/xsl"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:h="http://www.w3.org/TR/html4/"><channel><title>YuZhinn&apos;s Blog</title><description>We only get today.</description><link>https://yingshznrgb.github.io</link><item><title>个人博客上手指南</title><link>https://yingshznrgb.github.io/blog/blog-teach/blog-teach</link><guid isPermaLink="true">https://yingshznrgb.github.io/blog/blog-teach/blog-teach</guid><description>什么是个人博客？如何搭建简单的个人博客？完备的博客应有的功能？</description><pubDate>Tue, 14 Apr 2026 00:00:00 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;这是一份专为初学者设计的建站全流程指南。你将学会如何从零开始，搭建一个高性能、可个性化、完全免费的个人博客。如果你已经是大佬，也欢迎批评指正。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;前言：为什么你需要一个自己的博客？&lt;/h3&gt;
&lt;p&gt;我们正处在一个信息过载的数字时代。你习惯在朋友圈分享日常，在小红书标记生活，在知乎发表见解，在简历上罗列技能。但这些平台，终究是别人的“出租屋”——你遵守着它们的格式、算法和规则，内容也可能随时消失或被淹没在喧嚣的信息流中。&lt;/p&gt;
&lt;p&gt;你有没有想过，拥有一个完全由你掌控的线上空间？一个像你的家一样，可以按照自己的审美布置、自由表达、安静沉淀的地方？&lt;/p&gt;
&lt;p&gt;很多人可能会觉得，搭建一个看起来很酷的个人网站，是件非常复杂和昂贵的事情：需要学习 HTML/CSS/JS 全家桶，还要懂后端、数据库和服务器运维。但事实是，借助现代化的工具，这一切比你想象的要简单得多，甚至可以完全免费。&lt;/p&gt;
&lt;p&gt;本教程将作为一个完整的指南，带你从零开始，一步步搭建并部署一个高性能、易于维护的个人博客。即使你只有基础的电脑操作能力，只要跟着步骤走，也能拥有一个属于自己的、独一无二的网络小天地。&lt;/p&gt;
&lt;h3&gt;什么样的人适合搭建个人博客？&lt;/h3&gt;
&lt;p&gt;在开始之前，不妨看看你是否符合下面这几类人。如果答案是肯定的，那么这个教程就是为你准备的。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;技术萌新，充满好奇：你听说过 GitHub，知道 Git 的基本概念（比如 add、commit、push），但对前端技术栈（HTML/CSS/JS）几乎一无所知。你渴望拥有一个自己的网站，但不知道从何入手。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;写作者，渴望沉淀：你希望在喧嚣的互联网中，找到一块属于自己的、安静的、可长期沉淀的文字自留地。你不受限于平台的格式和审查，想完全掌控自己文章的排版和呈现方式。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;学习者，以教为学：你正在学习编程或某个领域，希望通过写博客来整理思路、记录学习过程，并分享给他人。一个好的博客本身就是最好的学习证明。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;创作者，打造个人品牌：你是一位设计师、摄影师、开发者或自由职业者，需要一个专业的、可高度自定义的作品集或个人名片，来展示你的能力和风格，摆脱千篇一律的模板。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;:::note[一句话总结：]
只要你想拥有一个免费的、美观的、完全听命于你的个人网站，无论你是否有技术背景，这个教程都适合你。
:::&lt;/p&gt;
&lt;h3&gt;现代前端网页搭建的基本逻辑&lt;/h3&gt;
&lt;p&gt;在动手之前，先了解一些基本的概念，有利于后续的实践操作。&lt;/p&gt;
&lt;p&gt;:::tip[什么是静态网站？]
:::
静态网站，简单来说，就是由不会变化的固定文件组成的网站。&lt;/p&gt;
&lt;p&gt;这些文件主要是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;HTML（网页的结构和内容，比如文字、图片）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;CSS（网页的样式，比如颜色、字体、布局）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;JavaScript（网页的交互效果，比如点击按钮、动画）&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;当你在浏览器里输入一个网址，服务器就直接把这些现成的文件发送给你的浏览器，浏览器再渲染成你看到的网页。&lt;/p&gt;
&lt;p&gt;静态网页的优点：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;速度快：	没有后台计算和数据库查询，文件直接发送，加载极快&lt;/li&gt;
&lt;li&gt;安全性高：	没有后端程序、没有数据库，黑客无从下手（比如无法SQL注入）&lt;/li&gt;
&lt;li&gt;成本极低：	只需要一个存文件的地方，GitHub Pages、Vercel 等平台甚至提供免费托管&lt;/li&gt;
&lt;li&gt;部署简单：	把文件上传到服务器就能访问，不需要配置复杂的运行环境&lt;/li&gt;
&lt;li&gt;适合搜索引擎：	内容是固定HTML，搜索引擎抓取非常友好（SEO天然优势）&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;常见的诸如 Github Pages 或者 Vercel 等平台，都是支持部署静态网页的，因此我们只需要将网页的构建产物上传到这些平台，就可以实现网页的部署。&lt;/p&gt;
&lt;p&gt;:::tip[现代前端框架有哪些？]
:::&lt;/p&gt;
&lt;p&gt;现代前端框架（如 &lt;strong&gt;Astro&lt;/strong&gt;, &lt;strong&gt;Vue&lt;/strong&gt;, &lt;strong&gt;React&lt;/strong&gt;）允许开发者用更高效、更模块化的方式来组织代码（比如写 Markdown 文章，或者用组件拼装页面）。虽然你在开发时写的是 .vue、.jsx、.astro 等文件，但这些框架最终会通过构建工具（如 &lt;strong&gt;Vite&lt;/strong&gt;、&lt;strong&gt;Webpack&lt;/strong&gt;、&lt;strong&gt;Rollup&lt;/strong&gt; 等）将你的代码转换为浏览器可以识别的 HTML、CSS 和 JavaScript 文件。这个构建过程就像“翻译”一样，把开发者写的高层代码翻译成浏览器能“听懂”的语言。&lt;/p&gt;
&lt;p&gt;而更进一步，无数的开发者为了便利博客等网站的构建，在这些现代框架的基础上构建了模板。这意味着你无需从零开始，只需要找到一个你喜欢的模板，在作者预设好的框架里，像填写个人信息、写文章一样去填充内容即可。模板已经帮你处理了 99% 的复杂技术细节。&lt;/p&gt;
&lt;h3&gt;开始吧！&lt;/h3&gt;
&lt;p&gt;讲完了理论，接下来让我们开始实践吧：&lt;/p&gt;
&lt;p&gt;下面的内容可能对于初学者朋友来说比较晦涩难懂，但是不需要懂，只要按照步骤一步一步操作，就可以收获看得见的成就，也不要因为某个步骤卡壳而灰心，当初笔者创建本网站的时候，足足用了一整个下午和晚上才搞定。&lt;/p&gt;
&lt;p&gt;接下来我以windows操作系统以及astro框架作为例子，带大家上手。&lt;/p&gt;
&lt;h4&gt;1.安装node.js&lt;/h4&gt;
&lt;p&gt;访问node官网下载node.js：&lt;a href=&quot;https://nodejs.org/en/download&quot;&gt;Node.js官网&lt;/a&gt;
&lt;img src=&quot;image.png&quot; alt=&quot;alt text&quot;&gt;&lt;/p&gt;
&lt;p&gt;验证并安装pnpm：
打开你的终端，输入一下命令以验证安装成功：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;node -v
npm -v
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果能看到版本号说明nodejs和它的包管理器&apos;npm&apos;已经安装成功了。
我们推荐一个更现代、更快速的包管理器&apos;pnpm&apos;，同时对于一些特定的框架也推荐用bun&apos;来安装依赖：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;npm install -g pnpm
npm install -g bun
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;:::note[NOTE]
&apos;pnpm&apos; 和 &apos;bun&apos; 都是替代 &apos;npm&apos; 的现代包管理工具，安装速度更快、依赖更少。大多数现代项目会推荐使用其中之一，根据项目中是否有 &apos;pnpm-lock.yaml&apos; 或 &apos;bun.lockb&apos; 来判断。
:::&lt;/p&gt;
&lt;h3&gt;2.选择一个框架并下载一个模板&lt;/h3&gt;
&lt;p&gt;你无需从0开始一步步搭建，网络上有非常海量的开源优秀模板。当然，在选择模板前，需要确定你要用什么框架来编写前端。&lt;/p&gt;
&lt;p&gt;目前个人博客主流的框架有三个：Hexo、Astro、Hugo&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;一句话帮你选择：纯小白用Hexo、会一些前端用Astro、~~M属性选择Hugo~~&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;他们的具体区别可以借鉴这篇文章：&lt;a href=&quot;https://zhuanlan.zhihu.com/p/1981456864127522296&quot;&gt;博客框架选择指南&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;三个框架的官方网址：&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://hexo.io/zh-cn/&quot;&gt;Hexo&lt;/a&gt;
&lt;a href=&quot;https://docs.astro.build/zh-cn/getting-started/&quot;&gt;Astro&lt;/a&gt;
&lt;a href=&quot;https://gohugo.io/&quot;&gt;Hugo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;大家可以自行判断选择。&lt;/p&gt;
&lt;p&gt;我个人偏向选择Astro，因为毕竟学过点计算机，而且Astro作为新生代框架，技术栈极其先进，可以混用React和Vue组件，开发体验非常好。&lt;/p&gt;
&lt;p&gt;然后就可以开始搜索挑选模板了。可以直接在github中搜索，也可以在上面提到的官方网址中找。&lt;/p&gt;
&lt;p&gt;这里我用到的一个模板是：&lt;a href=&quot;https://github.com/cworld1/astro-theme-pure&quot;&gt;astro-theme-pure&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;已经有了比较成熟的教程文档：&lt;a href=&quot;https://astro-pure.js.org/docs&quot;&gt;Docs of Astro Theme Pure&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;然后如何使用这个主题，具体教学文档见Astro官方：&lt;a href=&quot;https://docs.astro.build/en/install-and-setup/#use-a-theme-or-starter-template&quot;&gt;Use a theme or starter template&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;接下来我就以自己的开发过程为例子带大家过一遍操作流程：&lt;/p&gt;
&lt;h3&gt;3.开始本地部署&lt;/h3&gt;
&lt;p&gt;首先在vscode上下载插件Astro:
&lt;img src=&quot;image-1.png&quot; alt=&quot;alt text&quot;&gt;&lt;/p&gt;
&lt;p&gt;然后把模板仓库直接克隆到本地：
&lt;img src=&quot;image-2.png&quot; alt=&quot;alt text&quot;&gt;&lt;/p&gt;
&lt;p&gt;接着使用刚才下载的包管理工具安装所有依赖：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;npm install
# 推荐使用pnpm，我当时用npm有出现一些报错
pnpm install
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;image-3.png&quot; alt=&quot;alt text&quot;&gt;&lt;/p&gt;
&lt;p&gt;在首次安装依赖时，有一些依赖包含可能执行敏感操作的包，pnpm会拦截这些脚本的自动执行，所以会提示运行&apos;pnpm approve-buids&apos;来手动选择允许哪些包运行：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;image-4.png&quot; alt=&quot;alt text&quot;&gt;&lt;/p&gt;
&lt;p&gt;安装好所有依赖以后，就可以使用测试命令，在本地进行运行测试了：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;pnpm run dev
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;image-5.png&quot; alt=&quot;alt text&quot;&gt;&lt;/p&gt;
&lt;p&gt;在浏览器中打开它，恭喜你，你的网站已经在本地成功运行了！&lt;/p&gt;
&lt;p&gt;更棒的是，它支持热更新（HMR）。现在你修改任何源文件（比如一篇文章），浏览器里的页面都会自动刷新，实时展示你的改动。&lt;/p&gt;
&lt;h3&gt;4.个性化你的内容&lt;/h3&gt;
&lt;p&gt;本地网站跑起来了，现在是把它变成你自己的东西的时候了。作为模板使用者，你的工作非常简单，主要集中在两点：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;修改配置文件：在项目根目录找到 astro.config.mjs, _config.yml 或类似名字的配置文件。打开它，把里面的网站标题、作者名、社交链接等改成你自己的信息。&lt;/li&gt;
&lt;li&gt;管理内容文件：对于博客，通常会有一个 src/content/blog/ 或 posts/ 目录。你只需要在这个目录里添加、修改或删除 Markdown (.md 或 .mdx) 文件，网站的文章列表和页面就会自动更新。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;:::note[NOTE]
&apos;.md&apos; 是 Markdown 的标准格式，用来写文章非常方便。而 &apos;.mdx&apos; 是带有 React JSX 成分的 Markdown 文件，支持写组件和交互元素，部分博客模板可能用它来增强功能。基本上全部的博客模板都支持 &apos;.md&apos; 和 &apos;.mdx&apos; 两种格式，同时它的基础语法非常简单，你可以在 &lt;a href=&quot;https://markdown.com.cn/basic-syntax/&quot;&gt;Markdown教程&lt;/a&gt; 中找到它的基本语法。
:::&lt;/p&gt;
&lt;h3&gt;5.将你的网站推送到GitHub&lt;/h3&gt;
&lt;p&gt;在本地修改完成后，我们通常需要把代码上传到GitHub，这不仅是备份的好习惯，更是我们实现自动化部署的关键一步&lt;/p&gt;
&lt;p&gt;假如说你直接 &apos;git clone&apos; 了源码，可以直接删掉 &apos;.git&apos; 文件夹，然后执行 &apos;git init&apos; 初始化一个新的仓库。&lt;/p&gt;
&lt;p&gt;在 &lt;a href=&quot;https://github.com/&quot;&gt;GitHub官网&lt;/a&gt; 官网上创建一个新的空仓库（New Repository）。&lt;/p&gt;
&lt;p&gt;根据 GitHub 页面的提示，在你本地的项目文件夹中，通过终端执行以下命令，将代码推送到你的新仓库：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;git init -b main
git add .
git commit -m &quot;Initial commit: My personal website setup&quot;
git remote add origin [你的仓库HTTPS或SSH地址]
git push -u origin main
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;假如说本来就是从自己的仓库中克隆的，则可以直接执行 &apos;git push&apos; 将代码推送到远程仓库。&lt;/p&gt;
&lt;h3&gt;6.使用Vercel/GitHub Page一键部署&lt;/h3&gt;
&lt;p&gt;最激动人的时刻到了，如何让全世界的人都能访问到你的网站，我们将使用Vercel或者GitHub Page实现这个功能&lt;/p&gt;
&lt;p&gt;这边建议大家直接用Vercel，以为一方面我选择的这个模板本身有部署在Vercel上，如果要部署在GitHub Page上的话，需要修改许多配置，并且需要你手动配置构建流程（GitHub Actions)，我当时遇到了很多麻烦（感兴趣可以看我这篇文章：&lt;a href=&quot;https://yuzhinn.top/blog/build-blog/build-blog&quot;&gt;我的个人博客搭建历程&lt;/a&gt;）&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;用GitHub登录Vercel：&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;前往 &lt;a href=&quot;https://vercel.com/&quot;&gt;Vercel&lt;/a&gt;，点击右上角的“Login”，选择使用 GitHub 账号授权登录。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;image-6.png&quot; alt=&quot;alt text&quot;&gt;&lt;/p&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;
&lt;p&gt;导入你的项目
登录后，在主面板点击 &apos;Add New…&apos; → &apos;Project&apos;。之后选择你自己的账号，直接 &apos;instal vercel&apos;。
&lt;img src=&quot;image-7.png&quot; alt=&quot;alt text&quot;&gt;
Vercel 会列出你的 GitHub 仓库，找到你刚刚创建的网站仓库，点击旁边的 Import 按钮。
&lt;img src=&quot;image-8.png&quot; alt=&quot;alt text&quot;&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;部署！ Vercel 会自动识别你的项目是什么框架（Astro, Next.js, etc.），并帮你填好所有构建设置。你什么都不用改，直接点击 Deploy 按钮。
&lt;img src=&quot;image-9.png&quot; alt=&quot;alt text&quot;&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;稍等片刻，Vercel 就会完成构建和部署。当看到庆祝的动画时，你的网站就已经上线了！Vercel 会提供一个 &apos;.vercel.app&apos; 结尾的免费域名供你访问。
&lt;img src=&quot;image-10.png&quot; alt=&quot;alt text&quot;&gt;&lt;/p&gt;
&lt;p&gt;从此以后，你只需要在本地修改代码，然后 git push 到 GitHub，Vercel 就会自动拉取最新代码，重新构建和部署你的网站。完全自动化！&lt;/p&gt;
&lt;h3&gt;7.绑定你的专属域名（可选）&lt;/h3&gt;
&lt;p&gt;拥有一个&apos;yourname.com&apos;这样的域名，你的网站才算完整。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;购买域名
前往 &lt;a href=&quot;https://www.namesilo.com/&quot;&gt;NameSilo&lt;/a&gt;、&lt;a href=&quot;https://godaddy.com/&quot;&gt;GoDaddy&lt;/a&gt; 等域名注册商，购买一个你喜欢的域名。过程就像网购一样简单。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;使用Cloudflare管理DNS
虽然域名商也提供DNS解析，但是Cloudflare提供免费的全球CDN加速和更强大的安全防护。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;注册并登录 &lt;a href=&quot;https://dash.cloudflare.com/&quot;&gt;Cloudflare&lt;/a&gt;。&lt;/li&gt;
&lt;li&gt;点击 &apos;Add a domain&apos;，输入你购买的域名，选择免费（Free）套餐。
&lt;img src=&quot;image-11.png&quot; alt=&quot;alt text&quot;&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;接下来输入你的域名，这里以一个不存在的域名为例：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;image-12.png&quot; alt=&quot;alt text&quot;&gt;&lt;/p&gt;
&lt;p&gt;遗憾选择 Free 方案，完全已经够用：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;image-13.png&quot; alt=&quot;alt text&quot;&gt;&lt;/p&gt;
&lt;p&gt;接下来 DNS 记录先跳过，之后再添加。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Cloudflare 会扫描你现有的 DNS 记录（如果是新域名，这里是空的），然后提示你更改 NameServer。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;image-14.png&quot; alt=&quot;alt text&quot;&gt;&lt;/p&gt;
&lt;p&gt;它会提供两个 NameServer 地址。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;image-15.png&quot; alt=&quot;alt text&quot;&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;回到你的域名注册商（如 NameSilo）的域名管理后台，找到 NameServer/DNS服务器 设置，删除原来的，替换为 Cloudflare 提供的那两个地址。例如对于 NameSilo，在 My Account -&gt; Domain Manager -&gt; yuzhinn.top -&gt; NameServers 删掉原来的东西，并且添加这些。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;等待几分钟到几小时，时常刷新一下，让更改生效。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;在 Vercel 和 Cloudflare 中配置&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;Vercel 端：进入 Vercel 的项目设置（Settings → Domains），输入你的域名并添加。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;image-16.png&quot; alt=&quot;alt text&quot;&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Cloudflare 端：在你的域名管理页面，进入 DNS → Records，添加一条 CNAME 记录：
&lt;ul&gt;
&lt;li&gt;Type: CNAME&lt;/li&gt;
&lt;li&gt;Name: @ (代表你的根域名)&lt;/li&gt;
&lt;li&gt;Target: cname.vercel-dns.com&lt;/li&gt;
&lt;li&gt;Proxy status: Proxied (保持橙色云朵亮起)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;image-17.png&quot; alt=&quot;alt text&quot;&gt;&lt;/p&gt;
&lt;p&gt;最后，在 Cloudflare 的 SSL/TLS 页面，将加密模式设置为 Full (strict)，以确保端到端的安全连接。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;image-18.png&quot; alt=&quot;alt text&quot;&gt;&lt;/p&gt;
&lt;p&gt;完成这些，稍等片刻，你就可以通过自己的专属域名访问你的网站了！&lt;/p&gt;
&lt;h3&gt;总结&lt;/h3&gt;
&lt;p&gt;通过以上步骤，你已经可以实现从零到一地搭建自己地网站了，在此基础上，你可以通过修改原有内容实现个性化，也可以混合多个不同模板的组件实现一些更有趣的需求，也可以通过强大的前端ai工具，帮你将想法落地现实。&lt;/p&gt;
&lt;p&gt;但是现在你的网站还存在很多的问题，比如，国内访问速度有限、功能比较单一、开发效率不够，这些都需要你开动脑筋，利用云服务器、各种强大的ai工具（例如OpenClaw、Hermes）等提高你的效率，提升你的网站访问速率。&lt;/p&gt;
&lt;p&gt;从这里开始，尽情创造吧！&lt;/p&gt;
&lt;p&gt;最后给大家一些优秀的博客案例：
https://cmder.xyz/&lt;/p&gt;
&lt;p&gt;https://step-out.github.io/&lt;/p&gt;
&lt;p&gt;https://wendyluo1127.github.io/&lt;/p&gt;
&lt;p&gt;https://unmei.cn/&lt;/p&gt;
&lt;p&gt;https://2cat.net/&lt;/p&gt;
&lt;p&gt;https://idealclover.top/&lt;/p&gt;
&lt;p&gt;https://axi404.top/&lt;/p&gt;
&lt;p&gt;https://d-sketon.github.io/astro-theme-reimu/&lt;/p&gt;
&lt;p&gt;https://liaoxuefeng.com/index.html 推荐他的git教程：https://liaoxuefeng.com/books/git/what-is-git/index.html&lt;/p&gt;
&lt;p&gt;https://www.ruanyifeng.com/&lt;/p&gt;
&lt;p&gt;参考文章：&lt;/p&gt;
&lt;p&gt;https://xue6ing.cn/archives/1705394947292&lt;/p&gt;
&lt;p&gt;https://axi404.top/blog/website-vercel#%E5%89%8D%E8%A8%80&lt;/p&gt;
&lt;p&gt;https://astro-pure.js.org/docs&lt;/p&gt;</content:encoded><h:img src="/_astro/thumbnail.CE_sGu7Z.png"/><enclosure url="/_astro/thumbnail.CE_sGu7Z.png"/></item><item><title>WSL2下OpenClaw部署实例</title><link>https://yingshznrgb.github.io/blog/openclaw/openclaw-wechat</link><guid isPermaLink="true">https://yingshznrgb.github.io/blog/openclaw/openclaw-wechat</guid><description>在WSL2下部署OpenClaw，连接微信ClawBot并实现SQL server数据库远程查询</description><pubDate>Sun, 19 Apr 2026 00:00:00 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;此篇文档来源于我的数据库系统原理课程一项作业，要求使用小龙虾对话查询数据库。于是我将整个过程记录下来，形成了这篇文章。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;2026年年初的时候，小龙虾（OpenClaw）爆火，一直对它有所兴趣但是懒得动手的我，被老师的课程项目催促，不得不对它伸出毒手了，终于花了一个下午的时间，搞定了整个部署以及应用的过程，下面是详细的记录，如果有人感兴趣可以参考。&lt;/p&gt;
&lt;p&gt;:::note[NOTE]
OpenClaw，因其红色龙虾图标又被称为“龙虾”，是一个开源的自主人工智能虚拟助理软件项目。 它可以被看作是一个个人AI助手或一个AI代理框架，允许用户构建可自定义的私人AI助手，以自动执行各种任务。
:::&lt;/p&gt;
&lt;h3&gt;我的环境&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Windows11_X64_版本号：25H2&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;WSL2安装&lt;/h1&gt;
&lt;p&gt;如果你对Linux开发感兴趣，相信已经装过了WSL2，可以直接跳过这个部分。&lt;/p&gt;
&lt;h3&gt;前置准备&lt;/h3&gt;
&lt;p&gt;开启wsl2和虚拟机平台功能：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;按下&apos;win+R&apos;，输入&apos;optionalfeatures&apos;，回车打开 &apos;Windows功能&apos; 窗口&lt;/li&gt;
&lt;li&gt;勾选以下两个选项
&lt;ul&gt;
&lt;li&gt;适用于Linux的Windows子系统&lt;/li&gt;
&lt;li&gt;虚拟机平台
&lt;img src=&quot;image.png&quot; alt=&quot;alt text&quot;&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;点击确定，等待安装完成后重启电脑&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Tips: 安装完成后，建议先检查系统版本是否达标（&gt;=21H2）&lt;/p&gt;
&lt;h3&gt;WSL2安装&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;管理员身份打开windows终端&lt;/li&gt;
&lt;li&gt;命令行安装wsl2: 相关指令如下：&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code&gt;# 一键安装，自动启用功能，下载发行版，设置默认版本为2
wsl --install 

# 查看可选的wsl分发版（可选）
wsl --list --online 
# 安装指定版本
wsl --install -d Ubuntu-22.04 
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;image-1.png&quot; alt=&quot;alt text&quot;&gt;
3. 安装完成后，终端提示如上，会自动打开Ubuntu终端窗口，如果没有自启动按下&apos;win+s&apos;，搜索Ubuntu启动&lt;/p&gt;
&lt;ol start=&quot;4&quot;&gt;
&lt;li&gt;然后按照终端提示设置用户名和密码&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;image-2.png&quot; alt=&quot;alt text&quot;&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;（可选但建议）更换国内源，我这里更换了阿里源：&lt;/li&gt;
&lt;li&gt;先自检ubuntu版本，使用&apos;lsb_release&apos;命令，可以看到我的ubuntu版本是24.04：&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;image-3.png&quot; alt=&quot;alt text&quot;&gt;
2. 然后建议根据自己版本自行搜索换源方式，我这里直接放我的版本的操作：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# 备份
sudo cp /etc/apt/sources.list.d/ubuntu.sources /etc/apt/sources.list.d/ubuntu.sources.bak

# 编辑源文件
sudo nano /etc/apt/sources.list.d/ubuntu.sources

# 清空或注释所有内容替换为：
Types: deb
URIs: https://mirrors.aliyun.com/ubuntu/
Suites: noble noble-updates noble-backports noble-security
Components: main restricted universe multiverse
Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg

# 更新缓存
sudo apt update
sudo apt upgrade -y
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;常用操作命令&lt;/h3&gt;
&lt;p&gt;以下命令均在Windows终端中执行（非Ubuntu终端）可以直接复制粘贴&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;启动与关闭&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code&gt;# 启动WSL（直接进入默认发行版Ubuntu）
wsl
# 或 启动指定发行版（替换Ubuntu-24.04为你的发行版名称）
wsl -d Ubuntu-24.04

# 关闭所有WSL实例（彻底关闭，释放内存，建议不用时执行）
wsl --shutdown

# 关闭指定发行版
wsl --terminate Ubuntu-24.04
&lt;/code&gt;&lt;/pre&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;查看wsl状态与版本&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code&gt;# 查看已安装的所有WSL发行版，以及对应的WSL版本（1/2）
wsl -l -v
# 查看WSL版本信息
wsl --version

# 设置默认WSL版本（全局生效，后续安装的发行版默认用此版本）
wsl --set-default-version 2

# 设置默认发行版（后续输入wsl直接启动该发行版）
wsl --set-default Ubuntu-24.04
&lt;/code&gt;&lt;/pre&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;卸载wsl发行版&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code&gt;# 查看发行版名称（确认要卸载的发行版）
wsl -l -v
# 卸载指定发行版（替换Ubuntu-24.04为要卸载的名称，卸载后数据丢失）
wsl --unregister Ubuntu-24.04
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Windows与WSL文件互访&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;wsl访问Windows文件方式：
&lt;ol&gt;
&lt;li&gt;Windows的C盘：在Ubuntu终端输入&apos;cd /mnt/c&apos;，即可进入C盘根目录&lt;/li&gt;
&lt;li&gt;windows的所有磁盘都挂在在/mnt目录下面&lt;/li&gt;
&lt;li&gt;示例：访问C盘用户目录：&apos;cd /mnt/c/Users/你的Windows&apos;用户名&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;image-4.png&quot; alt=&quot;alt text&quot;&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Windows访问WSL文件：
&lt;ol&gt;
&lt;li&gt;方法一（推荐）：Ubuntu终端输入&apos;explorer.exe . &apos;（注意末尾空格和点），会自动打开Windows文件管理器&lt;/li&gt;
&lt;li&gt;方法二（有些电脑可能不行）：手动打开文件管理器，在地址栏输入&apos;\wsl$&apos;回车，即可看到所有已安装的WSL发行版，双击进入即可访问文件。
VScode连接WSL&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;VScode连接WSL&lt;/h3&gt;
&lt;p&gt;如果用vscode开发linux项目，直接连接wsl，可以实现在Windows中编辑，在WSL中运行，无需切换环境，比较方便&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;安装VScode&lt;/li&gt;
&lt;li&gt;在VScode中搜索安装安装wsl插件
&lt;img src=&quot;image-5.png&quot; alt=&quot;alt text&quot;&gt;&lt;/li&gt;
&lt;li&gt;点击VScode左下角&gt;&amp;#x3C;符号，然后选择连接到wsl即可
&lt;img src=&quot;image-6.png&quot; alt=&quot;alt text&quot;&gt;&lt;/li&gt;
&lt;li&gt;成功连接后：
&lt;img src=&quot;image-7.png&quot; alt=&quot;alt text&quot;&gt;
接下来就可以畅通使用wsl了！&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;参考文章：https://blog.csdn.net/weixin_44818765/article/details/157736533&lt;/p&gt;
&lt;h1&gt;OpenClaw基础安装&lt;/h1&gt;
&lt;h3&gt;写在前面&lt;/h3&gt;
&lt;p&gt;Windows安装前置要求（请安装前自行检查）：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Nodejs &gt;= 22&lt;/li&gt;
&lt;li&gt;WSL2&lt;/li&gt;
&lt;li&gt;Git&lt;/li&gt;
&lt;li&gt;科学上网&lt;/li&gt;
&lt;li&gt;pnpm（从源码构建需要，可选）&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;OpenClaw中文官网：https://docs.openclaw.ai/zh-CN&lt;/p&gt;
&lt;h3&gt;开始安装&lt;/h3&gt;
&lt;p&gt;直接选择官方推荐的一键安装方式（安装过程建议保持科学上网）：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;打开进入wsl&lt;/li&gt;
&lt;li&gt;运行安装命令：&apos;curl -fsSL https://openclaw.ai/install.sh | bash&apos;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;image-8.png&quot; alt=&quot;alt text&quot;&gt;&lt;/p&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;需要输入一次密码，然后等待安装步骤（会先检查你的环境，是否满足之前提到的系统要求）&lt;/li&gt;
&lt;li&gt;出现以下提示，说明开始安装（一些电脑安装过程是非可视化的就和下图一样，此时只需要保证网络通畅即可）&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;image-9.png&quot; alt=&quot;alt text&quot;&gt;&lt;/p&gt;
&lt;ol start=&quot;5&quot;&gt;
&lt;li&gt;出现一下界面说明安装成功：&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;image-10.png&quot; alt=&quot;alt text&quot;&gt;&lt;/p&gt;
&lt;ol start=&quot;6&quot;&gt;
&lt;li&gt;这里提示我找不到环境变量：
&lt;img src=&quot;image-11.png&quot; alt=&quot;alt text&quot;&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;可以直接忽略，因为他已经自动把环境变量添加好了，重新打开ubuntu终端即可生效。&lt;/p&gt;
&lt;h3&gt;配置选择过程&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;image-12.png&quot; alt=&quot;alt text&quot;&gt;&lt;/p&gt;
&lt;p&gt;是否个人使用，选择yes&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;image-13.png&quot; alt=&quot;alt text&quot;&gt;&lt;/p&gt;
&lt;p&gt;建议选择QuickStart，会自动使用合理的默认值&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;image-14.png&quot; alt=&quot;alt text&quot;&gt;&lt;/p&gt;
&lt;p&gt;模型选择，这个可以根据各自情况自行选择（注意之前可以使用的免费千问已经不支持了，现在是需要付费的Qwen Cloud，具体可见官方文档：https://docs.openclaw.ai/zh-CN/providers/qwen）&lt;/p&gt;
&lt;p&gt;我这里选择deepseek，然后填写apikey：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;image-15.png&quot; alt=&quot;alt text&quot;&gt;
&lt;img src=&quot;image-16.png&quot; alt=&quot;alt text&quot;&gt;&lt;/p&gt;
&lt;p&gt;默认模型我直接选择了当前模型deepseek&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;image-17.png&quot; alt=&quot;alt text&quot;&gt;&lt;/p&gt;
&lt;p&gt;选择聊天渠道，我这里暂时先跳过&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;image-18.png&quot; alt=&quot;alt text&quot;&gt;&lt;/p&gt;
&lt;p&gt;联网搜索配置，我这里也先跳过，如果后续有需要可以使用openclaw tools setup web命令配置&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;image-19.png&quot; alt=&quot;alt text&quot;&gt;&lt;/p&gt;
&lt;p&gt;配置skills，我这里暂时跳过&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;image-20.png&quot; alt=&quot;alt text&quot;&gt;&lt;/p&gt;
&lt;p&gt;钩子我也暂时跳过&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;image-21.png&quot; alt=&quot;alt text&quot;&gt;&lt;/p&gt;
&lt;p&gt;然后他会安装gateway&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;image-22.png&quot; alt=&quot;alt text&quot;&gt;&lt;/p&gt;
&lt;p&gt;ui我选web ui，比较方便用&lt;/p&gt;
&lt;p&gt;到这里基本配置就结束了。&lt;/p&gt;
&lt;p&gt;这里给了直接访问的链接（http://127.0.0.1:18789/#token=xxxxxxxxxx）&lt;/p&gt;
&lt;p&gt;还有工作区备份、安全警告等说明文档。&lt;/p&gt;
&lt;p&gt;直接复制访问链接到浏览器打开即可：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;image-24.png&quot; alt=&quot;alt text&quot;&gt;
&lt;img src=&quot;image-25.png&quot; alt=&quot;alt text&quot;&gt;&lt;/p&gt;
&lt;p&gt;可以看到已经可以进行对话了，到这里OpenClaw的基本安装就已经结束，恭喜！！！&lt;/p&gt;
&lt;h3&gt;常用命令&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;# 查看配置
openclaw config list

# 修改配置
openclaw configure

# 打开web控制台
openclaw dashboard
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;更多命令可查官方速查表：&lt;a href=&quot;https://openclawgithub.cc/guide/cheatsheet/#%25E6%2597%25A5%25E5%25BF%2597%25E5%2591%25BD%25E4%25BB%25A4&quot;&gt;OpenClaw 超级速查表&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;参考文章：zhuanlan.zhihu.com
参考视频：https://www.bilibili.com/video/BV1WLQwBrEL8?p=6&amp;#x26;vd_source=dc2cc07eaa930a2e35f5320de46b2f52&lt;/p&gt;
&lt;h1&gt;OpenClaw应用实例&lt;/h1&gt;
&lt;h3&gt;OpenClaw接入微信&lt;/h3&gt;
&lt;p&gt;首先打开OpenClaw，确保启动openclaw网关：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;openclaw gateway start
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;image-26.png&quot; alt=&quot;alt text&quot;&gt;&lt;/p&gt;
&lt;p&gt;执行腾讯官方的微信对接插件安装命令：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;npx -y @tencent-weixin/openclaw-weixin-cli@latest install
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然后打开手机微信，我的，设置，插件，可以看到clawbot插件，然后扫描二维码即可连接成功：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;image-29.png&quot; alt=&quot;alt text&quot;&gt;&lt;/p&gt;
&lt;p&gt;可以输入&apos;openclaw status&apos;查看Channels状态：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;image-30.png&quot; alt=&quot;alt text&quot;&gt;&lt;/p&gt;
&lt;h3&gt;创建数据库&lt;/h3&gt;
&lt;p&gt;打开SQL server，并通过下列代码创建数据库：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;-- 创建数据库
CREATE DATABASE StudentDB;

USE StudentDB;

-- 创建 Student 表
CREATE TABLE Student (
    Sno CHAR(8) PRIMARY KEY,
    Sname VARCHAR(20),
    Ssex CHAR(2),
    Sage INT,
    Sdept CHAR(4)
);

-- 创建 Course 表
CREATE TABLE Course (
    Cno INT PRIMARY KEY,
    Cname VARCHAR(20),
    Cpno INT NULL,
    Ccredit INT
);

-- 创建 SC 表
CREATE TABLE SC (
    Sno CHAR(8),
    Cno INT,
    Grade INT,
    PRIMARY KEY (Sno, Cno),
    FOREIGN KEY (Sno) REFERENCES Student(Sno),
    FOREIGN KEY (Cno) REFERENCES Course(Cno)
);

-- 插入 Student 数据
INSERT INTO Student (Sno, Sname, Ssex, Sage, Sdept) VALUES
(&apos;2024001&apos;, &apos;林书凡&apos;, &apos;男&apos;, 18, &apos;MA&apos;),
(&apos;2024002&apos;, &apos;李欣然&apos;, &apos;女&apos;, 19, &apos;IS&apos;),
(&apos;2024003&apos;, &apos;王武义&apos;, &apos;男&apos;, 20, &apos;CS&apos;),
(&apos;2024004&apos;, &apos;苏文甜&apos;, &apos;女&apos;, 19, &apos;CS&apos;);

-- 插入 Course 数据
INSERT INTO Course (Cno, Cname, Cpno, Ccredit) VALUES
(1, &apos;大数据&apos;, 3, 2),
(2, &apos;操作系统&apos;, 5, 4),
(3, &apos;数据库&apos;, 5, 4),
(4, &apos;编译原理&apos;, NULL, 4),
(5, &apos;编程语言&apos;, NULL, 2),
(6, &apos;数据挖掘&apos;, 3, 2);

-- 插入 SC 数据
INSERT INTO SC (Sno, Cno, Grade) VALUES
(&apos;2024001&apos;, 1, 97),
(&apos;2024001&apos;, 2, 78),
(&apos;2024001&apos;, 3, 86),
(&apos;2024002&apos;, 2, 85),
(&apos;2024002&apos;, 3, 77);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;可以看到创建成功：
&lt;img src=&quot;image-31.png&quot; alt=&quot;alt text&quot;&gt;
&lt;img src=&quot;image-32.png&quot; alt=&quot;alt text&quot;&gt;&lt;/p&gt;
&lt;h3&gt;配置SQL server&lt;/h3&gt;
&lt;p&gt;启用TCP/IP协议：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;image-33.png&quot; alt=&quot;alt text&quot;&gt;&lt;/p&gt;
&lt;p&gt;先右键启用，再右键配置属性IP地址，IPALL中TCP端口填写1433：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;image-34.png&quot; alt=&quot;alt text&quot;&gt;&lt;/p&gt;
&lt;p&gt;点击应用、确定，并重启SQL server服务&lt;/p&gt;
&lt;p&gt;在安全性一栏添加登录账户，配置密码：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;image-35.png&quot; alt=&quot;alt text&quot;&gt;
&lt;img src=&quot;image-36.png&quot; alt=&quot;alt text&quot;&gt;&lt;/p&gt;
&lt;p&gt;配置只读权限（图片中的是错误示例，开成了黑名单只读也就是不可读，正确的是db_datereader）：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;image-37.png&quot; alt=&quot;alt text&quot;&gt;&lt;/p&gt;
&lt;h3&gt;配置skills&lt;/h3&gt;
&lt;p&gt;搜索到两个skills比较契合该任务：&lt;/p&gt;
&lt;p&gt;https://clawhub.ai/gitgoodordietrying/sql-toolkit&lt;/p&gt;
&lt;p&gt;https://clawhub.ai/vince-winkintel/sql-server-skills&lt;/p&gt;
&lt;p&gt;先安装ClawHub（skill市场）&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;image-38.png&quot; alt=&quot;alt text&quot;&gt;&lt;/p&gt;
&lt;p&gt;安装skills：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;image-39.png&quot; alt=&quot;alt text&quot;&gt;
&lt;img src=&quot;image-40.png&quot; alt=&quot;alt text&quot;&gt;&lt;/p&gt;
&lt;p&gt;重启 OpenClaw 守护程序&lt;/p&gt;
&lt;h3&gt;配置openclaw&lt;/h3&gt;
&lt;p&gt;新建配置文件：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;image-41.png&quot; alt=&quot;alt text&quot;&gt;&lt;/p&gt;
&lt;p&gt;并编写配置文件内容如下：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# ~/.openclaw/config.yaml

skills:
  - id: &quot;query-my-sqlserver&quot;
    uses: &quot;nl2sql&quot;
    with:
      llm:
        provider: &quot;deepseek&quot;
        model: &quot;deepseek-chat&quot;

      db:
        driver: &quot;mssql&quot; 
        host: &quot;10.27.1xxxxxxx&quot; # Windows IP
        port: 1433
        database: &quot;Studxxxxxx&quot; # 数据库名
        username: &quot;${env.DB_USER}&quot;
        password: &quot;${env.DB_PASS}&quot;
        encryption: true

      schema: |
        -- 粘贴 CREATE TABLE 语句
        CREATE TABLE Student (
            Sno CHAR(8) PRIMARY KEY,
            Sname VARCHAR(20),
            Ssex CHAR(2),
            Sage INT,
            Sdept CHAR(4)
        );
        CREATE TABLE Course (
            Cno INT PRIMARY KEY,
            Cname VARCHAR(20),
            Cpno INT NULL,
            Ccredit INT
        );
        CREATE TABLE SC (
            Sno CHAR(8),
            Cno INT,
            Grade INT,
            PRIMARY KEY (Sno, Cno),
            FOREIGN KEY (Sno) REFERENCES Student(Sno),
            FOREIGN KEY (Cno) REFERENCES Course(Cno)
        );

# 环境变量
env:
  DB_USER: &quot;xxxxxx&quot;
  DB_PASS: &quot;xxxxxx&quot; 
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然后与微信clawbot对话，尝试连接数据库：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;image-42.png&quot; alt=&quot;alt text&quot;&gt;&lt;/p&gt;
&lt;p&gt;然后查询的时候遇到了问题，因为sql-server-skills需要安装sqlcmd，所以先安装sqlcmd：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;image-43.png&quot; alt=&quot;alt text&quot;&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;curl https://packages.microsoft.com/keys/microsoft.asc | sudo tee /etc/apt/trusted.gpg.d/microsoft.asc

# 由于我的ubuntu是24.04所以改成更兼容一点的22.04
add-apt-repository &quot;$(wget -qO- https://packages.microsoft.com/config/ubuntu/22.04/prod.list)&quot;

apt-get update
apt-get install sqlcmd
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;image-44.png&quot; alt=&quot;alt text&quot;&gt;&lt;/p&gt;
&lt;p&gt;这里安装完成。&lt;/p&gt;
&lt;p&gt;重新继续查询任务：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;image-45.png&quot; alt=&quot;alt text&quot;&gt;&lt;/p&gt;
&lt;p&gt;提示说登录失败，于是我修改了ssms中登录方式：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;image-46.png&quot; alt=&quot;alt text&quot;&gt;&lt;/p&gt;
&lt;p&gt;重启服务后再次尝试：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;image-47.png&quot; alt=&quot;alt text&quot;&gt;&lt;/p&gt;
&lt;p&gt;说没有select的权限，发现之前把权限设置错误了，重新配置权限：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;image-48.png&quot; alt=&quot;alt text&quot;&gt;&lt;/p&gt;
&lt;p&gt;再次尝试：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;image-49.png&quot; alt=&quot;alt text&quot;&gt;&lt;/p&gt;
&lt;p&gt;查询完成！！！&lt;/p&gt;
&lt;p&gt;tips：&lt;/p&gt;
&lt;p&gt;最后附一下总共token的消费：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;image-50.png&quot; alt=&quot;alt text&quot;&gt;&lt;/p&gt;
&lt;h1&gt;小结&lt;/h1&gt;
&lt;p&gt;OpenClaw确实可以自主帮我们完成任务，但是我们的提示词一定要小心谨慎，下载skills时也要小心谨慎，因为它可能会不经过我们同意自主搞一些不太好的事情，所以大家使用的时候要小心嗷。&lt;/p&gt;</content:encoded><h:img src="/_astro/image-10.CkmHLqk5.png"/><enclosure url="/_astro/image-10.CkmHLqk5.png"/></item><item><title>2025年度总结</title><link>https://yingshznrgb.github.io/blog/2025-sum/2025-summary</link><guid isPermaLink="true">https://yingshznrgb.github.io/blog/2025-sum/2025-summary</guid><description>关于我的一年,都在这儿了</description><pubDate>Wed, 31 Dec 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;2025最后一天也即将过去，一年的时光原来这么快，眨眼间从踌躇满志的大二上到了大三上学期的期末，回顾这一年来，自己学会了很多也变化了很多。&lt;/p&gt;
&lt;p&gt;今年的日常依旧每天活跃在小猫大学，在宿舍-教室-社团几点之间来回奔波，尤其是更新了硬件设备之后，每天都坐在电脑前翻来覆去。&lt;/p&gt;
&lt;p&gt;年初的自己还是大二的小中登，不知怎么年末突然变成超级老登了。&lt;/p&gt;
&lt;p&gt;也许是见证了两届学长的毕业，越发感觉到自己的本科生活正被没收剥夺；&lt;/p&gt;
&lt;p&gt;也许是两年多的摸爬滚打，认识到大学原来也就那么回事，逐渐对大学生活祛魅了，只剩下责任感在身上；&lt;/p&gt;
&lt;p&gt;也许是平时接触更多的是小学弟，自己不知不觉已经成为老资历了；&lt;/p&gt;
&lt;p&gt;如果现在问我大学生活的经验，我绝对滔滔不绝说上三天三夜，你要再问我怎么规划自己的未来，我仍旧可以滔滔不绝三天三夜。可以说今年关于自己的人生思考最多的问题就是未来的规划。要从保研、就业、考公、考研等等里面选出个所以然，那现在的我特别擅长了。&lt;/p&gt;
&lt;p&gt;即便如此，事情落到自己身上的时候，总是比别人身上要麻烦的多。我甚至思考过我是谁的哲学问题，思考过我的天赋在哪，我的长处如何，虽然没有什么肯定的回答，但我比往常任何时候都更加深刻的认识了自己；&lt;/p&gt;
&lt;p&gt;就比如，我骨子里是个e人，但从小到大表现的很i，导致现在的我好像处于i与e的分界，这个我专门问过学心理学的老师，他告诉我分界不是平均，而是精神分裂hhh，但其实我有能量时确实渴望与人社交，并且也会从中获取一定的能量，没有什么绝对的i和e，我这人就这鸟样；再比如我找到了各方面的天赋，例如超强的专注力，让我做什么事情都能全身心投入，并且忘记时间的概念，但与此同时非常讨厌被人打扰，因此面对繁杂的大学生活有时会显得很烦躁；又比如我明白了人确实为自己而活，更少地去在意自己在某些别人眼里的形象等等。&lt;/p&gt;
&lt;p&gt;虽然更加了解自己没什么值得自吹自擂的，但是我觉得这是我今年最大的收获之一，甚至是我一生中最大的收获之一。&lt;/p&gt;
&lt;p&gt;当然，今年的我变了很多，也尝试了很多从未尝试的事情。&lt;/p&gt;
&lt;p&gt;我开始更多的学习如何打扮自己，从护肤、发型、穿搭，各个方面，经常早上起个床收拾半个多小时，跟着某音的博主学着弄头发、搞穿搭，虽然现在还是个小白，但是我对自己的审美还是有自信的，所以我相信后面会越来越好，而且我发现打扮自己真的非常快乐，虽然人长什么样基本由基因决定，但是折腾和不折腾，给人的感觉天差地别。我甚至尝试了化妆，也不怕人笑话，粉底液、散粉我都尝试了，再加上护肤买的东西，~~列举出来容易被说是gay~~（问就是有人这么说过）。&lt;/p&gt;
&lt;p&gt;我开始更多地记录自己，虽然不上镜，没有颜值，但拍给自己看这些都不重要，走不了性感风就走可爱风，走不了可爱风就走亲和风，亲和风都走不了那就走高P风，怎么舒服怎么好看怎么来。记录自己确实能够让自己变得更好，能让你看到自己的变化，自己的成长，将延迟满足切片成即刻的满足，简直是拖延癌的救星。&lt;/p&gt;
&lt;p&gt;我开始搭建属于自己的内容体系。首先我创建了自己的个人博客，在上面乱写一些东西，时不时拿出来看一下会觉得很有成就感，虽然写的东西质量参差不齐，也没写很多，但是这种切实拥有属于自己的东西的感觉非常让人欲罢不能，就是可以随意根据自己的想法去更改风格、增删东西，就比如装一个音乐的播放器在上面，能浏览文章的时候听歌，有一种免费获得qq会员的爽感hhh。其次我开始更频繁地写一些自己的小想法，记录一些自己的所思所感，这个让我非常明显地感觉自己总是处于思考状态，脑子一直在活动，~~如果你觉得自己脑子秀逗可以尝试一下~~。并且我逐渐开始学习将自己的money有规则得存起来，虽然这个对一个高度p人非常难，但是我觉得这个非常重要。&lt;/p&gt;
&lt;p&gt;我也开始转变自己关于很多事情的想法，例如关于自己的未来，不再以一个天真的视角看待自己的精力，不对未来的自己抱有更多的期待，更多去关注当前阶段的自己，把未来描绘的更加模糊，可以让自己现今的选择更加清晰。&lt;/p&gt;
&lt;p&gt;我开始逐渐体会到阅读的快乐，对网络小说丰富的阅读经验，让我回归那些更有名的文学圈著作时，深刻体会到其文笔的深厚和思想的丰富，远比网络小说跌宕却套路的故事情节更吸引人，也更能引发我对自己的生活的思考。高中结束之后与文字的距离越来越远，我切实的感受到自己的描写越发苍白，只有骨骼没有肌肉的文字更多的出现在我的笔下，而网络热梗就像黏在鞋子上的口香糖，讨厌却甩不掉，总是不自觉的从脑子里面蹦出来。这也让高级的文字更加的吸引我，我的阅读也更多的去体会和揣摩文字排列组合的美丽，而不是故事情节的种种。&lt;/p&gt;
&lt;p&gt;当然，今年依旧保持高强度网上冲浪，从年初在王者峡谷奋战，到后来瓦洛兰特、三角洲，可以说游戏都没少玩，然后也玩了一些高质量的单机游戏，比如黑神话、丝之歌、只狼等等，然而都没通关hhh。补了许多动漫，例如《罪恶王冠》、《86-不存在的战区》、《画江湖之不良人》，看了许多电视剧，例如《陷入我们的热恋》、《春色寄情人》等，也刷了很多综艺，例如《音乐缘计划》、《中国唱将》等。看的东西杂七杂八，什么都看一点，在此感谢某鱼平台为我的会员付出的贡献，高清无广真的很爽。&lt;/p&gt;
&lt;p&gt;同样，今年也取得了许多大大小小的成就，学会了打高尔夫，尝试学习了弹钢琴，学会了剪视频，学会了更多唱歌的技巧，学会了更多编程语言、更多计算机相关的知识，此外，八段锦已经成为肌肉记忆，键盘盲打的速度史无前例，FPS点小球的技巧愈发熟练，王者巅峰赛来到了1800，远程签到的方式更加多样，吹牛的技巧也更上一层楼，脸皮比以前也更厚了。正经东西的话，拿了一个创新类比赛的国二，一些小比赛的省奖，八段锦校奖，少许可怜的奖学金，担任了几个学生工作的职务。&lt;/p&gt;
&lt;p&gt;今年许多值得记忆的深刻瞬间，让我的生活丰富而深刻：&lt;/p&gt;
&lt;p&gt;一月十八号，第一次在同学的陪伴下度过自己的生日，吃了同学买的蛋糕，幸福满满；&lt;/p&gt;
&lt;p&gt;一月二十八号，在老家感受久违的围炉取暖，暖尽一年的心酸寒苦；&lt;/p&gt;
&lt;p&gt;二月八号，在武汉高铁站中转通宵，《哪吒2》陪我度过孤独时光；&lt;/p&gt;
&lt;p&gt;三月七号，新工科大楼新引入的咖啡机让人赞不绝口；&lt;/p&gt;
&lt;p&gt;四月二号，答应了同学早上去思明吃饭，结果睡到中午，仍然吃上了漂亮饭；&lt;/p&gt;
&lt;p&gt;四月十七号，军理课出大糗，史上最社死的一集；&lt;/p&gt;
&lt;p&gt;四月二十号，在泉州喝了唐沫茶兮，回味无穷；&lt;/p&gt;
&lt;p&gt;五月十一号，小组社会实践去实地采访，结果都是社恐走完了全程采访了零个人；&lt;/p&gt;
&lt;p&gt;六月十三号，第一知道理发店还有按摩服务，并且被按的头疼；&lt;/p&gt;
&lt;p&gt;六月二十二号，为了比赛想方案想了三天毫无进展；&lt;/p&gt;
&lt;p&gt;七月二十九号，陪伴高中同学在厦门玩了一天，吃到了最好吃的沙茶面；&lt;/p&gt;
&lt;p&gt;九月二十二号，早晨六点的日出非常美；&lt;/p&gt;
&lt;p&gt;十月二十四号，几个月没碰八段锦依然信手捏来；&lt;/p&gt;
&lt;p&gt;十一月七号，发现宝藏穿搭博主，大半夜学习穿搭技巧到凌晨；&lt;/p&gt;
&lt;p&gt;十二月三号，第一次尝试寿喜烧感觉味道很上头；&lt;/p&gt;
&lt;p&gt;十二月六号，今天绝对是自拍最多的一天，沉迷自己的颜值不可自拔；&lt;/p&gt;
&lt;p&gt;十二月十号，手工织围巾进行时；&lt;/p&gt;
&lt;p&gt;十二月十六号，被扬才班党会震撼，同学们演技爆棚，罗扬才扮演者令人印象深刻；&lt;/p&gt;
&lt;p&gt;十二月二十一号，创造了史上最唐的ppt；&lt;/p&gt;
&lt;p&gt;十二月三十一号，写下人生第一篇年度报告。&lt;/p&gt;
&lt;p&gt;回顾一年，自己变得更加成熟，人生观世界观更加明晰，展望未来，希望自己活出自己想成为的样子。&lt;/p&gt;
&lt;p&gt;新的一年，我的目标：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;[ ] 保研上岸&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;[ ] 网站优化至大陆即刻访问&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;[ ] 写五篇高质量的文章&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;[ ] 自费去三个陌生的城市&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;[ ] 读完五本书&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;[ ] get两个新技能&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;[ ] 深度参与一项科研任务&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;[ ] 开发一个高质量的新项目&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;[ ] 坚持运动&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;</content:encoded><h:img src="/_astro/thumbnail.8x80JNtA.jpg"/><enclosure url="/_astro/thumbnail.8x80JNtA.jpg"/></item><item><title>小站装修记录</title><link>https://yingshznrgb.github.io/blog/change</link><guid isPermaLink="true">https://yingshznrgb.github.io/blog/change</guid><description>记录了此站建立以来做了哪些风格上的修改</description><pubDate>Fri, 19 Dec 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;字体：引入 「霞鹜文楷」。&lt;/p&gt;
&lt;p&gt;质感背景：叠加了一层极淡的 噪点 (Grainy Texture)，增加“纸质感”。&lt;/p&gt;
&lt;p&gt;鼠标选取色彩微调：鼠标选区颜色改成了 亮蓝色。&lt;/p&gt;
&lt;p&gt;手感优化：引入 Lenis 平滑滚动。&lt;/p&gt;
&lt;p&gt;首页文字：增加了 Fade In (浮现) 动画。&lt;/p&gt;
&lt;p&gt;文章首段文字：第一个字超大写。&lt;/p&gt;
&lt;p&gt;Projects 页面：
放弃了复杂的特效，回归 极简图文卡片。
增加了 微悬浮 + 阴影 交互。
设计了 首字母大写水印，营造出“设计杂志”的高级排版感。&lt;/p&gt;
&lt;p&gt;404 页面：去掉了报错提示，改成了 巨大的装饰数字 + 托尔金的诗句。&lt;/p&gt;
&lt;p&gt;Header：在搜索旁增加了 Travelling (开往) 的小火车/地球入口。&lt;/p&gt;
&lt;p&gt;点击特效：制作了 水墨晕染 (Ink Ripple) 效果，点击时会溅开不规则的墨痕。&lt;/p&gt;
&lt;p&gt;文章引用块：改造成了古籍批注风格，带有巨大的引号水印。&lt;/p&gt;
&lt;p&gt;手写签名：在部分页面和文章后面放手写签名字体。&lt;/p&gt;
&lt;p&gt;音乐播放：在左下角添加音乐播放器，目前歌单是我从自己qq音乐歌单挑出来的几首免费的歌。&lt;/p&gt;
&lt;p&gt;（已弃用）阅读进度条：顶部增加了淡金色进度条，并且有一只 小纸船 ⛵️ 随着阅读漂流。&lt;/p&gt;
&lt;p&gt;（已弃用）回到顶部：右上角挂了一只线条风格的小猫，点击它就能拉回顶部，且解决了白色背景隐身的问题。&lt;/p&gt;
&lt;hr&gt;</content:encoded><h:img src="/_astro/image.C3ZGZPsv.png"/><enclosure url="/_astro/image.C3ZGZPsv.png"/></item><item><title>从初学者的角度扫过Astro</title><link>https://yingshznrgb.github.io/blog/astro-build/astro-build</link><guid isPermaLink="true">https://yingshznrgb.github.io/blog/astro-build/astro-build</guid><description>此篇记录了我搭建Astro以来踩过的坑，遇到的各种小白问题</description><pubDate>Tue, 16 Dec 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;对于第一次接触前端的我，处处像个小白，小到@的使用，大到组件的修改，总是遇到各种问题，在gemini的帮助下也是逐渐走上了正确的道路。&lt;/p&gt;
&lt;p&gt;这也是我第一次在&lt;strong&gt;没有学会一个知识之前&lt;/strong&gt;直接动手去做，边做边学的一次经历，希望我能坚持把这篇文章写下去。&lt;/p&gt;
&lt;h3&gt;Git黑名单.gitignore&lt;/h3&gt;
&lt;p&gt;在Git上面有一个叫做黑名单的东西，也就是说每次git的时候，他会自动忽略这些黑名单里的东西。
其中非常典型的就是: node_modules/
因为node_modules里面装的是成千上万个第三方包，体积巨大。而且这些包完全可以通过package.json这个“购物清单”重新下载下来。&lt;/p&gt;
&lt;p&gt;所以改代码的时候如果改了node_modules里面定义好的包，本地是可以看到改变的但是Push上去会被忽略，git会重新下载一个崭新的包，所以你的修改就丢了。&lt;/p&gt;
&lt;p&gt;因此想要修改包的定义，需要把这个文件copy到本地，然后在本地改过之后，用到这个包的地方改一下路径，就可以了。也就是把包私有化。&lt;/p&gt;
&lt;h3&gt;关于@&lt;/h3&gt;
&lt;p&gt;@其实就是一个路径别名，通常在tsconfig.json里面定义，目的就是防止出现巨长的路径名又难改又&lt;strong&gt;丑&lt;/strong&gt;。
而@是前端工具链特有的习惯配置，并不是语言原本的。&lt;/p&gt;
&lt;p&gt;如果想要在一个python项目里面使用类似的技巧，其实你只要项目写的足够规范，比如设置了PYTHONPATH或者通过Pip install -e . 把项目安装为可编辑包，就可以随时随地import了，就是这么任性。&lt;/p&gt;
&lt;h3&gt;关于Tab&lt;/h3&gt;
&lt;p&gt;这个主题的tab很有特色，但是修改的时候要注意匹配关系，主要体现在：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const headings = [
  { depth: 2, slug: &apos;hobbies&apos;, text: &apos;爱好&apos; },
  { depth: 2, slug: &apos;tools&apos;, text: &apos;工具&apos; },
  { depth: 2, slug: &apos;social-networks&apos;, text: &apos;社交&apos; },
  { depth: 2, slug: &apos;recent&apos;, text: &apos;最近在听&apos; },
  { depth: 2, slug: &apos;about-blog&apos;, text: &apos;About Blog&apos; },

]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;此处定义的slug必须和下面使用的一致，并且区分大小写，在修改小标题的时候需要注意，不然会失去目录的动态效果，变成静态目录(~~虽然也挺好看的~~)。&lt;/p&gt;
&lt;hr&gt;</content:encoded><h:img src="/_astro/thumbnail.PAmM8K5J.jpg"/><enclosure url="/_astro/thumbnail.PAmM8K5J.jpg"/></item><item><title>汇编上机考试指北</title><link>https://yingshznrgb.github.io/blog/huibian/hb</link><guid isPermaLink="true">https://yingshznrgb.github.io/blog/huibian/hb</guid><description>由于汇编的特性，上机考看这一篇就够了</description><pubDate>Thu, 18 Dec 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;笔者用六个小时速通了汇编上级考试要点，第二天速通上机题，这里是我和AI一起整理的上级级别的汇编笔记和要点，上机题会这些足够了，汇编考的一般不会太难，都是很简单很基础的题目，一方面现在很多高校计算机专业不再学汇编，另一方面汇编代码无论编程还是调试都很折磨，相关的资料又比较少，上机题考太难有点说不过去。&lt;/p&gt;
&lt;p&gt;首先简单介绍一下一个完整的汇编代码的基本结构：&lt;/p&gt;
&lt;p&gt;一个完整的汇编代码一般由三段组成：数据段、堆栈段和代码段&lt;/p&gt;
&lt;p&gt;而一个&lt;code&gt;SEGMENT&lt;/code&gt; + &lt;code&gt;ENDS&lt;/code&gt;就是一个段&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;;数据段
DATA SEGMENT
  INPUT_BUF   DB 100          ; 最大允许输入 100 个字符
              DB ?            ; DOS 会在这里填入实际长度
              DB 100 DUP(?)   ; 存放字符串的空间
DATA ENDS

;堆栈段
STACK SEGMENT
    db 100 dup(?)
STACK ENDS

;代码段
CODE  SEGMENT

;在主程序开始前需要一个ASSUME字段,ES是可选
    ASSUME CS:CODE,DS:DATA,SS:STACK,ES:DATA


;主程序开始
START:
    ;要先对DS进行初始化，如果用到ES，还需要初始化ES
    MOV AX, DATA
    MOV DS, AX

    ;结束
    MOV AH, 4Ch
    INT 21h
CODE ENDS
END  START
;程序结束

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;其中ASSUME字段需要定义这几个寄存器：&lt;/p&gt;
&lt;p&gt;DS: 数据段寄存器&lt;/p&gt;
&lt;p&gt;SS: 堆栈段寄存器&lt;/p&gt;
&lt;p&gt;CS: 代码段寄存器&lt;/p&gt;
&lt;p&gt;ES: 附加段寄存器（可选）&lt;/p&gt;
&lt;p&gt;下面是一些概念笔记：&lt;/p&gt;
&lt;p&gt;一个主label： &lt;code&gt;START:&lt;/code&gt; + &lt;code&gt;END START&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;一个段：&lt;code&gt;SEGMENT&lt;/code&gt; + &lt;code&gt;ENDS&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;一个函数：&lt;code&gt;CALL&lt;/code&gt; + &lt;code&gt;PRCO&lt;/code&gt; + &lt;code&gt;RET&lt;/code&gt; + &lt;code&gt;ENDP&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;DB: a byte --12H&lt;/p&gt;
&lt;p&gt;DW: a word --1234H&lt;/p&gt;
&lt;p&gt;留空：？&lt;/p&gt;
&lt;p&gt;首先我建议你先一字一句地过一遍下面的内容，然后找几道例题尝试读懂代码，并且我可以负责任地告诉你&lt;strong&gt;最有价值地内容在本文最后&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h1&gt;基础概念&lt;/h1&gt;
&lt;h3&gt;&lt;strong&gt;第一章：寄存器 (Registers)&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;核心概念：寄存器是CPU内部的“口袋”或“草稿纸”，是CPU能直接、高速访问的存储单元。&lt;strong&gt;你的一切操作，几乎都必须通过寄存器来中转。&lt;/strong&gt; 把它们想象成你的双手，内存（RAM）是你的大仓库，你必须先把东西从仓库拿到手上，才能进行加工。&lt;/p&gt;
&lt;p&gt;8086 CPU的寄存器主要分为四类：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1. 通用寄存器 (General Purpose Registers)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;它们都是16位的，但可以拆成两个8位来用。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;AX (Accumulator Register - 累加器)&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;16位&lt;/strong&gt;：&lt;code&gt;AX&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;8位拆分&lt;/strong&gt;：&lt;code&gt;AH&lt;/code&gt; (高8位), &lt;code&gt;AL&lt;/code&gt; (低8位)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;主要用途&lt;/strong&gt;：算术运算的默认“主角”。乘法、除法等很多指令默认就使用&lt;code&gt;AX&lt;/code&gt;或&lt;code&gt;AL&lt;/code&gt;来存放操作数或结果。它是最重要的寄存器，没有之一。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;BX (Base Register - 基址寄存器)&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;16位&lt;/strong&gt;：&lt;code&gt;BX&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;8位拆分&lt;/strong&gt;：&lt;code&gt;BH&lt;/code&gt; (高8位), &lt;code&gt;BL&lt;/code&gt; (低8位)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;主要用途&lt;/strong&gt;：&lt;strong&gt;内存寻址的“指针”&lt;/strong&gt;。当你需要访问内存中某个地址的数据时，经常会把这个地址先放到&lt;code&gt;BX&lt;/code&gt;里。语法是 &lt;code&gt;[BX]&lt;/code&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;CX (Count Register - 计数器)&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;16位&lt;/strong&gt;：&lt;code&gt;CX&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;8位拆分&lt;/strong&gt;：&lt;code&gt;CH&lt;/code&gt; (高8位), &lt;code&gt;CL&lt;/code&gt; (低8位)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;主要用途&lt;/strong&gt;：&lt;strong&gt;天生的循环计数器&lt;/strong&gt;。&lt;code&gt;LOOP&lt;/code&gt;指令会自动使用&lt;code&gt;CX&lt;/code&gt;的值作为循环次数。做循环时，首选&lt;code&gt;CX&lt;/code&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;DX (Data Register - 数据寄存器)&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;16位&lt;/strong&gt;：&lt;code&gt;DX&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;8位拆分&lt;/strong&gt;：&lt;code&gt;DH&lt;/code&gt; (高8位), &lt;code&gt;DL&lt;/code&gt; (低8位)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;主要用途&lt;/strong&gt;：&lt;strong&gt;算术运算的“辅助”和I/O的“信使”&lt;/strong&gt;。
&lt;ul&gt;
&lt;li&gt;在32位乘除法中，&lt;code&gt;DX&lt;/code&gt;与&lt;code&gt;AX&lt;/code&gt;组合成&lt;code&gt;DX:AX&lt;/code&gt;存放结果或被除数。&lt;/li&gt;
&lt;li&gt;在与外部设备（如屏幕、键盘）交互时，&lt;code&gt;DX&lt;/code&gt;常用来存放地址或端口号。&lt;strong&gt;打印字符串时，字符串地址必须在&lt;code&gt;DX&lt;/code&gt;里。&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;2. 指针和变址寄存器 (Pointer &amp;#x26; Index Registers)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;它们主要用于内存寻址和堆栈操作，一般不拆分使用。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;SP (Stack Pointer - 堆栈指针)&lt;/strong&gt;：永远指向&lt;strong&gt;栈顶&lt;/strong&gt;。&lt;code&gt;PUSH&lt;/code&gt;和&lt;code&gt;POP&lt;/code&gt;指令会自动修改它的值。你一般不需要手动修改它。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;BP (Base Pointer - 基址指针)&lt;/strong&gt;：通常用于在堆栈中寻址，寻找传递给子程序的参数。初学阶段可以暂时把它看作一个备用的&lt;code&gt;BX&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SI (Source Index - 源变址寄存器)&lt;/strong&gt;：在字符串操作中，通常指向&lt;strong&gt;源字符串&lt;/strong&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;DI (Destination Index - 目的变址寄存器)&lt;/strong&gt;：在字符串操作中，通常指向&lt;strong&gt;目的字符串&lt;/strong&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;3. 段寄存器 (Segment Registers)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;核心概念&lt;/strong&gt;：8086的内存地址是“段地址:偏移地址”的形式。段寄存器就负责存放“段地址”。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;CS (Code Segment - 代码段)&lt;/strong&gt;：存放当前正在执行的指令的段地址。你不能直接修改它。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;DS (Data Segment - 数据段)&lt;/strong&gt;：存放程序中定义的数据的段地址。&lt;strong&gt;这是最重要的段寄存器！程序一开始必须手动初始化它，否则你无法访问任何变量。&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SS (Stack Segment - 堆栈段)&lt;/strong&gt;：存放堆栈的段地址。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ES (Extra Segment - 附加段)&lt;/strong&gt;：一个备用的数据段寄存器，在字符串操作中常作为目的段。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;4. 标志寄存器 (Flags Register)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;它不是一个单一的寄存器，而是一组记录状态的“开关”（标志位）。你不会直接修改它，但算术和逻辑指令会&lt;strong&gt;自动&lt;/strong&gt;改变它的状态。&lt;strong&gt;条件跳转指令会根据它的状态来决定是否跳转。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;考试必记的几个标志位：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;ZF (Zero Flag - 零标志位)&lt;/strong&gt;：如果一次运算的&lt;strong&gt;结果为0&lt;/strong&gt;，则&lt;code&gt;ZF=1&lt;/code&gt;；否则&lt;code&gt;ZF=0&lt;/code&gt;。
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;JE&lt;/code&gt; (Jump if Equal) 和 &lt;code&gt;JZ&lt;/code&gt; (Jump if Zero) 指令就是看它。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CF (Carry Flag - 进位标志位)&lt;/strong&gt;：
&lt;ul&gt;
&lt;li&gt;在&lt;strong&gt;无符号数&lt;/strong&gt;加法中，如果最高位产生&lt;strong&gt;进位&lt;/strong&gt;，&lt;code&gt;CF=1&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;在&lt;strong&gt;无符号数&lt;/strong&gt;减法中，如果需要&lt;strong&gt;借位&lt;/strong&gt;，&lt;code&gt;CF=1&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;JA&lt;/code&gt; (Jump if Above) 和 &lt;code&gt;JB&lt;/code&gt; (Jump if Below) 看它。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SF (Sign Flag - 符号标志位)&lt;/strong&gt;：如果一次运算的&lt;strong&gt;结果为负数&lt;/strong&gt;（最高位为1），则&lt;code&gt;SF=1&lt;/code&gt;。
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;JG&lt;/code&gt; (Jump if Greater) 和 &lt;code&gt;JL&lt;/code&gt; (Jump if Less) 会参考它。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;OF (Overflow Flag - 溢出标志位)&lt;/strong&gt;：在&lt;strong&gt;带符号数&lt;/strong&gt;运算中，如果结果&lt;strong&gt;超出了范围&lt;/strong&gt;（例如两个正数相加得到一个负数），则&lt;code&gt;OF=1&lt;/code&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;strong&gt;第二章：常用指令与注意事项&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;1. 数据传送指令 &lt;code&gt;MOV&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;格式&lt;/strong&gt;: &lt;code&gt;MOV 目的操作数, 源操作数&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;功能&lt;/strong&gt;: 把“源”的值复制给“目的”。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;注意事项&lt;/strong&gt;:
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;MOV [内存地址1], [内存地址2]&lt;/code&gt; 是绝对非法的！&lt;/strong&gt; 不能直接从内存复制到内存。必须通过寄存器中转。
&lt;ul&gt;
&lt;li&gt;错误: &lt;code&gt;MOV VAR1, VAR2&lt;/code&gt; (如果两者都是变量)&lt;/li&gt;
&lt;li&gt;正确: &lt;code&gt;MOV AX, VAR2&lt;/code&gt; -&gt; &lt;code&gt;MOV VAR1, AX&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;MOV&lt;/code&gt; 指令不影响任何标志位。&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;操作数的&lt;strong&gt;大小必须匹配&lt;/strong&gt;。不能 &lt;code&gt;MOV AX, BL&lt;/code&gt; (16位 vs 8位)。&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;2. 算术运算指令&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;ADD&lt;/code&gt; / &lt;code&gt;SUB&lt;/code&gt; (加 / 减)&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;格式: &lt;code&gt;ADD 目的, 源&lt;/code&gt; (目的 = 目的 + 源)&lt;/li&gt;
&lt;li&gt;注意: 都会影响 &lt;code&gt;ZF&lt;/code&gt;, &lt;code&gt;CF&lt;/code&gt;, &lt;code&gt;SF&lt;/code&gt;, &lt;code&gt;OF&lt;/code&gt; 标志位。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;INC&lt;/code&gt; / &lt;code&gt;DEC&lt;/code&gt; (加一 / 减一)&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;格式: &lt;code&gt;INC 寄存器/内存&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;注意: &lt;strong&gt;不影响&lt;code&gt;CF&lt;/code&gt;进位标志位！&lt;/strong&gt; 这是一个常考的细节。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;MUL&lt;/code&gt; / &lt;code&gt;IMUL&lt;/code&gt; (无符号乘法 / 带符号乘法)&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;格式: &lt;code&gt;MUL 源&lt;/code&gt; (8位或16位)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;规则 (必记)&lt;/strong&gt;:
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;MUL BL&lt;/code&gt; (8位): &lt;code&gt;AX = AL * BL&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;MUL BX&lt;/code&gt; (16位): &lt;code&gt;DX:AX = AX * BX&lt;/code&gt; (结果是32位，高16位在DX)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;IMUL&lt;/code&gt; 规则相同，但处理的是带符号数。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;DIV&lt;/code&gt; / &lt;code&gt;IDIV&lt;/code&gt; (无符号除法 / 带符号除法)&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;格式: &lt;code&gt;DIV 源&lt;/code&gt; (8位或16位)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;规则 (必记)&lt;/strong&gt;:
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;DIV BL&lt;/code&gt; (8位): &lt;code&gt;AX / BL&lt;/code&gt; -&gt; &lt;code&gt;AL&lt;/code&gt;=商, &lt;code&gt;AH&lt;/code&gt;=余数&lt;/li&gt;
&lt;li&gt;&lt;code&gt;DIV BX&lt;/code&gt; (16位): &lt;code&gt;DX:AX / BX&lt;/code&gt; -&gt; &lt;code&gt;AX&lt;/code&gt;=商, &lt;code&gt;DX&lt;/code&gt;=余数&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;注意&lt;/strong&gt;: 做16位除法前，如果被除数只有16位在&lt;code&gt;AX&lt;/code&gt;里，&lt;strong&gt;必须&lt;/strong&gt;先用 &lt;code&gt;CWD&lt;/code&gt; 指令将&lt;code&gt;AX&lt;/code&gt;的符号位扩展到&lt;code&gt;DX&lt;/code&gt;，否则结果会出错！&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;3. 逻辑与移位指令&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;AND&lt;/code&gt;, &lt;code&gt;OR&lt;/code&gt;, &lt;code&gt;XOR&lt;/code&gt; (与, 或, 异或)&lt;/strong&gt;: 主要用于位操作，比如屏蔽某些位。
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;AND AX, 0FH&lt;/code&gt; 会只保留&lt;code&gt;AX&lt;/code&gt;的低4位。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;XOR AX, AX&lt;/code&gt; 是最高效的清零指令。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;SHL&lt;/code&gt; / &lt;code&gt;SHR&lt;/code&gt; (逻辑左移 / 右移)&lt;/strong&gt;: 用于快速乘以2或除以2。移出的位用0补充。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;4. 比较与跳转指令 (程序流程控制的核心！)&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;CMP&lt;/code&gt; (Compare - 比较)&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;格式: &lt;code&gt;CMP 操作数1, 操作数2&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;功能: &lt;strong&gt;执行一个“隐形”的减法 (&lt;code&gt;操作数1 - 操作数2&lt;/code&gt;)&lt;/strong&gt;，但&lt;strong&gt;不保存结果&lt;/strong&gt;，只根据结果&lt;strong&gt;设置标志位&lt;/strong&gt; (&lt;code&gt;ZF&lt;/code&gt;, &lt;code&gt;CF&lt;/code&gt;, &lt;code&gt;SF&lt;/code&gt;, &lt;code&gt;OF&lt;/code&gt;)。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;CMP&lt;/code&gt; 是所有条件跳转的“前戏”。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;条件跳转指令 (Jumps)&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;基于相等/零&lt;/strong&gt;:
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;JE label&lt;/code&gt; / &lt;code&gt;JZ label&lt;/code&gt;: 如果相等/结果为零 (ZF=1)，则跳转。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;JNE label&lt;/code&gt; / &lt;code&gt;JNZ label&lt;/code&gt;: 如果不相等/结果非零 (ZF=0)，则跳转。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;基于无符号数比较 (大于/小于)&lt;/strong&gt;:
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;JA label&lt;/code&gt; (Jump if Above): 如果大于 (CF=0, ZF=0)。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;JB label&lt;/code&gt; (Jump if Below): 如果小于 (CF=1)。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;JAE label&lt;/code&gt; (Above or Equal): 如果大于等于 (CF=0)。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;JBE label&lt;/code&gt; (Below or Equal): 如果小于等于 (CF=1 or ZF=1)。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;基于带符号数比较 (大于/小于)&lt;/strong&gt;:
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;JG label&lt;/code&gt; (Jump if Greater): 如果大于。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;JL label&lt;/code&gt; (Jump if Less): 如果小于。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;JGE label&lt;/code&gt; (Greater or Equal): 如果大于等于。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;JLE label&lt;/code&gt; (Less or Equal): 如果小于等于。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;JMP&lt;/code&gt; (Unconditional Jump - 无条件跳转)&lt;/strong&gt;: &lt;code&gt;JMP label&lt;/code&gt;，直接跳转。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;LOOP&lt;/code&gt; (循环)&lt;/strong&gt;: &lt;code&gt;LOOP label&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;自动执行两步：&lt;code&gt;DEC CX&lt;/code&gt; -&gt; 如果&lt;code&gt;CX&lt;/code&gt;不为0，则&lt;code&gt;JMP label&lt;/code&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;5. 堆栈指令 (Stack Instructions)&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;PUSH 源&lt;/code&gt;&lt;/strong&gt;: 将一个16位的值压入堆栈。&lt;code&gt;SP&lt;/code&gt; 的值会减2。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;POP 目的&lt;/code&gt;&lt;/strong&gt;: 从堆栈顶部弹出一个16位的值。&lt;code&gt;SP&lt;/code&gt; 的值会加2。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;规则&lt;/strong&gt;: 堆栈是&lt;strong&gt;后进先出 (LIFO)&lt;/strong&gt;。&lt;code&gt;POP&lt;/code&gt; 的顺序必须与 &lt;code&gt;PUSH&lt;/code&gt; 的顺序&lt;strong&gt;完全相反&lt;/strong&gt;！
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;PUSH AX&lt;/code&gt; -&gt; &lt;code&gt;PUSH BX&lt;/code&gt; -&gt; &lt;code&gt;POP BX&lt;/code&gt; -&gt; &lt;code&gt;POP AX&lt;/code&gt; (正确)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;PUSH AX&lt;/code&gt; -&gt; &lt;code&gt;PUSH BX&lt;/code&gt; -&gt; &lt;code&gt;POP AX&lt;/code&gt; -&gt; &lt;code&gt;POP BX&lt;/code&gt; (错误！)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;6. 子程序指令 (Procedures)&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;CALL label&lt;/code&gt;&lt;/strong&gt;: 调用子程序。它会做两件事：1. 把下一条指令的地址 &lt;code&gt;PUSH&lt;/code&gt; 到堆栈（以便&lt;code&gt;RET&lt;/code&gt;能回来）。2. &lt;code&gt;JMP&lt;/code&gt; 到 &lt;code&gt;label&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;RET&lt;/code&gt;&lt;/strong&gt;: 从子程序返回。它只做一件事：从堆栈 &lt;code&gt;POP&lt;/code&gt; 出返回地址，然后 &lt;code&gt;JMP&lt;/code&gt; 到那里。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;strong&gt;第三章：DOS &lt;code&gt;INT 21h&lt;/code&gt; 功能调用&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;核心概念&lt;/strong&gt;: &lt;code&gt;INT 21h&lt;/code&gt; 是调用DOS系统功能的“万能钥匙”。具体调用哪个功能，由 &lt;code&gt;AH&lt;/code&gt; 寄存器的值决定。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;考试必背“功能菜单”:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;AH = 01h&lt;/code&gt; - 读取一个字符 (带回显)&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;输入&lt;/strong&gt;: 无&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;输出&lt;/strong&gt;: &lt;code&gt;AL&lt;/code&gt; = 用户输入的字符的ASCII码。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;注意&lt;/strong&gt;: 程序会在这里暂停，等你按下一个键。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;AH = 02h&lt;/code&gt; - 显示一个字符&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;输入&lt;/strong&gt;: &lt;code&gt;DL&lt;/code&gt; = 要显示的字符的ASCII码。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;注意&lt;/strong&gt;: 是&lt;code&gt;DL&lt;/code&gt;，不是&lt;code&gt;AL&lt;/code&gt;！&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;AH = 09h&lt;/code&gt; - 显示一个字符串&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;输入&lt;/strong&gt;: &lt;code&gt;DS:DX&lt;/code&gt; 指向字符串的&lt;strong&gt;起始地址&lt;/strong&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;注意&lt;/strong&gt;: 字符串必须以 &lt;strong&gt;&lt;code&gt;$&lt;/code&gt;&lt;/strong&gt; 符号结尾！&lt;code&gt;$&lt;/code&gt;本身不会被显示。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;AH = 0Ah&lt;/code&gt; - 读取一个字符串&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;输入&lt;/strong&gt;: &lt;code&gt;DS:DX&lt;/code&gt; 指向一个&lt;strong&gt;特殊格式的缓冲区&lt;/strong&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;缓冲区格式&lt;/strong&gt;:
&lt;ul&gt;
&lt;li&gt;第1字节：你定义的最大能容纳的字符数。&lt;/li&gt;
&lt;li&gt;第2字节：留空，DOS会填入&lt;strong&gt;用户实际输入的字符数&lt;/strong&gt;。&lt;/li&gt;
&lt;li&gt;第3字节及以后：留空，DOS会填入用户输入的字符串。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;示例&lt;/strong&gt;: &lt;code&gt;BUFFER DB 20, 0, 20 DUP(0)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;AH = 4Ch&lt;/code&gt; - 终止程序&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;输入&lt;/strong&gt;: &lt;code&gt;AL&lt;/code&gt; 可以是返回码 (通常设为&lt;code&gt;0&lt;/code&gt;)。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;注意&lt;/strong&gt;: 这是&lt;strong&gt;唯一正确&lt;/strong&gt;的程序退出方式！你的程序必须以此结尾。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;strong&gt;第四章：考试策略&lt;/strong&gt;&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;熟记寄存器&lt;/strong&gt;：尤其是&lt;code&gt;AX, BX, CX, DX&lt;/code&gt;的分工和&lt;code&gt;AH/AL&lt;/code&gt;的拆分。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;背熟 &lt;code&gt;INT 21h&lt;/code&gt;&lt;/strong&gt;：特别是&lt;code&gt;01h, 02h, 09h, 0Ah, 4Ch&lt;/code&gt;这五个功能的用法，输入/输出寄存器是什么，有什么特殊要求（比如&lt;code&gt;$&lt;/code&gt;结尾）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;理解 &lt;code&gt;CMP&lt;/code&gt; + &lt;code&gt;Jcc&lt;/code&gt;&lt;/strong&gt;: 这是所有逻辑判断的核心。知道何时用无符号比较（&lt;code&gt;JA/JB&lt;/code&gt;），何时用带符号比较（&lt;code&gt;JG/JL&lt;/code&gt;）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;掌握内存访问&lt;/strong&gt;: 理解 &lt;code&gt;MOV AX, [BX]&lt;/code&gt; 和 &lt;code&gt;MOV AX, BX&lt;/code&gt; 的天壤之别。记住 &lt;code&gt;OFFSET&lt;/code&gt; 操作符是用来获取变量地址的。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;程序框架&lt;/strong&gt;: 记住基本的程序框架结构：段定义 -&gt; &lt;code&gt;ASSUME&lt;/code&gt; -&gt; &lt;code&gt;START:&lt;/code&gt; -&gt; 初始化&lt;code&gt;DS&lt;/code&gt; -&gt; 主逻辑 -&gt; 调用&lt;code&gt;4Ch&lt;/code&gt;退出。&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;p&gt;现在你已经基本了解了汇编的指令，但是想要应付上机考试还不够，你需要切实写几个程序感受一下汇编的独特之处。&lt;/p&gt;
&lt;p&gt;请你用~~比较靠谱的~~ai实现下面这个程序：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;定义X=1234H,读取用户输入的Y=2345H,将相加的结果Z=3579H打印出来&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;:::caution[请注意！！！]
写完的代码请你重点关注这几个部分：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;读取输入的时候关注换行符号（13，10），关注进制转换，关注字符串结尾必须有&apos;$&apos;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;输出的时候关注进制转换，输出方式&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;在程序运行的过程中关注光标的移动
:::&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;接下来让我们仔细研究一下输入和输出：&lt;/p&gt;
&lt;h1&gt;输入和输出&lt;/h1&gt;
&lt;h3&gt;&lt;strong&gt;一、 字符串 (String) 的输入与输出&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;1. 字符串输入 (键盘 -&gt; 内存)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;工具&lt;/strong&gt;: &lt;code&gt;INT 21h, AH = 0Ah&lt;/code&gt; (带缓冲的键盘输入)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;原理&lt;/strong&gt;: 你在内存里准备一个“篮子”，告诉DOS这个篮子有多大，然后DOS会帮你把用户输入的字符（包括最后的回车）装进去，并告诉你实际装了多少个。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;步骤与代码示例&lt;/strong&gt;:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step 1: 在 &lt;code&gt;.DATA&lt;/code&gt; 段定义一个特殊格式的缓冲区&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-assembly&quot;&gt;.DATA
    MAX_LEN     EQU 80      ; 定义一个常量, 表示最大长度, 方便修改
    INPUT_BUFFER DB MAX_LEN, 0, MAX_LEN DUP(0)
    ;           |        |  |
    ;           |        |  `-- 预留 MAX_LEN 个字节的空间, 用0填充
    ;           |        `---- 第2字节, 留空, DOS会填入用户实际输入的字符数
    ;           `--------- 第1字节, 告诉DOS这个缓冲区最多能装多少字符
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Step 2: 在 &lt;code&gt;.CODE&lt;/code&gt; 段调用 &lt;code&gt;0Ah&lt;/code&gt; 功能&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-assembly&quot;&gt;.CODE
    ; ... 初始化 DS ...

    ; 准备调用
    LEA DX, INPUT_BUFFER    ; 把缓冲区的地址放入 DX
    MOV AH, 0Ah             ; 功能号
    INT 21h                 ; 执行. 程序会在这里暂停, 等待用户输入并按回车

    ; --- 输入完成后的处理 (非常重要！) ---
    ; 此时, 用户输入的内容已经存放在 INPUT_BUFFER 中了
    ; 假设用户输入了 &quot;HELLO&quot;

    ; 获取实际长度
    MOV CL, INPUT_BUFFER[1] ; CL = 5 (H-E-L-L-O 的长度)
    MOV CH, 0               ; 现在 CX = 5

    ; 获取字符串内容的起始地址
    LEA SI, INPUT_BUFFER[2] ; SI 指向 &apos;H&apos;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;注意事项&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;0Ah&lt;/code&gt; 功能会自动处理退格键等编辑操作。&lt;/li&gt;
&lt;li&gt;它会把最后那个&lt;strong&gt;回车符 (0Dh)&lt;/strong&gt; 也存入缓冲区，在实际字符串的末尾。如果你要进行精确的字符串比较，记得处理掉这个回车符。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;2. 字符串输出 (内存 -&gt; 屏幕)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;工具&lt;/strong&gt;: &lt;code&gt;INT 21h, AH = 09h&lt;/code&gt; (显示字符串)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;原理&lt;/strong&gt;: 你告诉DOS，你的字符串放在内存的哪个位置，DOS就会从那个位置开始一个一个地显示字符，直到遇到一个特殊的结束标志 &lt;code&gt;$&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;步骤与代码示例&lt;/strong&gt;:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step 1: 在 &lt;code&gt;.DATA&lt;/code&gt; 段定义一个以 &lt;code&gt;$&lt;/code&gt; 结尾的字符串&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-assembly&quot;&gt;.DATA
    WELCOME_MSG DB &apos;Hello, World!$&apos; ; &amp;#x3C;-- 结尾必须是美元符号 &apos;$&apos;
    ANOTHER_MSG DB &apos;This is a test.&apos;, 13, 10, &apos;$&apos; ; 可以包含回车换行
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Step 2: 在 &lt;code&gt;.CODE&lt;/code&gt; 段调用 &lt;code&gt;09h&lt;/code&gt; 功能&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-assembly&quot;&gt;.CODE
    ; ... 初始化 DS ...

    LEA DX, WELCOME_MSG     ; 把要显示的字符串的地址放入 DX
    MOV AH, 09h             ; 功能号
    INT 21h                 ; 执行. 屏幕上会显示 &quot;Hello, World!&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;注意事项&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;$&lt;/code&gt; 符号是&lt;strong&gt;结束标志&lt;/strong&gt;，它本身不会被显示。&lt;/li&gt;
&lt;li&gt;如果你要显示的字符串是刚刚用 &lt;code&gt;0Ah&lt;/code&gt; 读进来的，你需要手动在它的末尾（覆盖掉那个回车符的位置）加上 &lt;code&gt;$&lt;/code&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;strong&gt;二、 单个字符 (Character) 的输入与输出&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;这通常用于菜单选择、简单的交互等。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1. 单个字符输入&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;工具&lt;/strong&gt;: &lt;code&gt;INT 21h, AH = 01h&lt;/code&gt; (读取字符并回显) 或 &lt;code&gt;AH = 07h/08h&lt;/code&gt; (读取字符不回显)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;原理&lt;/strong&gt;: 程序暂停，等待用户按下一个键，然后把这个键的ASCII码返回。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;代码示例&lt;/strong&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-assembly&quot;&gt;.CODE
    MOV AH, 01h     ; 功能号. 01h会把你按的键显示在屏幕上, 07h/08h不会
    INT 21h         ; 执行

    ; --- 输入完成 ---
    ; 用户按下的键的ASCII码现在存储在 AL 寄存器中
    CMP AL, &apos;y&apos;     ; 比如, 比较用户是否按下了 &apos;y&apos; 键
    JE  DO_SOMETHING
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;2. 单个字符输出&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;工具&lt;/strong&gt;: &lt;code&gt;INT 21h, AH = 02h&lt;/code&gt; (显示单个字符)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;原理&lt;/strong&gt;: 你把要显示的字符的ASCII码放入 &lt;code&gt;DL&lt;/code&gt; 寄存器，DOS就会把它显示出来。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;代码示例&lt;/strong&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-assembly&quot;&gt;.CODE
    MOV DL, &apos;A&apos;     ; 把字符 &apos;A&apos; 的ASCII码放入 DL
    MOV AH, 02h     ; 功能号
    INT 21h         ; 执行. 屏幕上会显示一个 &apos;A&apos;

    ; 打印一个数字 (需要先转换成ASCII)
    MOV DL, 5       ; 这是一个纯数字
    ADD DL, &apos;0&apos;     ; DL = 5 + 30h = 35h, 也就是字符 &apos;5&apos; 的ASCII码
    MOV AH, 02h
    INT 21h         ; 执行. 屏幕上会显示一个 &apos;5&apos;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;注意事项&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;记住是 &lt;code&gt;DL&lt;/code&gt; 寄存器，不是 &lt;code&gt;AL&lt;/code&gt; 或 &lt;code&gt;DX&lt;/code&gt;！&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;strong&gt;三、 数字 (Number) 的输入与输出&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;这是最复杂的部分，因为&lt;strong&gt;DOS不能直接读写数字&lt;/strong&gt;，它只认识字符。所以，数字的I/O本质上是&lt;strong&gt;字符串与数字之间的转换&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1. 数字输入 (字符串 -&gt; 数字)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;原理&lt;/strong&gt;: 先用 &lt;code&gt;0Ah&lt;/code&gt; 功能把用户输入的数字当作&lt;strong&gt;字符串&lt;/strong&gt;读进来 (例如 &quot;123&quot;)，然后你自己写算法，把这个字符串转换成一个二进制数 (存入 &lt;code&gt;AX&lt;/code&gt;)。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;算法：“循环累乘法”&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;初始化结果寄存器 &lt;code&gt;AX = 0&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;从字符串的第一个字符开始循环。&lt;/li&gt;
&lt;li&gt;取出一个字符 (例如 &lt;code&gt;&apos;1&apos;&lt;/code&gt;)。&lt;/li&gt;
&lt;li&gt;将字符 &lt;code&gt;&apos;1&apos;&lt;/code&gt; 减去 &lt;code&gt;&apos;0&apos;&lt;/code&gt;，得到纯数字 &lt;code&gt;1&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;将当前结果 &lt;code&gt;AX&lt;/code&gt; 乘以 &lt;code&gt;10&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;将新得到的数字 &lt;code&gt;1&lt;/code&gt; 加到 &lt;code&gt;AX&lt;/code&gt; 上。&lt;/li&gt;
&lt;li&gt;处理下一个字符，重复3-6步。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;代码框架示例&lt;/strong&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-assembly&quot;&gt;; 假设用户输入的 &quot;123&quot; 已经用 0Ah 读入 INPUT_BUFFER
; 并且字符串起始地址在 SI, 长度在 CX

    XOR AX, AX              ; AX = 0 (存放最终结果)
    XOR BX, BX              ; BX 临时存放单个数字
    MOV DI, 10              ; DI = 10 (用于乘法)

CONVERT_LOOP:
    MOV BL, [SI]            ; 取出当前字符, e.g., &apos;1&apos;
    SUB BL, &apos;0&apos;             ; 转换成数字, e.g., 1

    MUL DI                  ; AX = AX * 10
    ADD AX, BX              ; AX = AX + 当前数字

    INC SI
    LOOP CONVERT_LOOP       ; CX 控制循环次数

; 循环结束后, AX 中就存放着转换好的二进制数 123
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;注意&lt;/strong&gt;: 这段代码处理的是&lt;strong&gt;无符号数&lt;/strong&gt;。处理带符号数需要额外检查第一个字符是否是 &lt;code&gt;&apos;-&apos;&lt;/code&gt; 负号。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2. 数字输出 (数字 -&gt; 字符串)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;原理&lt;/strong&gt;: 这是数字输入的逆过程。你自己写算法，把寄存器中的二进制数 (例如 &lt;code&gt;AX = 123&lt;/code&gt;)，转换成字符串 (&lt;code&gt;&quot;123&quot;&lt;/code&gt;)，然后用 &lt;code&gt;09h&lt;/code&gt; (显示字符串) 或 &lt;code&gt;02h&lt;/code&gt; (逐个显示字符) 打印出来。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;算法：“除10取余法”&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;代码框架示例&lt;/strong&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-assembly&quot;&gt;; 假设要打印的数字在 AX 中 (e.g., 123)

    XOR CX, CX              ; CX 作计数器
    MOV BX, 10              ; 除数是 10

DIVIDE_LOOP:
    XOR DX, DX              ; 每次除法前必须清零 DX
    DIV BX                  ; DX:AX / BX -&gt; AX=商, DX=余数

    ADD DL, &apos;0&apos;             ; 将余数转换为ASCII字符
    PUSH DX                 ; 压入堆栈 (顺序会反转)
    INC CX                  ; 计数器加一

    CMP AX, 0               ; 商是否为0?
    JNE DIVIDE_LOOP         ; 不为0则继续

PRINT_LOOP:
    POP DX                  ; 从堆栈中弹出字符 (现在顺序是正确的)
    MOV AH, 02h             ; 用 02h 打印单个字符
    INT 21h
    LOOP PRINT_LOOP         ; CX 控制循环
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;注意&lt;/strong&gt;: 这段代码处理的是&lt;strong&gt;无符号正数&lt;/strong&gt;。处理带符号数需要先检查数字是否为负。如果是，先打印一个 &lt;code&gt;&apos;-&apos;&lt;/code&gt; 负号，然后对原数取反 (&lt;code&gt;NEG AX&lt;/code&gt;)，再执行上面的正数打印逻辑。&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;在这个过程中，你还需要注意的是根据不同的需求，考虑将字符串输入到一个数组还是一个缓冲区中。这很大程度上会影响你后面的代码是否复杂。&lt;/p&gt;
&lt;p&gt;当涉及到不止一个字符串时，就需要用到串处理的相关内容，其中最重要的就是串比较。&lt;/p&gt;
&lt;h1&gt;串比较&lt;/h1&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;strong&gt;一、 普通比较 (&lt;code&gt;CMP&lt;/code&gt;) vs. 串比较 (&lt;code&gt;CMPSB&lt;/code&gt;/&lt;code&gt;CMPSW&lt;/code&gt;)&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;1. 普通比较指令：&lt;code&gt;CMP&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;核心功能&lt;/strong&gt;: 比较&lt;strong&gt;两个单独的&lt;/strong&gt;操作数，可以是&lt;strong&gt;寄存器 vs. 寄存器&lt;/strong&gt;、&lt;strong&gt;寄存器 vs. 内存&lt;/strong&gt;、&lt;strong&gt;内存 vs. 寄存器&lt;/strong&gt;，或&lt;strong&gt;寄存器 vs. 立即数&lt;/strong&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;操作单位&lt;/strong&gt;: 一次比较一个字节 (8位)、一个字 (16位) 或一个双字 (32位，在386+ CPU中)。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;工作原理&lt;/strong&gt;: &lt;code&gt;CMP A, B&lt;/code&gt; 在CPU内部执行 &lt;code&gt;A - B&lt;/code&gt; 的减法，但&lt;strong&gt;不保存结果&lt;/strong&gt;，只根据结果（正、负、零、是否溢出/借位）来&lt;strong&gt;设置标志位&lt;/strong&gt; (&lt;code&gt;ZF&lt;/code&gt;, &lt;code&gt;CF&lt;/code&gt;, &lt;code&gt;SF&lt;/code&gt;, &lt;code&gt;OF&lt;/code&gt;)。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;指针管理&lt;/strong&gt;: &lt;strong&gt;完全手动&lt;/strong&gt;。你需要自己用 &lt;code&gt;INC&lt;/code&gt; 或 &lt;code&gt;ADD&lt;/code&gt; 来移动指针，以便比较数组或字符串中的下一个元素。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;循环&lt;/strong&gt;: &lt;strong&gt;完全手动&lt;/strong&gt;。你需要自己用 &lt;code&gt;DEC&lt;/code&gt; 和 &lt;code&gt;JNZ&lt;/code&gt;/&lt;code&gt;LOOP&lt;/code&gt; 等指令来构建循环。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;CMP&lt;/code&gt; 的应用场景&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;比较单个变量：&lt;code&gt;CMP AX, 0&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;检查循环计数器：&lt;code&gt;CMP CX, 10&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;在手动实现的循环中，比较数组或字符串中的单个元素：
&lt;pre&gt;&lt;code class=&quot;language-assembly&quot;&gt;; 手动比较两个字符串是否相等
MOV SI, OFFSET STR1
MOV DI, OFFSET STR2
MOV CX, LENGTH

    MANUAL_COMPARE_LOOP:
        MOV AL, [SI]
        CMP AL, [DI]        ; &amp;#x3C;-- 使用 CMP 比较单个字节
        JNE NOT_EQUAL       ; 如果不相等, 马上跳出

        INC SI
        INC DI
        LOOP MANUAL_COMPARE_LOOP

        ; 如果循环正常结束, 说明字符串相等
    EQUAL:
        ; ...
    NOT_EQUAL:
        ; ...
    ```

**`CMP` 的优点**: 灵活，可以比较任意来源的操作数。
**`CMP` 的缺点**: 效率低，代码冗长，需要手动管理所有细节。
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;2. 串比较指令：&lt;code&gt;CMPSB&lt;/code&gt; / &lt;code&gt;CMPSW&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;核心功能&lt;/strong&gt;: &lt;strong&gt;专门用于&lt;/strong&gt;比较&lt;strong&gt;内存中&lt;/strong&gt;的两个数据块（字符串或数组）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;操作单位&lt;/strong&gt;: &lt;code&gt;CMPSB&lt;/code&gt; 一次比较一个&lt;strong&gt;字节&lt;/strong&gt; (Byte)。&lt;code&gt;CMPSW&lt;/code&gt; 一次比较一个&lt;strong&gt;字&lt;/strong&gt; (Word)。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;工作原理&lt;/strong&gt;: &lt;code&gt;CMPSB&lt;/code&gt; 在CPU内部执行 &lt;code&gt;DS:[SI] - ES:[DI]&lt;/code&gt; 的减法，同样只设置标志位。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;指针管理&lt;/strong&gt;: &lt;strong&gt;完全自动&lt;/strong&gt;！执行一次 &lt;code&gt;CMPSB&lt;/code&gt; 后，CPU 会&lt;strong&gt;自动&lt;/strong&gt;根据&lt;strong&gt;方向标志位 (DF)&lt;/strong&gt; 来增加或减少 &lt;code&gt;SI&lt;/code&gt; 和 &lt;code&gt;DI&lt;/code&gt;。
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;CLD&lt;/code&gt; 指令 (Clear Direction Flag) -&gt; &lt;code&gt;DF=0&lt;/code&gt; -&gt; &lt;code&gt;SI&lt;/code&gt; 和 &lt;code&gt;DI&lt;/code&gt; &lt;strong&gt;自动递增&lt;/strong&gt; (最常用)。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;STD&lt;/code&gt; 指令 (Set Direction Flag) -&gt; &lt;code&gt;DF=1&lt;/code&gt; -&gt; &lt;code&gt;SI&lt;/code&gt; 和 &lt;code&gt;DI&lt;/code&gt; &lt;strong&gt;自动递减&lt;/strong&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;循环&lt;/strong&gt;: 通常与&lt;strong&gt;重复前缀 (&lt;code&gt;REPxx&lt;/code&gt;)&lt;/strong&gt; 配合使用，形成一个硬件级别的高效循环。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;CMPSB&lt;/code&gt; 的应用场景&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;高效地比较两个字符串或数组是否相等。
&lt;pre&gt;&lt;code class=&quot;language-assembly&quot;&gt;; 使用串比较指令比较两个字符串是否相等
CLD ; &amp;#x3C;&amp;#x3C;&amp;#x3C;--- 关键步骤1: 确保方向是递增
LEA SI, STR1
LEA DI, STR2
MOV CX, LENGTH
    REPE CMPSB          ; &amp;#x3C;&amp;#x3C;&amp;#x3C;--- 关键步骤2: 一行代码搞定循环比较

    ; --- 检查结果 ---
    JE  EQUAL           ; 如果 REPE 是因为 CX=0 结束的, 说明完全相等, (JE/JZ)
    JNE NOT_EQUAL       ; 如果 REPE 是因为中途不相等而结束的
    ```
**串指令的优点**: **速度极快，代码极其简洁**。把手动循环的几行代码压缩成了一行。
**串指令的缺点**: 不够灵活。它只能比较 `DS:[SI]` 和 `ES:[DI]`，操作数来源是固定的。
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;strong&gt;二、 串处理时的注意事项&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;1. 段寄存器 &lt;code&gt;DS&lt;/code&gt; 和 &lt;code&gt;ES&lt;/code&gt; (致命陷阱)&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;串指令的操作数永远是 &lt;code&gt;DS:[SI]&lt;/code&gt; (源) 和 &lt;code&gt;ES:[DI]&lt;/code&gt; (目的)。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;注意&lt;/strong&gt;: 即使你的源和目的字符串都在同一个数据段，你也&lt;strong&gt;必须&lt;/strong&gt;确保 &lt;code&gt;DS&lt;/code&gt; 和 &lt;code&gt;ES&lt;/code&gt; 都正确地指向了这个数据段。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;最佳实践&lt;/strong&gt;: 在程序的开头，总是同时初始化 &lt;code&gt;DS&lt;/code&gt; 和 &lt;code&gt;ES&lt;/code&gt;。
&lt;pre&gt;&lt;code class=&quot;language-assembly&quot;&gt;START:
    MOV AX, DATA
    MOV DS, AX
    MOV ES, AX      ; &amp;#x3C;&amp;#x3C;&amp;#x3C;--- 永远不要忘记这一行！
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;2. 方向标志位 &lt;code&gt;DF&lt;/code&gt; (健壮性关键)&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;DF&lt;/code&gt; 决定了 &lt;code&gt;SI&lt;/code&gt; 和 &lt;code&gt;DI&lt;/code&gt; 是递增还是递减。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;问题&lt;/strong&gt;: DOS 中断 (&lt;code&gt;INT 21h&lt;/code&gt;) 或其他你调用的子程序，&lt;strong&gt;可能会改变 &lt;code&gt;DF&lt;/code&gt; 的状态&lt;/strong&gt;，而不会通知你。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;最佳实践&lt;/strong&gt;: 在每次使用串操作指令&lt;strong&gt;之前&lt;/strong&gt;，都明确地使用 &lt;code&gt;CLD&lt;/code&gt; (清方向标志，递增模式) 或 &lt;code&gt;STD&lt;/code&gt; (置方向标志，递减模式) 来设置你期望的方向。不要假设 &lt;code&gt;DF&lt;/code&gt; 的状态。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-assembly&quot;&gt;; 错误的假设
LEA SI, SRC
LEA DI, DST
MOV CX, LEN
REP MOVSB       ; &amp;#x3C;-- 如果此时 DF=1, 你的复制就会从后往前, 可能导致错误

; 正确的、健壮的做法
CLD             ; &amp;#x3C;&amp;#x3C;&amp;#x3C;--- 明确设置方向
LEA SI, SRC
LEA DI, DST
MOV CX, LEN
REP MOVSB
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;3. 重复前缀 (&lt;code&gt;REPxx&lt;/code&gt;) 与循环&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;REPxx&lt;/code&gt; 是串指令的“涡轮增压器”。它们会自动使用 &lt;code&gt;CX&lt;/code&gt; 作为计数器，在硬件层面实现循环。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;REP&lt;/code&gt;&lt;/strong&gt;: &lt;strong&gt;无条件重复&lt;/strong&gt;。只要 &lt;code&gt;CX &gt; 0&lt;/code&gt; 就一直执行。通常和 &lt;code&gt;MOVSB&lt;/code&gt; (移动字符串) 或 &lt;code&gt;STOSB&lt;/code&gt; (存储字符串) 配合。
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;REP MOVSB&lt;/code&gt;: 复制 &lt;code&gt;CX&lt;/code&gt; 个字节。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;REP STOSB&lt;/code&gt;: 用 &lt;code&gt;AL&lt;/code&gt; 中的值填充 &lt;code&gt;CX&lt;/code&gt; 个字节。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;REPE&lt;/code&gt; / &lt;code&gt;REPZ&lt;/code&gt;&lt;/strong&gt;: &lt;strong&gt;相等/为零则重复&lt;/strong&gt; (Repeat if Equal / Repeat if Zero)。当 &lt;code&gt;CX &gt; 0&lt;/code&gt; &lt;strong&gt;并且&lt;/strong&gt; &lt;code&gt;ZF=1&lt;/code&gt; (上一次比较相等) 时才继续。通常和 &lt;code&gt;CMPSB&lt;/code&gt; 配合。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;REPNE&lt;/code&gt; / &lt;code&gt;REPNZ&lt;/code&gt;&lt;/strong&gt;: &lt;strong&gt;不相等/不为零则重复&lt;/strong&gt; (Repeat if Not Equal / Repeat if Not Zero)。当 &lt;code&gt;CX &gt; 0&lt;/code&gt; &lt;strong&gt;并且&lt;/strong&gt; &lt;code&gt;ZF=0&lt;/code&gt; (上一次比较不相等) 时才继续。通常和 &lt;code&gt;SCASB&lt;/code&gt; (扫描字符串) 配合，用于查找某个特定字符。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;4. 跳转条件：如何判断 &lt;code&gt;REPE CMPSB&lt;/code&gt; 的结果？&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;这是上机考试中逻辑判断的&lt;strong&gt;核心&lt;/strong&gt;。&lt;code&gt;REPE CMPSB&lt;/code&gt; 结束后，有两种可能：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;中途因不匹配而终止&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;CX&lt;/code&gt; 的值 &gt; 0。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;ZF&lt;/code&gt; 标志位 = 0&lt;/strong&gt; (因为最后一次 &lt;code&gt;CMPSB&lt;/code&gt; 的结果是不相等)。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;SI&lt;/code&gt; 和 &lt;code&gt;DI&lt;/code&gt; 指向&lt;strong&gt;第一个不匹配&lt;/strong&gt;的字符的&lt;strong&gt;下一个位置&lt;/strong&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;如何判断&lt;/strong&gt;: 使用 &lt;code&gt;JNE&lt;/code&gt; (Jump if Not Equal) 或 &lt;code&gt;JNZ&lt;/code&gt; (Jump if Not Zero)。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;因 &lt;code&gt;CX&lt;/code&gt; 变成 0 而正常结束&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;CX&lt;/code&gt; 的值 = 0。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;ZF&lt;/code&gt; 标志位 = 1&lt;/strong&gt; (因为每一次 &lt;code&gt;CMPSB&lt;/code&gt; 的结果都是相等)。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;SI&lt;/code&gt; 和 &lt;code&gt;DI&lt;/code&gt; 指向两个字符串的末尾之后。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;如何判断&lt;/strong&gt;: 使用 &lt;code&gt;JE&lt;/code&gt; (Jump if Equal) 或 &lt;code&gt;JZ&lt;/code&gt; (Jump if Zero)。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;经典代码模板&lt;/strong&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-assembly&quot;&gt;    CLD
    LEA SI, STR1
    LEA DI, STR2
    MOV CX, LENGTH

    REPE CMPSB

    ; 现在检查结果
    JE  STRINGS_ARE_EQUAL   ; 如果跳转, 说明两个字符串完全一样

    ; 如果程序执行到这里, 说明中途不匹配
    JMP STRINGS_ARE_DIFFERENT

STRINGS_ARE_EQUAL:
    ; ... 处理相等的情况 ...
    JMP NEXT_STEP

STRINGS_ARE_DIFFERENT:
    ; ... 处理不相等的情况 ...

NEXT_STEP:
    ; ...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;总结&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;用 &lt;code&gt;CMP&lt;/code&gt;，你就是“工人”，需要自己搬砖、计数、判断。&lt;/li&gt;
&lt;li&gt;用 &lt;code&gt;CMPSB&lt;/code&gt; + &lt;code&gt;REPE&lt;/code&gt;，你就是“老板”，只需要下达一个命令，CPU这个“自动化机器人”就会帮你完成所有工作。&lt;/li&gt;
&lt;li&gt;使用串指令前，永远记住**“三板斧”**：
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;初始化 &lt;code&gt;DS&lt;/code&gt; 和 &lt;code&gt;ES&lt;/code&gt;&lt;/strong&gt; (在程序开头)。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;设置方向 &lt;code&gt;CLD&lt;/code&gt;/&lt;code&gt;STD&lt;/code&gt;&lt;/strong&gt; (在指令前)。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;设置计数器 &lt;code&gt;CX&lt;/code&gt;&lt;/strong&gt; (在指令前)。&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;REPE CMPSB&lt;/code&gt; 结束后，用 &lt;code&gt;JE&lt;/code&gt;/&lt;code&gt;JNE&lt;/code&gt; 来判断最终结果。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;到现在你又学习了一些知识，又到了实践的环节，请你自己给自己设计一道题目，并尝试独立完成。如果遇到问题和ai交流。（并不是笔者偷懒不想写了）&lt;/p&gt;
&lt;p&gt;最后查漏补缺一下&lt;/p&gt;
&lt;h1&gt;查漏补缺&lt;/h1&gt;
&lt;hr&gt;
&lt;p&gt;下面是学有余力，可以关注的在考试中&lt;strong&gt;可能出现&lt;/strong&gt;的知识点。&lt;/p&gt;
&lt;h4&gt;1. 更深入的算术运算 (有符号数 vs 无符号数)&lt;/h4&gt;
&lt;p&gt;在一般的题目中主要用 &lt;code&gt;ADD&lt;/code&gt;/&lt;code&gt;SUB&lt;/code&gt; 操作地址，但考试可能专门考数值计算。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;MUL&lt;/code&gt; vs &lt;code&gt;IMUL&lt;/code&gt; (乘法)&lt;/strong&gt; / &lt;strong&gt;&lt;code&gt;DIV&lt;/code&gt; vs &lt;code&gt;IDIV&lt;/code&gt; (除法)&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;区别&lt;/strong&gt;: 前者处理&lt;strong&gt;无符号数&lt;/strong&gt;，后者处理&lt;strong&gt;带符号数 (Integer)&lt;/strong&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;陷阱 (必考！)&lt;/strong&gt;: &lt;code&gt;DIV&lt;/code&gt;/&lt;code&gt;IDIV&lt;/code&gt; 的被除数是 &lt;code&gt;DX:AX&lt;/code&gt; (32位)。如果你的被除数只有16位在&lt;code&gt;AX&lt;/code&gt;里：
&lt;ul&gt;
&lt;li&gt;做无符号除法 &lt;code&gt;DIV&lt;/code&gt; 前，必须 &lt;code&gt;XOR DX, DX&lt;/code&gt; (手动将&lt;code&gt;DX&lt;/code&gt;清零)。&lt;/li&gt;
&lt;li&gt;做带符号除法 &lt;code&gt;IDIV&lt;/code&gt; 前，必须用 &lt;code&gt;CWD&lt;/code&gt; 指令 (将&lt;code&gt;AX&lt;/code&gt;的符号位自动扩展到&lt;code&gt;DX&lt;/code&gt;)。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;忘记这一步，结果几乎肯定是错的！&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;ADC&lt;/code&gt; / &lt;code&gt;SBB&lt;/code&gt; (带进/借位的加减法)&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;功能&lt;/strong&gt;: &lt;code&gt;ADC AX, BX&lt;/code&gt; 的意思是 &lt;code&gt;AX = AX + BX + CF&lt;/code&gt; (CF是进位标志位)。&lt;code&gt;SBB&lt;/code&gt; 同理。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;考点&lt;/strong&gt;: 当你需要做&lt;strong&gt;超过16位的加减法&lt;/strong&gt;时（比如两个32位数相加），必须使用它们。
&lt;pre&gt;&lt;code class=&quot;language-assembly&quot;&gt;; 计算 [DX:AX] + [CX:BX] -&gt; 结果存入 [DX:AX]
ADD AX, BX  ; 先加低16位, 这可能会产生一个进位(CF=1)
ADC DX, CX  ; 再加高16位, 同时把刚才的进位也加上
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;2. 位运算 (Bitwise Operations)&lt;/h4&gt;
&lt;p&gt;这是汇编的特色，常用于状态判断、数据加密或硬件控制（很小概率会考）。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;AND&lt;/code&gt;, &lt;code&gt;OR&lt;/code&gt;, &lt;code&gt;XOR&lt;/code&gt;, &lt;code&gt;NOT&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;AND&lt;/code&gt;: 主要用于“屏蔽”或“清零”某些位。&lt;code&gt;AND AL, 0FH&lt;/code&gt; 会只保留&lt;code&gt;AL&lt;/code&gt;的低4位。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;XOR&lt;/code&gt;: &lt;code&gt;XOR AX, AX&lt;/code&gt; 是最高效的清零方法。也用于翻转某些位。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;OR&lt;/code&gt;: 主要用于“设置”某些位。&lt;code&gt;OR AL, 80H&lt;/code&gt; 会将&lt;code&gt;AL&lt;/code&gt;的最高位置1。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;NOT&lt;/code&gt;: 翻转所有位（0变1，1变0）。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;TEST&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;功能&lt;/strong&gt;: 和 &lt;code&gt;AND&lt;/code&gt; 一样执行“与”运算，但&lt;strong&gt;不保存结果&lt;/strong&gt;，只设置标志位。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;考点&lt;/strong&gt;: &lt;strong&gt;不破坏操作数&lt;/strong&gt;的情况下检查某些位。
&lt;pre&gt;&lt;code class=&quot;language-assembly&quot;&gt;TEST AL, 01H  ; 检查 AL 的最低位是否为1 (判断奇偶)
JNZ IS_ODD    ; 如果结果不为0 (ZF=0), 说明最低位是1, 是奇数
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;SHL&lt;/code&gt;/&lt;code&gt;SHR&lt;/code&gt; (逻辑移位)&lt;/strong&gt; &amp;#x26; &lt;strong&gt;&lt;code&gt;SAL&lt;/code&gt;/&lt;code&gt;SAR&lt;/code&gt; (算术移位)&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;SHL&lt;/code&gt;/&lt;code&gt;SAL&lt;/code&gt;&lt;/strong&gt;: 左移，最低位补0。&lt;code&gt;SHL AX, 1&lt;/code&gt; 等价于 &lt;code&gt;AX = AX * 2&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;SHR&lt;/code&gt;&lt;/strong&gt;: 逻辑右移，最高位补0。用于&lt;strong&gt;无符号数&lt;/strong&gt;的快速除法。&lt;code&gt;SHR AX, 1&lt;/code&gt; 等价于 &lt;code&gt;AX = AX / 2&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;SAR&lt;/code&gt;&lt;/strong&gt;: 算术右移，最高位用&lt;strong&gt;原符号位&lt;/strong&gt;填充。用于&lt;strong&gt;带符号数&lt;/strong&gt;的快速除法。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;考点&lt;/strong&gt;: 区分 &lt;code&gt;SHR&lt;/code&gt; 和 &lt;code&gt;SAR&lt;/code&gt; 的不同应用场景。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;3. 堆栈的进阶用法 (参数传递)&lt;/h4&gt;
&lt;p&gt;用堆栈来保护寄存器了是必须会的，但考试也可能会考用堆栈来传递参数。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;原理&lt;/strong&gt;: 主程序在 &lt;code&gt;CALL&lt;/code&gt; 子程序之前，先把参数 &lt;code&gt;PUSH&lt;/code&gt; 进堆栈。子程序内部通过 &lt;code&gt;BP&lt;/code&gt; 寄存器来访问这些参数。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-assembly&quot;&gt;; 主程序
MOV AX, 5
PUSH AX       ; 压入参数
CALL MY_SUB
ADD SP, 2     ; 调用结束后要清理堆栈！

; 子程序
MY_SUB PROC
    PUSH BP       ; 保护旧的BP
    MOV BP, SP    ; 让 BP 指向当前的栈顶

    ; 现在可以通过 BP 来访问参数
    ; [BP]   存的是旧的 BP
    ; [BP+2] 存的是返回地址
    ; [BP+4] 存的是我们压入的参数 5
    MOV AX, [BP+4] ; AX = 5

    POP BP        ; 恢复旧的BP
    RET
MY_SUB ENDP
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这个稍微复杂，但如果考到，会是拉开差距的题目。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h1&gt;最后&lt;/h1&gt;
&lt;p&gt;最后附一些常用的子程序模板，如果你的老师允许携带电子材料，或者有机会使用U盘配置电脑环境（至少我们是这样），这个必不可少。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;; ============================================
; 子程序：打印换行
; ============================================
PRINT_NEWLINE PROC
    PUSH AX
    PUSH DX

    MOV DL, 0Dh
    MOV AH, 02h
    INT 21h
    MOV DL, 0Ah
    INT 21h

    POP DX
    POP AX
    RET
PRINT_NEWLINE ENDP
; ========================================================================
; 子程序名称: ATOI (ASCII String to Integer)
; 功能: 将字符串转换为 16 位有符号整数
;
; 输入:
;   注意：获取位置要使用LEA而不是MOV
;   DS:SI = 指向字符串的首地址 (例如: &quot;123&quot;, &quot;-45&quot;, &quot;12a&quot;)
;
; 输出:
;   AX = 转换后的整数结果 (例如: 123, -45)
;   SI = 指向停止转换的那个字符 (例如 &apos;a&apos; 或结束符)
;
; 寄存器影响:
;   AX 被修改用于存放结果，其他寄存器 (BX, CX, DX, DI) 自动保存恢复
; ========================================================================
ATOI PROC NEAR
    PUSH BX
    PUSH CX
    PUSH DX
    PUSH DI             ; 用于保存符号标志 (0=正, 1=负)

    XOR BX, BX          ; BX 用于存放最终数值
    XOR CX, CX          ; CX 用于临时存放当前位数字
    XOR DI, DI          ; DI 清零，默认为正数

    ; --- 1. 处理符号位 ---
    MOV AL, [SI]        ; 读取第一个字符
    CMP AL, &apos;-&apos;         ; 是负号吗？
    JNE CHECK_PLUS      ; 不是负号，检查是不是正号
    INC DI              ; 标记为负数 (DI=1)
    INC SI              ; 指针移向下一位
    JMP PROCESS_DIGIT   ; 开始处理数字

CHECK_PLUS:
    CMP AL, &apos;+&apos;         ; 是正号吗？
    JNE PROCESS_DIGIT   ; 也不是，说明直接是数字，开始处理
    INC SI              ; 是正号，跳过，指针移向下一位

    ; --- 2. 循环处理数字位 ---
PROCESS_DIGIT:
    MOV AL, [SI]        ; 读取当前字符

    ; 校验字符是否在 &apos;0&apos;~&apos;9&apos; 之间
    CMP AL, &apos;0&apos;
    JB FINISH_CONVERT   ; 小于 &apos;0&apos; (非数字)，结束
    CMP AL, &apos;9&apos;
    JA FINISH_CONVERT   ; 大于 &apos;9&apos; (非数字)，结束

    SUB AL, &apos;0&apos;         ; ASCII 转 数值 (例如 &apos;3&apos; -&gt; 3)
    MOV CL, AL          ; 暂存在 CL 中 (因为 AX 要用来做乘法)

    ; 核心公式: Result = Result * 10 + Current_Digit
    MOV AX, BX          ; 把当前的 Result 放入 AX
    MOV DX, 10
    MUL DX              ; AX = AX * 10 (结果在 DX:AX，假设不溢出只看 AX)

    ADD AX, CX          ; AX = AX + 当前位
    MOV BX, AX          ; 结果存回 BX

    INC SI              ; 移动到下一个字符
    JMP PROCESS_DIGIT   ; 继续循环

    ; --- 3. 结束处理与符号调整 ---
FINISH_CONVERT:
    MOV AX, BX          ; 将结果放入 AX 准备返回

    CMP DI, 1           ; 检查刚才是不是负数
    JNE ATOI_EXIT       ; 如果不是，直接退出
    NEG AX              ; 如果是负数，取补码 (变为负值)

ATOI_EXIT:
    POP DI
    POP DX
    POP CX
    POP BX
    RET
ATOI ENDP

; ============================================
; 有符号数打印子程序
; 输入：AX (16位有符号整数)

;如果需要对8位符号数扩展到16符号数，使用 CBW (Convert Byte to Word)。
;作用：它检查 AL 的最高位（符号位）。如果 AL 是负的，它自动把 AH 全填成 1（FF）；如果 AL 是正的，它自动把 AH 清零（00）。
;结果：AX 就变成了数值相等的 16 位数。

; ============================================

PRINT_SIGNED_16 PROC NEAR
    PUSH AX
    PUSH DX

    ; --- 1. 判断正负 ---
    CMP AX, 0           ; 和 0 比较
    JGE P_POSITIVE      ; 如果 &gt;= 0，直接打印

    ; --- 2. 如果是负数 ---
    PUSH AX             ; 保护 AX
    MOV DL, &apos;-&apos;         ; 准备打印负号
    MOV AH, 02h
    INT 21h             ; 输出 &apos;-&apos;
    POP AX              ; 恢复 AX

    NEG AX              ; 【关键】取反，把 -5 变成 5，方便后面除法

P_POSITIVE:
    CALL PRINT_NUM      ; 调用基础的数字打印函数(打印绝对值)

    POP DX
    POP AX
    RET
PRINT_SIGNED_16 ENDP

; ============================================
; PRINT_NUM: 打印 AX 中的非负整数（最多5位或更多，视AX大小）
;将寄存器 AX 中的数值（无符号数），转换成对应的十进制字符（ASCII码），并输出到屏幕上。
; ============================================
PRINT_NUM PROC
    PUSH AX
    PUSH BX
    PUSH CX
    PUSH DX

    XOR CX, CX        ; 位计数
    MOV BX, 10        ; 除数 10

    ; 处理 AX==0 的特殊情况
    CMP AX, 0
    JNE PN_DIV_LOOP
    ; 如果 AX == 0, 直接打印 &apos;0&apos;
    MOV DL, &apos;0&apos;
    MOV AH, 02h
    INT 21h
    JMP PN_DONE

PN_DIV_LOOP:
    ; 循环：用 DX:AX / BX (16-bit 除法)
    ; 每次将余数(DX)压栈，直到 AX==0（商为0）
DIV_LOOP_PN:
    XOR DX, DX        ; 清除高位，准备 16-bit 除法
    DIV BX            ; AX / BX -&gt; AX=quotient, DX=remainder
    PUSH DX           ; 保存 remainder（0..9）
    INC CX
    CMP AX, 0
    JNE DIV_LOOP_PN

    ; 弹出并打印余数（高位先被压入，故弹出时顺序正确）
PRINT_LOOP_PN:
    POP DX
    ADD DL, &apos;0&apos;
    MOV AH, 02h
    INT 21h
    LOOP PRINT_LOOP_PN

PN_DONE:
    POP DX
    POP CX
    POP BX
    POP AX
    RET
PRINT_NUM ENDP
; ============================================
; 子程序：打印换行
; ============================================
PRINT_NEWLINE PROC
    PUSH AX
    PUSH DX

    MOV DL, 0Dh
    MOV AH, 02h
    INT 21h
    MOV DL, 0Ah
    INT 21h

    POP DX
    POP AX
    RET
PRINT_NEWLINE ENDP
========================================================================
; 子程序名称: ATOI (ASCII String to Integer)
; 功能: 将字符串转换为 16 位有符号整数，这里的ATOI转化为的符号数是补码
;
; 输入:
;   注意：获取位置要使用LEA而不是MOV
;   DS:SI = 指向字符串的首地址 (例如: &quot;123&quot;, &quot;-45&quot;, &quot;12a&quot;)
;
; 输出:
;   AX = 转换后的整数结果 (例如: 123, -45)
;   SI = 指向停止转换的那个字符 (例如 &apos;a&apos; 或结束符)
;
; 寄存器影响:
;   AX 被修改用于存放结果，其他寄存器 (BX, CX, DX, DI) 自动保存恢复
; ========================================================================
ATOI PROC NEAR
    PUSH BX
    PUSH CX
    PUSH DX
    PUSH DI             ; 用于保存符号标志 (0=正, 1=负)

    XOR BX, BX          ; BX 用于存放最终数值
    XOR CX, CX          ; CX 用于临时存放当前位数字
    XOR DI, DI          ; DI 清零，默认为正数

    ; --- 1. 处理符号位 ---
    MOV AL, [SI]        ; 读取第一个字符
    CMP AL, &apos;-&apos;         ; 是负号吗？
    JNE CHECK_PLUS      ; 不是负号，检查是不是正号
    INC DI              ; 标记为负数 (DI=1)
    INC SI              ; 指针移向下一位
    JMP PROCESS_DIGIT   ; 开始处理数字

CHECK_PLUS:
    CMP AL, &apos;+&apos;         ; 是正号吗？
    JNE PROCESS_DIGIT   ; 也不是，说明直接是数字，开始处理
    INC SI              ; 是正号，跳过，指针移向下一位

    ; --- 2. 循环处理数字位 ---
PROCESS_DIGIT:
    MOV AL, [SI]        ; 读取当前字符

    ; 校验字符是否在 &apos;0&apos;~&apos;9&apos; 之间
    CMP AL, &apos;0&apos;
    JB FINISH_CONVERT   ; 小于 &apos;0&apos; (非数字)，结束
    CMP AL, &apos;9&apos;
    JA FINISH_CONVERT   ; 大于 &apos;9&apos; (非数字)，结束

    SUB AL, &apos;0&apos;         ; ASCII 转 数值 (例如 &apos;3&apos; -&gt; 3)
    MOV CL, AL          ; 暂存在 CL 中 (因为 AX 要用来做乘法)

    ; 核心公式: Result = Result * 10 + Current_Digit
    MOV AX, BX          ; 把当前的 Result 放入 AX
    MOV DX, 10
    MUL DX              ; AX = AX * 10 (结果在 DX:AX，假设不溢出只看 AX)

    ADD AX, CX          ; AX = AX + 当前位
    MOV BX, AX          ; 结果存回 BX

    INC SI              ; 移动到下一个字符
    JMP PROCESS_DIGIT   ; 继续循环

    ; --- 3. 结束处理与符号调整 ---
FINISH_CONVERT:
    MOV AX, BX          ; 将结果放入 AX 准备返回

    CMP DI, 1           ; 检查刚才是不是负数
    JNE ATOI_EXIT       ; 如果不是，直接退出
    NEG AX              ; 如果是负数，取补码 (变为负值)

ATOI_EXIT:
    POP DI
    POP DX
    POP CX
    POP BX
    RET
ATOI ENDP
; =====================================
; 标准输入转十进制
; 假设 SI 指向缓冲区首地址
; BX 用于存放最终的十进制数值结果
; ====================================
MOV BX, 0       ; 结果清零
MOV CX, 10      ; 准备乘数 10 (0Ah)

NEXT_DIGIT:
    MOV AL, [SI]    ; 取一个字符
    INC SI          ; 指针后移

    ; --- 1. 校验是否结束 ---
    CMP AL, &apos;0&apos;
    JB FINISH       ; 小于 &apos;0&apos; 不是数字，结束
    CMP AL, &apos;9&apos;
    JA FINISH       ; 大于 &apos;9&apos; 不是数字，结束

    ; --- 2. 核心算法：转换 ---
    SUB AL, 30H     ; 【修正点】减去 30H，而不是 40H
    MOV AH, 0       ; 为了不干扰后面加法，把高位清零，现在 AX 就是那个个位数

    ; --- 3. 核心算法：位权 (Result * 10) ---
    PUSH AX         ; 暂时保存当前的个位数

    MOV AX, BX      ; 把之前的总结果拿来
    MUL CX          ; AX = AX * 10 (注意：结果可能溢出到 DX，这里假设数字不大)
    MOV BX, AX      ; 乘完的结果放回 BX

    POP AX          ; 取回刚才那个个位数

    ; --- 4. 核心算法：累加 (+ Current) ---
    ADD BX, AX      ; result = result * 10 + digit

    JMP NEXT_DIGIT  ; 继续处理下一个字符

FINISH:
    ; 此时 BX 中存储的就是 10 进制数值，可以用于 CMP 比较了

; ============================================
; 有符号数打印子程序
; 输入：AX (16位有符号整数)

;如果需要对8位符号数扩展到16符号数，使用 CBW (Convert Byte to Word)。
;作用：它检查 AL 的最高位（符号位）。如果 AL 是负的，它自动把 AH 全填成 1（FF）；如果 AL 是正的，它自动把 AH 清零（00）。
;结果：AX 就变成了数值相等的 16 位数。

; ============================================

PRINT_SIGNED_16 PROC NEAR
    PUSH AX
    PUSH DX

    ; --- 1. 判断正负 ---
    CMP AX, 0           ; 和 0 比较
    JGE P_POSITIVE      ; 如果 &gt;= 0，直接打印

    ; --- 2. 如果是负数 ---
    PUSH AX             ; 保护 AX
    MOV DL, &apos;-&apos;         ; 准备打印负号
    MOV AH, 02h
    INT 21h             ; 输出 &apos;-&apos;
    POP AX              ; 恢复 AX

    NEG AX              ; 【关键】取反，把 -5 变成 5，方便后面除法

P_POSITIVE:
    CALL PRINT_NUM      ; 调用基础的数字打印函数(打印绝对值)

    POP DX
    POP AX
    RET
PRINT_SIGNED_16 ENDP

; ============================================
; PRINT_NUM: 打印 AX 中的非负整数（最多5位或更多，视AX大小）
;将寄存器 AX 中的数值（无符号数），转换成对应的十进制字符（ASCII码），并输出到屏幕上。
; ============================================
PRINT_NUM PROC
    PUSH AX
    PUSH BX
    PUSH CX
    PUSH DX

    XOR CX, CX        ; 位计数
    MOV BX, 10        ; 除数 10

    ; 处理 AX==0 的特殊情况
    CMP AX, 0
    JNE PN_DIV_LOOP
    ; 如果 AX == 0, 直接打印 &apos;0&apos;
    MOV DL, &apos;0&apos;
    MOV AH, 02h
    INT 21h
    JMP PN_DONE

PN_DIV_LOOP:
    ; 循环：用 DX:AX / BX (16-bit 除法)
    ; 每次将余数(DX)压栈，直到 AX==0（商为0）
DIV_LOOP_PN:
    XOR DX, DX        ; 清除高位，准备 16-bit 除法
    DIV BX            ; AX / BX -&gt; AX=quotient, DX=remainder
    PUSH DX           ; 保存 remainder（0..9）
    INC CX
    CMP AX, 0
    JNE DIV_LOOP_PN

    ; 弹出并打印余数（高位先被压入，故弹出时顺序正确）
PRINT_LOOP_PN:
    POP DX
    ADD DL, &apos;0&apos;
    MOV AH, 02h
    INT 21h
    LOOP PRINT_LOOP_PN

PN_DONE:
    POP DX
    POP CX
    POP BX
    POP AX
    RET
PRINT_NUM ENDP

=========================================================================
; 子程序: HEXSTR_TO_NUM
; 功能:   将一个十六进制字符串转换为一个16位二进制数
; 输入:   DS:SI - 指向字符串的开头
;         CX    - 字符串的长度
; 输出:   BX    - 转换后的数字
; =========================================================================
HEXSTR_TO_NUM PROC
    PUSH AX
    PUSH CX
    PUSH SI

    XOR BX, BX              ; 结果清零 (BX = 0)
CONVERT_LOOP:
    CMP CX, 0               ; 检查是否所有字符都已处理
    JE CONVERT_DONE         ; 如果是, 则完成

    MOV AL, [SI]            ; 取一个字符

    ; --- 核心转换逻辑: 将 &apos;0&apos;-&apos;9&apos;, &apos;A&apos;-&apos;F&apos;, &apos;a&apos;-&apos;f&apos; 转换为数字 0-15 ---
    CMP AL, &apos;9&apos;
    JBE IS_DIGIT
    CMP AL, &apos;F&apos;
    JBE IS_UPPER_HEX
    CMP AL, &apos;f&apos;
    JBE IS_LOWER_HEX
    JMP INVALID_CHAR        ; 如果不是有效十六进制字符, 跳过

IS_DIGIT:
    SUB AL, &apos;0&apos;             ; &apos;0&apos;..&apos;9&apos; -&gt; 0..9
    JMP ACCUMULATE

IS_UPPER_HEX:
    SUB AL, &apos;A&apos;             ; &apos;A&apos;..&apos;F&apos; -&gt; 0..5
    ADD AL, 10              ; 0..5 -&gt; 10..15
    JMP ACCUMULATE

IS_LOWER_HEX:
    SUB AL, &apos;a&apos;             ; &apos;a&apos;..&apos;f&apos; -&gt; 0..5
    ADD AL, 10              ; 0..5 -&gt; 10..15

ACCUMULATE:
    ; --- 核心累加算法: result = result * 16 + digit ---
    PUSH AX                 ; 保存当前转换出的数字 (0-15)

    MOV AX, BX              ; 把之前的总结果拿来
    MOV DX, 16              ; 乘以 16
    MUL DX                  ; AX = AX * 16
    MOV BX, AX              ; 更新总结果

    POP AX                  ; 取回刚才的数字
    MOV AH, 0               ; 清零高位, 因为 AL 中是 0-15
    ADD BX, AX              ; 加上当前位的值

INVALID_CHAR:
    INC SI
    DEC CX
    JMP CONVERT_LOOP

CONVERT_DONE:
    POP SI
    POP CX
    POP AX
    RET
HEXSTR_TO_NUM ENDP

=========================================================================
; 子程序: PRINT_HEX_NUM (你之前的 BTOH 子程序)
; 功能:   将 AX 中的16位数作为4位十六进制数直接打印到屏幕
; 输入:   AX - 要转换的数字
; 输出:   无 (直接在屏幕显示结果)
; =========================================================================
PRINT_HEX_NUM PROC
    PUSH AX
    PUSH CX
    PUSH DX

    MOV BX, AX              ; 把它移到 BX, 因为 ROL BX, CL 更方便
    MOV CX, 4               ; 16/4, 处理四次
ROTATE:
    MOV CL, 4               ; 每次旋转4位
    ROL BX, CL              ; 循环左移四位
    MOV AL, BL              ; 取低8位
    AND AL, 0Fh             ; 只取低4位
    ADD AL, &apos;0&apos;             ; 转换为数字字符
    CMP AL, &apos;9&apos;
    JBE  PRINT_CHAR
    ADD AL, 7               ; 修正为字母
PRINT_CHAR:
    MOV DL, AL
    MOV AH, 02h
    INT 21H

    DEC CH
    JNZ ROTATE

    POP DX
    POP CX
    POP AX
    RET
PRINT_HEX_NUM ENDP

==========================================================
; 子程序：TO_UPPER
; 功能：将 AL 中的字符转为大写
; 原理：AND AL, 11011111B (0DFH) -&gt; 将第6位强制置0
; 注意：会自动忽略非小写字母
; ==========================================================
TO_UPPER PROC NEAR
    CMP AL, &apos;a&apos;         ; 小于 &apos;a&apos; 不是小写字母
    JB  UPPER_EXIT
    CMP AL, &apos;z&apos;         ; 大于 &apos;z&apos; 不是小写字母
    JA  UPPER_EXIT

    ; --- 核心指令 ---
    AND AL, 11011111B   ; 也就是 AND AL, 0DFH
    ; ----------------

UPPER_EXIT:
    RET
TO_UPPER ENDP

; ==========================================================
; 子程序：TO_LOWER
; 功能：将 AL 中的字符转为小写
; 原理：OR AL, 00100000B (20H) -&gt; 将第6位强制置1
; 注意：会自动忽略非大写字母
; ==========================================================
TO_LOWER PROC NEAR
    CMP AL, &apos;A&apos;         ; 小于 &apos;A&apos; 不是大写字母
    JB  LOWER_EXIT
    CMP AL, &apos;Z&apos;         ; 大于 &apos;Z&apos; 不是大写字母
    JA  LOWER_EXIT

    ; --- 核心指令 ---
    OR  AL, 00100000B   ; 也就是 OR AL, 20H
    ; ----------------

LOWER_EXIT:
    RET
TO_LOWER ENDP

&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;</content:encoded><h:img src="/_astro/thumbnail.DHSrvF1Q.jpg"/><enclosure url="/_astro/thumbnail.DHSrvF1Q.jpg"/></item><item><title>Markdown 语法支持</title><link>https://yingshznrgb.github.io/blog/markdown-zh</link><guid isPermaLink="true">https://yingshznrgb.github.io/blog/markdown-zh</guid><description>Markdown 是一种轻量级的「标记语言」。</description><pubDate>Wed, 26 Jul 2023 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;基本语法&lt;/h2&gt;
&lt;p&gt;Markdown 是一种轻量级且易于使用的语法，用于为您的写作设计风格。&lt;/p&gt;
&lt;h3&gt;标题&lt;/h3&gt;
&lt;p&gt;文章内容较多时，可以用标题分段：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-markdown&quot;&gt;# 标题 1

## 标题 2

## 大标题

### 小标题
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;标题预览会打乱文章的结构，所以在此不展示。&lt;/p&gt;
&lt;h3&gt;粗斜体&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-markdown&quot;&gt;_斜体文本_

**粗体文本**

**_粗斜体文本_**
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;预览：&lt;/p&gt;
&lt;p&gt;&lt;em&gt;斜体文本&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;粗体文本&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;粗斜体文本&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;链接&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-markdown&quot;&gt;文字链接 [链接名称](http://链接网址)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;预览：&lt;/p&gt;
&lt;p&gt;文字链接 &lt;a href=&quot;http://%E9%93%BE%E6%8E%A5%E7%BD%91%E5%9D%80&quot;&gt;链接名称&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;行内代码&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-markdown&quot;&gt;这是一条 `单行代码`
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;预览：&lt;/p&gt;
&lt;p&gt;这是一条 &lt;code&gt;行内代码&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;代码块&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-markdown&quot;&gt;```js
// calculate fibonacci
function fibonacci(n) {
  if (n &amp;#x3C;= 1) return 1
  return fibonacci(n - 1) + fibonacci(n - 2)
}
```
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;预览：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-js&quot;&gt;// calculate fibonacci
function fibonacci(n) {
  if (n &amp;#x3C;= 1) return 1
  return fibonacci(n - 1) + fibonacci(n - 2)
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;当前使用 shiki 作为代码高亮插件，支持的语言请参考 &lt;a href=&quot;https://shiki.matsu.io/languages.html&quot;&gt;shiki / languages&lt;/a&gt;。&lt;/p&gt;
&lt;h3&gt;行内公式&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-markdown&quot;&gt;这是一条行内公式 $e^{i\pi} + 1 = 0$
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;预览：&lt;/p&gt;
&lt;p&gt;这是一条行内公式 $e^{i\pi} + 1 = 0$&lt;/p&gt;
&lt;h3&gt;公式块&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-markdown&quot;&gt;$$
\hat{f}(\xi) = \int_{-\infty}^{\infty} f(x) e^{-2\pi i x \xi} \, dx
$$
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;预览：&lt;/p&gt;
&lt;p&gt;$$
\hat{f}(\xi) = \int_{-\infty}^{\infty} f(x) e^{-2\pi i x \xi} , dx
$$&lt;/p&gt;
&lt;p&gt;当前使用 KaTeX 作为数学公式插件，支持的语法请参考 &lt;a href=&quot;https://katex.org/docs/supported.html&quot;&gt;KaTeX Supported Functions&lt;/a&gt;。&lt;/p&gt;
&lt;h4&gt;图片&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-markdown&quot;&gt;![CWorld](https://cravatar.cn/avatar/1ffe42aa45a6b1444a786b1f32dfa8aa?s=200)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;预览：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cravatar.cn/avatar/1ffe42aa45a6b1444a786b1f32dfa8aa?s=200&quot; alt=&quot;CWorld&quot;&gt;&lt;/p&gt;
&lt;h4&gt;删除线&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-markdown&quot;&gt;~~删除线~~
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;预览：&lt;/p&gt;
&lt;p&gt;~~删除线~~&lt;/p&gt;
&lt;h3&gt;列表&lt;/h3&gt;
&lt;p&gt;普通无序列表&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-markdown&quot;&gt;- 1
- 2
- 3
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;预览：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;1&lt;/li&gt;
&lt;li&gt;2&lt;/li&gt;
&lt;li&gt;3&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;普通有序列表&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-markdown&quot;&gt;1. GPT-4
2. Claude Opus
3. LLaMa
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;预览：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;GPT-4&lt;/li&gt;
&lt;li&gt;Claude Opus&lt;/li&gt;
&lt;li&gt;LLaMa&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;列表里可以继续嵌套语法&lt;/p&gt;
&lt;h3&gt;引用&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-markdown&quot;&gt;&gt; 枪响，雷鸣，剑起。繁花血景。
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;预览：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;枪响，雷鸣，剑起。繁花血景。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;引用里也可以继续嵌套语法。&lt;/p&gt;
&lt;h3&gt;换行&lt;/h3&gt;
&lt;p&gt;markdown 分段落是需要空一行的。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-markdown&quot;&gt;如果不空行
就会在一段

第一段

第二段
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;预览：&lt;/p&gt;
&lt;p&gt;如果不空行
就会在一段&lt;/p&gt;
&lt;p&gt;第一段&lt;/p&gt;
&lt;p&gt;第二段&lt;/p&gt;
&lt;h3&gt;分隔符&lt;/h3&gt;
&lt;p&gt;如果你有写分割线的习惯，可以新起一行输入三个减号&lt;code&gt;---&lt;/code&gt; 或者星号 &lt;code&gt;***&lt;/code&gt;。当前后都有段落时，请空出一行：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-markdown&quot;&gt;---
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;预览：&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;高级技巧&lt;/h2&gt;
&lt;h3&gt;行内 HTML 元素&lt;/h3&gt;
&lt;p&gt;目前只支持部分段内 HTML 元素效果，包括 &lt;code&gt;&amp;#x3C;kdb&gt; &amp;#x3C;b&gt; &amp;#x3C;i&gt; &amp;#x3C;em&gt; &amp;#x3C;sup&gt; &amp;#x3C;sub&gt; &amp;#x3C;br&gt;&lt;/code&gt; ，如&lt;/p&gt;
&lt;h4&gt;键位显示&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-markdown&quot;&gt;使用 &amp;#x3C;kbd&gt;Ctrl&amp;#x3C;/kbd&gt; + &amp;#x3C;kbd&gt;Alt&amp;#x3C;/kbd&gt; + &amp;#x3C;kbd&gt;Del&amp;#x3C;/kbd&gt; 重启电脑
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;预览：&lt;/p&gt;
&lt;p&gt;使用 Ctrl + Alt + Del 重启电脑&lt;/p&gt;
&lt;h4&gt;粗斜体&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-markdown&quot;&gt;&amp;#x3C;b&gt; Markdown 在此处同样适用，如 _加粗_ &amp;#x3C;/b&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;预览：&lt;/p&gt;
&lt;p&gt; Markdown 在此处同样适用，如 &lt;em&gt;加粗&lt;/em&gt; &lt;/p&gt;
&lt;h3&gt;其他 HTML 写法&lt;/h3&gt;
&lt;h4&gt;折叠块&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-markdown&quot;&gt;&amp;#x3C;details&gt;&amp;#x3C;summary&gt;点击展开&amp;#x3C;/summary&gt;它被隐藏了&amp;#x3C;/details&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;预览：&lt;/p&gt;
&lt;h3&gt;表格&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-markdown&quot;&gt;| 表头1 | 表头2 |
| ----- | ----- |
| 内容1 | 内容2 |
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;预览：&lt;/p&gt;
&lt;p&gt;| 表头1 | 表头2 |
| ----- | ----- |
| 内容1 | 内容2 |&lt;/p&gt;
&lt;h3&gt;注释&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-markdown&quot;&gt;在引用的地方使用 [^注释] 来添加注释。

然后在文档的结尾，添加注释的内容（会默认于文章结尾渲染之）。

[^注释]: 这里是注释的内容
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;预览：&lt;/p&gt;
&lt;p&gt;在引用的地方使用 &lt;a href=&quot;%E8%BF%99%E9%87%8C%E6%98%AF%E6%B3%A8%E9%87%8A%E7%9A%84%E5%86%85%E5%AE%B9&quot;&gt;^注释&lt;/a&gt; 来添加注释。&lt;/p&gt;
&lt;p&gt;然后在文档的结尾，添加注释的内容（会默认于文章结尾渲染之）。&lt;/p&gt;
&lt;h3&gt;To-Do 列表&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-markdown&quot;&gt;- [ ] 未完成的任务
- [x] 已完成的任务
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;预览：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;[ ] 未完成的任务&lt;/li&gt;
&lt;li&gt;[x] 已完成的任务&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;符号转义&lt;/h3&gt;
&lt;p&gt;如果你的描述中需要用到 markdown 的符号，比如 _ # * 等，但又不想它被转义，这时候可以在这些符号前加反斜杠，如 &lt;code&gt;\_&lt;/code&gt; &lt;code&gt;\#&lt;/code&gt; &lt;code&gt;\*&lt;/code&gt; 进行避免。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-markdown&quot;&gt;\_不想这里的文本变斜体\_

\*\*不想这里的文本被加粗\*\*
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;预览：&lt;/p&gt;
&lt;p&gt;_不想这里的文本变斜体_&lt;/p&gt;
&lt;p&gt;**不想这里的文本被加粗**&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;我编写的Aside&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;:::tip[aaa]
这是一个tip
:::

:::note
这是一个note
:::

:::caution
这是一个caution
:::


:::danger
这是一个danger
:::

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;预览：
:::tip[aaa]
这是一个aaa
:::&lt;/p&gt;
&lt;p&gt;:::note
这是一个note
:::&lt;/p&gt;
&lt;p&gt;:::caution
这是一个caution
:::&lt;/p&gt;
&lt;p&gt;:::danger
这是一个danger
:::&lt;/p&gt;
&lt;h2&gt;内嵌 Astro 组件&lt;/h2&gt;
&lt;p&gt;See &lt;a href=&quot;/docs/integrations/components&quot;&gt;User Components&lt;/a&gt; and &lt;a href=&quot;/docs/integrations/advanced&quot;&gt;Advanced Components&lt;/a&gt; for details.&lt;/p&gt;</content:encoded><h:img src="/_astro/thumbnail.HAXFr_hw.jpg"/><enclosure url="/_astro/thumbnail.HAXFr_hw.jpg"/></item><item><title>我的个人博客建站历程</title><link>https://yingshznrgb.github.io/blog/build-blog/build-blog</link><guid isPermaLink="true">https://yingshznrgb.github.io/blog/build-blog/build-blog</guid><description>此站的来源</description><pubDate>Sun, 14 Dec 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;起因是笔者看到某大佬的个人博客大受震撼，想要搭一个自己的博客，将学习过程记录以方便读者（~~如果有~~）借鉴（笔者在此之前是完全没学过前端，只会写一点点html和css, js基本不会，纯小白了也算是）&lt;/p&gt;
&lt;h2&gt;框架选择&lt;/h2&gt;
&lt;p&gt;目前主流框架有三个：Hexo、Astro、Hugo&lt;/p&gt;
&lt;p&gt;一句话：小白选Hexo、会前端选Astro，~~M属性选Hugo~~。&lt;/p&gt;
&lt;p&gt;借鉴这篇文章：https://zhuanlan.zhihu.com/p/1981456864127522296&lt;/p&gt;
&lt;p&gt;官方网址：&lt;/p&gt;
&lt;p&gt;Hexo:https://hexo.io/zh-cn/&lt;/p&gt;
&lt;p&gt;Astro:https://docs.astro.build/zh-cn/getting-started/&lt;/p&gt;
&lt;p&gt;Hugo：https://gohugo.io/&lt;/p&gt;
&lt;p&gt;我选择了Astro，然后找了一个主题感觉不错先用着：&lt;/p&gt;
&lt;p&gt;https://github.com/cworld1/astro-theme-pure&lt;/p&gt;
&lt;p&gt;教程：&lt;/p&gt;
&lt;p&gt;https://astro-pure.js.org/docs&lt;/p&gt;
&lt;p&gt;https://docs.astro.build/en/install-and-setup/#use-a-theme-or-starter-template&lt;/p&gt;
&lt;h2&gt;本地部署：&lt;/h2&gt;
&lt;p&gt;Node 版本：v20&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;D:\Camel\Blog&gt;node --version
v20.15.1
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;安装vscode扩展&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;image.png&quot; alt=&quot;alt text&quot;&gt;&lt;/p&gt;
&lt;p&gt;把代码clone一下：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;image-1.png&quot; alt=&quot;alt text&quot;&gt;&lt;/p&gt;
&lt;p&gt;然后：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;npm install //安装所有依赖
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;因为有报错所以尝试用pnpm安装：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;npm install -g pnpm
pnpm install
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;最后用测试命令运行：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;pnpm run dev
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;image-2.png&quot; alt=&quot;alt text&quot;&gt;&lt;/p&gt;
&lt;p&gt;然后就跑起来啦！&lt;/p&gt;
&lt;p&gt;后面Blog的具体搭建就是自己慢慢学习和测试的过程喽（欢呼）。&lt;/p&gt;
&lt;h2&gt;挂到github pages上：&lt;/h2&gt;
&lt;p&gt;先搞一个最简单的试一下，后面再尝试vercel等等&lt;/p&gt;
&lt;p&gt;强烈建议先在本地调试！！！调试到没有错误再挂github&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;pnpm run build
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;因为这个主题项目本身是挂在vercel上的，所以要先卸载一些相关的包和修改一些配置。&lt;/p&gt;
&lt;p&gt;先在github上新建一个空仓库，命名必须是：用户名.github.io
&lt;img src=&quot;image-3.png&quot; alt=&quot;alt text&quot;&gt;
在根目录新建.github文件夹（已有的话直接下一步）
在.github下面新建workflows文件夹
在workflows文件夹下面新建deploy.yml文件，放下面内容（这是适配 pnpm 的自动部署脚本）：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;name: Deploy to GitHub Pages

on:
  push:
    branches: [ main ]
  workflow_dispatch:

permissions:
  contents: read
  pages: write
  id-token: write

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout your repository using git
        uses: actions/checkout@v4
      
      - name: Install, build, and upload your site
        uses: withastro/action@v2
        with:
            package-manager: pnpm

  deploy:
    needs: build
    runs-on: ubuntu-latest
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}
    steps:
      - name: Deploy to GitHub Pages
        id: deployment
        uses: actions/deploy-pages@v4
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然后
&lt;img src=&quot;image-4.png&quot; alt=&quot;alt text&quot;&gt;&lt;/p&gt;
&lt;p&gt;回到github，setting，Pages，选择Github Actions（因为刚才配置了deloy.yml文件）
&lt;img src=&quot;image-5.png&quot; alt=&quot;alt text&quot;&gt;&lt;/p&gt;
&lt;p&gt;然后点击前往Action界面：
报错：
&lt;img src=&quot;image-6.png&quot; alt=&quot;alt text&quot;&gt;
说是GitHub 正在尝试用 Jekyll（一种老旧的博客生成器）来构建你的网站，而不是用 Astro&lt;/p&gt;
&lt;p&gt;在public文件夹下新建文件.nojeky11&lt;/p&gt;
&lt;p&gt;然后重新git add - push&lt;/p&gt;
&lt;p&gt;报错：
&lt;img src=&quot;image-7.png&quot; alt=&quot;alt text&quot;&gt;
原因：我的 astro.config.ts 配置文件里写了一句代码引用了 @astrojs/markdown-remark 这个工具，但是你的 package.json（依赖列表）里并没有安装它。&lt;/p&gt;
&lt;p&gt;于是：pnpm add -D @astrojs/markdown-remark&lt;/p&gt;
&lt;p&gt;然后重新git add - push&lt;/p&gt;
&lt;p&gt;然后又报错...&lt;/p&gt;
&lt;p&gt;一系列调试之后，终于本地调通了😭😭：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;image-8.png&quot; alt=&quot;alt text&quot;&gt;
但是github依旧报错...&lt;/p&gt;
&lt;p&gt;长达一个小时的调试，终于调通了（释然）。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;image-9.png&quot; alt=&quot;alt text&quot;&gt;&lt;/p&gt;
&lt;h2&gt;挂到vercel:&lt;/h2&gt;
&lt;p&gt;创建账号：continue with github
选择项目，import即可。&lt;/p&gt;
&lt;h3&gt;配置waline:&lt;/h3&gt;
&lt;p&gt;第一阶段：准备数据库 (LeanCloud)&lt;/p&gt;
&lt;p&gt;需要一个免费的地方存数据。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;打开 LeanCloud 国际版 并注册账号。
(选国际版是因为不需要域名备案，省事)&lt;/li&gt;
&lt;li&gt;点击 创建应用，名字随便填（比如 MyBlogComments），点击创建。&lt;/li&gt;
&lt;li&gt;进入刚才创建的应用，点击左侧菜单的 设置 (Settings) -&gt; 应用凭证 (App Keys)。&lt;/li&gt;
&lt;li&gt;停在这个页面别动，一会儿我们要复制这里的 AppID、AppKey 和 MasterKey。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;第二阶段：部署评论服务 (Vercel)&lt;/p&gt;
&lt;p&gt;我们需要在 Vercel 上运行一个 Waline 程序来帮我们管理评论。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;点击这个链接一键部署 Waline。&lt;/li&gt;
&lt;li&gt;Vercel 会跳出来让你创建新项目：&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;Repository Name: 随便填，比如 my-waline。&lt;/li&gt;
&lt;li&gt;点击 Create。&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;最关键的一步（配置环境变量）：
你会看到一个叫 Environment Variables 的折叠框，点开它，把你刚才在 LeanCloud 里看到的三个值填进去：&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;LEAN_ID 👉 粘贴 LeanCloud 的 AppID&lt;/li&gt;
&lt;li&gt;LEAN_KEY 👉 粘贴 LeanCloud 的 AppKey&lt;/li&gt;
&lt;li&gt;LEAN_MASTER_KEY 👉 粘贴 LeanCloud 的 MasterKey&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start=&quot;4&quot;&gt;
&lt;li&gt;点击底部的 Deploy 按钮。
等待几分钟，部署成功后，点击 Continue to Dashboard。
你会获得一个类似 https://my-waline.vercel.app 的网址。复制这个网址！这就是你的评论服务器地址。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;第三阶段：连接到博客
回到 VS Code：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;打开 src/site.config.ts。&lt;/li&gt;
&lt;li&gt;找到 waline 配置块。&lt;/li&gt;
&lt;li&gt;修改两处：&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code&gt;waline: {
enable: true, // 1. 开启评论
server: &apos;https://my-waline.vercel.app&apos;, // 2. 换成刚才复制的那个新网址// ...其他保持不变
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;提交代码并推送&lt;/p&gt;
&lt;h3&gt;管理waline:&lt;/h3&gt;
&lt;p&gt;第一个在评论区注册的人会成为管理员。还可以输入wailne地址/ui访问。&lt;/p&gt;
&lt;h2&gt;其他平台选择&lt;/h2&gt;
&lt;p&gt;Github pages:https://docs.github.com/en/pages/quickstart&lt;/p&gt;
&lt;p&gt;vercel:https://zhuanlan.zhihu.com/p/641263373&lt;/p&gt;
&lt;p&gt;cloudflare pages:https://dash.cloudflare.com/487b19a8595082c8ae72aa2d1a2706a1/home/domains&lt;/p&gt;
&lt;p&gt;绑定域名：https://xue6ing.cn/archives/1705394947292&lt;/p&gt;
&lt;p&gt;eu.org免费域名：https://xue6ing.cn/archives/free-yu-ming-yao-bu-yao&lt;/p&gt;
&lt;p&gt;[图片]&lt;/p&gt;
&lt;h2&gt;ps&lt;/h2&gt;
&lt;p&gt;astro一些主题：
https://astro-pure.js.org/docs&lt;/p&gt;
&lt;p&gt;https://d-sketon.github.io/astro-theme-reimu/&lt;/p&gt;
&lt;hr&gt;</content:encoded><h:img src="/_astro/thumbnail.GjSQuYEm.jpg"/><enclosure url="/_astro/thumbnail.GjSQuYEm.jpg"/></item><item><title>Using MDX</title><link>https://yingshznrgb.github.io/blog/using-mdx</link><guid isPermaLink="true">https://yingshznrgb.github.io/blog/using-mdx</guid><description>Learning how to use MDX in Astro</description><pubDate>Sun, 01 Jun 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;This theme comes with the &lt;a href=&quot;https://docs.astro.build/en/guides/integrations-guide/mdx/&quot;&gt;@astrojs/mdx&lt;/a&gt; integration installed and configured in your &lt;code&gt;astro.config.ts&lt;/code&gt; config file. If you prefer not to use MDX, you can disable support by removing the integration from your config file.&lt;/p&gt;
&lt;h2&gt;Why MDX?&lt;/h2&gt;
&lt;p&gt;MDX is a special flavor of Markdown that supports embedded JavaScript &amp;#x26; JSX syntax. This unlocks the ability to &lt;a href=&quot;https://docs.astro.build/en/guides/markdown-content/#mdx-features&quot;&gt;mix JavaScript and UI Components into your Markdown content&lt;/a&gt; for things like interactive charts or alerts.&lt;/p&gt;
&lt;p&gt;If you have existing content authored in MDX, this integration will hopefully make migrating to Astro a breeze.&lt;/p&gt;
&lt;h2&gt;Example&lt;/h2&gt;
&lt;p&gt;Here is how you import and use a UI component inside of MDX.&lt;br&gt;
When you open this page in the browser, you should see the clickable button below.&lt;/p&gt;
&lt;p&gt;import { Button } from &apos;astro-pure/user&apos;&lt;/p&gt;
&lt;p&gt;Click Me&lt;/p&gt;
&lt;h2&gt;More Links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://mdxjs.com/docs/what-is-mdx&quot;&gt;MDX Syntax Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.astro.build/en/guides/markdown-content/#markdown-and-mdx-pages&quot;&gt;Astro Usage Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Note:&lt;/strong&gt; &lt;a href=&quot;https://docs.astro.build/en/reference/directives-reference/#client-directives&quot;&gt;Client Directives&lt;/a&gt; are still required to create interactive components. Otherwise, all components in your MDX will render as static HTML (no JavaScript) by default.&lt;/li&gt;
&lt;/ul&gt;</content:encoded><h:img src="undefined"/><enclosure url="undefined"/></item></channel></rss>