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...
大模型数学速成(05):注意力机制与 Softmax
上一篇我们有了 Norm 与残差;第 03 篇我们算出了 Q、K、V。现在进入 Transformer 的核心:每个 token 用 Q 去「查询」全序列的 K,按匹配度加权混合 V。 这一篇把 注意力分数、Softmax、输出混合 的公式与手算例子讲清楚,并区分 Self-Attention 与 Cross-Attention。 这是「大模型数学速成」系列的第 5 篇。建议先读 第 04 篇:LayerNorm 与残差。下一篇讲 前馈网络 FFN。 一、图书馆检索三步把 第 03 篇 的图书馆类比补全: 步骤 数学 生活类比 1. 匹配 $Q$ 与每个 $K$ 算相似度 → scores 你的检索便签与每本书脊标签比对 2. 归一化 Softmax → 权重(和为 1) 把分数变成「借哪几本、各占多少比例」 3. 混合 按权重对 $V$ 加权求和 → 输出 把选中书的正文按比例拼成一份摘要 三步走完,每个 token 的输出不再只是「自己长什么样」,而是融入了它选择关注的其他 token 的信息。 二、符号与形状(列 = token)沿...
现代 C++ 实战(19):哈希表实现
第 18 篇 用 std::sort 做 O(log n) 查找前的准备;哈希表把查找压到平均 O(1)——键经哈希函数映射到桶,碰撞用链地址或开放寻址解决。理解这两条路,就摸清了 std::unordered_map 的底层地图。 demo:ref/cpp_demo/algorithms/hash_table/(链地址、线性探测、双重哈希 + 与标准库性能对比)。 这是「现代 C++ 实战」系列的第 19 篇。建议先读 第 18 篇:排序算法。 一、哈希表在干什么? 操作 平均时间 思路 插入 O(1) index = hash(key) % bucket_count 查找 O(1) 同 index,再比对 key 删除 O(1) 定位后删节点或标记槽位 碰撞(collision):不同 key 算出同一 index。解决策略分两大类: 12链地址法: bucket[i] → (k1,v1) → (k2,v2) → …开放寻址: table[i], table[i+1], … 在同一数组里探测下一个空位 二、哈希函数好哈希函数:确定性、均匀分...
x86 汇编入门(01):Hello World 与系统调用
每个程序员的第一课都是 Hello World。汇编版也不例外——只不过这次没有 printf,没有标准库,只有你和内核之间四条寄存器传话。搞懂这一篇,你就摸到了 Linux 程序最底层的「打电话」方式。 这是「x86 汇编入门」系列的第 1 篇。上一篇我们搭好了 Docker 环境和编译流程。这一篇从 01_hello.asm 出发,理解汇编程序的基本结构和 Linux 系统调用机制。 一、程序长什么样?汇编程序可以粗分为两块:数据放哪里,代码放哪里。 123456789section .data msg db "Hello, Assembly World!", 10 msg_len equ $ - msgsection .text global _start_start: ; ... 系统调用写在这里 ... 部分 作用 section .data 存放已初始化的数据,比如字符串 section .text 存放可执行的机器指令 global _start 告诉链接器:程序从这里开始执行 ...
大模型数学速成(04):LayerNorm、RMS Norm 与残差连接
上一篇我们算出 Q、K、V——但在乘 $W_q$ 之前,输入通常先过 LayerNorm 或 RMS Norm。算完注意力或 FFN 之后,还要加一条 残差连接 把原输入「抄送」回来。 这一篇搞懂:为什么要归一化、两种 Norm 差在哪、Pre-LN 与 Post-LN 怎么排、残差为什么能训深网络。 这是「大模型数学速成」系列的第 4 篇。建议先读 第 03 篇:Q/K/V 投影。下一篇讲 注意力机制与 Softmax。 一、为什么需要归一化?深度网络堆叠几十层后,中间激活的数值尺度容易漂移:某些维爆炸、某些维趋近 0,梯度不稳定,训练变慢甚至发散。 归一化(Normalization) 对每个 token 的特征向量做「拉回标准尺度」——让均值为 0、方差为 1(或类似效果),再交给下一层矩阵乘法。 生活类比:音响均衡器——不管输入音量忽大忽小,先归一化到合适响度,再进功放。 在本系列约定下(第 01 篇): 输入形状 [n_embd, n_tokens],每一列是一个 token 的 $n_embd$ 维向量 Norm 按列操作:对每个 tok...
现代 C++ 实战(18):排序算法与 std::sort
第二季讲完语言与工程,第三季进入算法与数据结构。排序是第一课:手写七种经典算法理解原理,再和 std::sort 做性能对比——感受工业级实现为何快一个数量级。 demo:ref/cpp_demo/algorithms/sorting/(含 7 种手写排序 + benchmark)。 这是「现代 C++ 实战」系列的第 18 篇,第三季开篇。建议先读 第 17 篇:C++23 新特性。 一、排序算法全景 算法 平均时间 最坏 空间 稳定 比较? 冒泡 O(n²) O(n²) O(1) ✅ 是 选择 O(n²) O(n²) O(1) ❌ 是 插入 O(n²) O(n²) O(1) ✅ 是 归并 O(n log n) O(n log n) O(n) ✅ 是 快速 O(n log n) O(n²) O(log n) ❌ 是 堆 O(n log n) O(n log n) O(1) ❌ 是 计数 O(n + k) O(n + k) O(n + k) ✅ 否 std::sort O(n log n) — O(log n) ❌ 是(IntroSo...
x86 汇编入门(00):环境搭建与编译流程
学汇编,最怕的不是指令难记,而是环境配半天就跑不起来。这一篇我们不写任何寄存器,只把「能编译、能运行」这件事搞定。后面 6 篇会在这个环境里,一步步写出真正的汇编程序。 这是「x86 汇编入门」系列的第 0 篇。本系列基于 NASM 语法 + Linux x86_64 系统调用,在 Docker 容器中编译运行,不依赖 C 标准库。下一篇我们从 Hello World 开始,认识第一个系统调用。 一、为什么这样学?你可能听过汇编「难学、难调试、离硬件近」。这些都没错,但入门阶段更大的障碍往往是:工具链太杂。 本系列的选择很克制: 选择 原因 NASM 语法清晰,注释友好,Linux 社区资料多 Linux syscall 不链接 libc,直接跟内核对话,看清程序最底层在干什么 x86_64 64 位寄存器更多,调用约定也更规整 Docker 一次配好 nasm / ld / gdb,Mac 和 Linux 行为一致 可以把它想成学开车:我们先找一条封闭赛道(Docker),车况统一(Ubuntu 22.04 + 工具链),...
大模型数学速成(03):Q/K/V 投影——同一输入,三种角色
上一篇我们学会了 $y = W \cdot x + b$ 的「握手规则」。在 Transformer 的注意力层里,同一份输入特征会连乘三次——分别得到 Q、K、V。为什么要三套权重?权重 $W_q$ 和激活 Q 有什么区别? 这一篇把 Q/K/V 投影一次讲透,为第 05 篇的注意力与 Softmax 铺路。 这是「大模型数学速成」系列的第 3 篇。建议先读 第 02 篇:矩阵乘法。下一篇讲 LayerNorm、RMS Norm 与残差连接。 一、三次投影:同一输入,三种「角色眼镜」LayerNorm 之后,每个 token 有一列通用特征 $X$,形状 [768, S](S 为 token 数)。注意力层对 同一 X 做三次线性变换: \[Q = W_q \cdot X + b_q,\quad K = W_k \cdot X + b_k,\quad V = W_v \cdot X + b_v\] 12345678910 同一份 X(Norm 后的特征) [768 × S] ...
现代 C++ 实战(17):C++23 新特性
C++20 上了 Concepts、协程、Ranges;C++23 继续「还债」:std::expected 补错误处理、std::print 补输出、deducing this 补成员函数模板、std::generator 补协程生成器——不必等 C++26 也能用上不少干货。 这一篇对应 demo:ref/cpp_demo/basics/cpp23_features/(含条件编译,按编译器能力启用特性)。 这是「现代 C++ 实战」系列的第 17 篇。建议先读 第 16 篇:GoogleTest 与 第 08 篇:错误处理。 一、C++23 概览 特性 解决什么 std::expected<T, E> 成功值 + 错误原因,替代部分异常/错误码 deducing this 一份成员函数覆盖 const/非 const std::print / println 类型安全格式化输出 std::generator 标准协程生成器(惰性序列) if consteval constexpr 函数里区分编译期...
大模型数学速成(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 = [咖啡豆量, 水量, 奶量] ← 原始配方权...















