x86 汇编入门(06):文件读写
程序不能只跟终端打交道。配置文件、日志、数据文件——都离不开文件 I/O。这一篇用 06_file_io.asm 完成「写入 → 关闭 → 重新打开 → 读取 → 输出」全流程,也是本系列的收官之作。 这是「x86 汇编入门」系列的第 6 篇,也是最后一篇。前五篇覆盖了输出、输入、算术、循环和函数。这一篇综合运用文件相关系统调用,并回顾整个系列的学习路径。 一、文件相关系统调用 调用号 名称 作用 2 sys_open 打开或创建文件 0 sys_read 从 fd 读取 1 sys_write 向 fd 写入 3 sys_close 关闭 fd sys_open 参数: 寄存器 含义 rdi 文件路径(以 \0 结尾的 C 字符串) rsi 打开标志 flags rdx 权限 mode(创建文件时有效) 返回值 rax 文件描述符;失败时为负数 常用 flags(可位或组合): 标志 值 含义 O_RDONLY 0 只读 O_WRONLY 1 只写 O_CREAT 0x40 不存在则创建...
x86 汇编入门(05):函数调用与递归阶乘
call 和 ret 是汇编里最重要的「接力棒」。没有它们,代码只能从上到下一条道走到黑。这一篇我们拆开函数调用的完整机制,并用递归计算 5 的阶乘——在汇编里亲眼看到栈是怎么一层层长高的。 这是「x86 汇编入门」系列的第 5 篇。上一篇用跳转实现了循环。这一篇通过 05_function.asm,理解 call / ret、栈帧和 x86_64 调用约定。 一、call 和 ret 做了什么?123call factorial ; ① 把「下一条指令地址」压栈 ② 跳到 factorial...ret ; 从栈弹出地址,跳回去 可以把它想成:call 留下回城坐标,ret 按坐标回去。栈就是存放这些坐标的地方。 二、栈帧:函数自己的「工作台」每次进入函数,标准开场是: 12345678factorial: push rbp ; 保存调用者的帧指针 mov rbp, rsp ; 建立当前帧 push rbx ; 保存要用的 callee...
大模型数学速成(02):矩阵乘法——神经网络的基本变换
上一篇我们约定:列 = token,形状 [768, 1024] 表示 768 维特征 × 1024 个 token。接下来几乎所有 Transformer 层都在做同一件事——矩阵乘法:对每个 token 的特征向量做线性变换。 这一篇搞懂 $y = W \cdot x + b$ 在算什么、「握手规则」为什么必须成立,并用 3 维 × 2 token 的手算例子建立直觉。Q/K/V 三次投影留到下一篇。 这是「大模型数学速成」系列的第 2 篇。建议先读 第 01 篇:张量、维度与「列 = token」。下一篇讲 Q/K/V 投影——同一输入,三种角色。 一、一句话概括矩阵乘法 = 对每个 token 的特征向量做一次线性变换(旋转 + 拉伸 + 平移),把信息从一个「语义空间」映射到另一个「语义空间」。 神经网络里一层线性层,本质上就是一次矩阵乘法加偏置;堆叠多层非线性激活,才形成复杂的表达能力。 二、生活类比:调咖啡1234567输入向量 x = [咖啡豆量, 水量, 奶量] ← ...
x86 汇编入门(04):循环与条件跳转
高级语言里写 for (i = 1; i <= 10; i++) 一行搞定。汇编里没有 for,只有比较 + 跳转。这一篇用 04_loop.asm 打印 1 到 10,把循环拆成你能看见的每一步。 这是「x86 汇编入门」系列的第 4 篇。上一篇实现了算术和数字打印。这一篇通过 04_loop.asm,学习条件跳转指令和循环结构的汇编写法。 一、比较与跳转cmp a, b 做减法但不保存结果,只设置 CPU 标志位。然后根据标志位跳转: 指令 条件 je 相等 (ZF=1) jne 不相等 jl 小于(有符号) jle 小于等于 jg 大于 jge 大于等于 jmp 无条件跳转 二、用跳转拼出循环04_loop.asm 的逻辑等价于: 123for (int i = 1; i <= 10; i++) { printf("当前数字: %d\n", i);} 汇编实现: 1234567891011121314mov r12, 1 ...
大模型数学速成(01):张量、维度与「列 = token」
你在文档里看到 [768, 1024],第一反应可能是:768 是行还是列?1024 是 token 数还是特征维?PyTorch 教程写 [batch, seq, hidden],推理引擎源码写 [n_embd, n_tokens]——同一套数据,括号顺序不同,读错维度后面所有公式都会对不上。 这一篇只解决一件事:在本系列采用的约定下,张量形状怎么读、矩阵图怎么画、常见运算后维度怎么变。 搞懂它,后面矩阵乘法、Q/K/V 投影才有共同语言。 这是「大模型数学速成」系列的第 1 篇。建议先读 第 00 篇:读 Transformer 前需要哪些数学?。下一篇我们讲 矩阵乘法——神经网络的「基本变换器」。 一、什么是张量?在深度学习里,张量(tensor) 就是存放数字的多维数组。维度越高,结构越丰富,但读法有统一套路: 维度 生活类比 大模型中的例子 1D 向量 一行成绩:[语文, 数学, 英语, …] 某一个 token 的 768 维 embedding 2D 矩阵 Excel 表格 [n_embd, n_tokens] 整段序列的...
现代 C++ 实战(04):智能指针(上)——所有权与 RAII
上一篇我们搞懂了移动语义——资源可以在对象之间「搬家」。但还有一个更根本的问题:这块内存到底谁负责释放? C++ 没有垃圾回收,手动 new / delete 一旦配对出错,就是泄漏或 double-free。 现代 C++ 的答案是 RAII + 智能指针:把所有权写进类型系统,让编译器和析构函数帮你收尾。这一篇聚焦 unique_ptr 与 shared_ptr 的上半场——独占 vs 共享、什么时候该用谁、以及 make_unique / make_shared 为什么更推荐。 这是「现代 C++ 实战」系列的第 4 篇。对应 demo:ref/cpp_demo/smart_pointers/ 第 01–04 节。建议先读 第 03 篇:移动语义与右值引用。 一、RAII:资源获取即初始化RAII(Resource Acquisition Is Initialization) 是 C++ 资源管理的核心惯用法: 阶段 做什么 构造 获取资源(内存、文件句柄、锁……) 使用 通过对象访问资源 析构 自动释放资源——无论正常返回还...
x86 汇编入门(03):算术运算与数字转字符串
终端只能显示字符,不能直接显示数字 42。所以汇编里做算术只是第一步,更麻烦的是把结果「翻译」成 '4' 和 '2' 再送出去。这一篇我们练四则运算,并实现一个可复用的 print_number 子程序。 这是「x86 汇编入门」系列的第 3 篇。前两篇解决了输出字符串和读取输入。这一篇通过 03_calc.asm,掌握算术指令和整数转 ASCII 的核心技巧。 一、基本算术指令对两个常数 42 和 8 演示四则运算: 指令 含义 示例结果 add dst, src 加法 42 + 8 = 50 sub dst, src 减法 42 - 8 = 34 imul dst, src 有符号乘法 42 × 8 = 336 idiv src 有符号除法 42 ÷ 8 = 5 … 2 除法要特别注意:idiv 用 rdx:rax 作为被除数。执行前需要 cqo 把 rax 符号扩展到 rdx: 1234mov rax, num_acqo ...
大模型数学速成(00):读 Transformer 前需要哪些数学?
你可能已经读过「Attention Is All You Need」的科普版,知道 Transformer 靠「注意力」连接 token;也可能看过 LLM 是「预测下一个词」的接龙游戏。但一旦打开技术文章或论文,公式里突然出现 $QK^\top$、LayerNorm、RoPE、KV Cache——矩阵维度对不上、符号各说各话,读几段就想关掉页面。 这一篇不讲任何具体公式,只回答一件事:接下来 11 篇数学速成,各自解决什么困惑、该怎么读。 把它当成进入 Transformer 计算世界的地图。 这是「大模型数学速成」系列的第 0 篇。本系列与「现代 C++ 实战」并行日更:同一天还会有一篇 C++ 文章,两线互不干扰。下一篇我们从最基础的约定说起——张量、维度,以及为什么「列 = token」。 一、为什么需要这个系列?「小白讲 AI」系列刻意零公式:用图书馆、接龙、投票来类比 Transformer 和 LLM,降低入门门槛。那套讲法足够建立直觉,但不足以回答下面这类问题: 困惑 典型场景 $Q \cdot K^\top$ 到底在算什么? 读论文...
现代 C++ 实战(03):移动语义与右值引用
上一篇我们把 C++ 版本地图铺好了。C++11 里有一项改动,几乎改变了整个语言写高性能代码的方式:移动语义(Move Semantics)。很多人第一次遇到 std::move 和 T&& 时会困惑:「这到底是在拷贝还是在移动?」 这一篇我们拆开来看:左值 / 右值是什么、std::move 做了什么、移动构造如何省掉深拷贝,并带你跑 right_ref_demo demo。 这是「现代 C++ 实战」系列的第 3 篇。对应 demo:ref/cpp_demo/basics/right_ref_demo/。建议先读 第 02 篇:C++ 版本演进一览。 一、为什么需要移动语义?想象你在搬家:把书从旧书架搬到新书架,有两种做法: 做法 类比 C++ 中的对应 复印 把每本书复印一份放到新家,旧家原件还在 拷贝构造——两份独立数据 直接搬 把书整箱抬走,旧书架空了 移动构造——资源所有权转移 对 std::string、std::vector 这类在堆上持有大块内存的类型,深拷贝意味着: 分配同等大小的新内存 逐字节复制内容...
x86 汇编入门(02):读取用户输入
上一篇程序只会「说」,不会「听」。真实程序几乎都要处理输入——命令行参数、用户键入、网络数据,本质都是往缓冲区里塞字节。这一篇我们学 sys_read,并认识汇编里的第三个地盘:.bss 段。 这是「x86 汇编入门」系列的第 2 篇。上一篇用 sys_write 输出了 Hello World。这一篇通过 02_input.asm,实现读取键盘输入并回显。 一、三段式内存布局到本篇为止,汇编程序的「地盘」凑齐了: 段 用途 类比 .data 已初始化的常量(字符串、数字) 写死在程序里的便签 .bss 未初始化的变量(缓冲区) 运行时用的空白草稿纸 .text 可执行指令 操作步骤 .bss 里的空间在程序加载时自动清零,用 resb N 预留 N 个字节: 12section .bss name_buf resb 64 ; 预留 64 字节缓冲区 二、sys_read 怎么用?sys_read 是 sys_write 的镜像操作: 寄存器 含义 rax 0(调用号) rdi 文件描述符(0 = st...










