
简介这是一份面向汇编语言初学者的课后习题答案参考对应钱晓捷主编《汇编语言程序设计》新版第2章8086指令系统内容可配套教材用于自测、备考或作业订正。资料以PDF形式提供共1个文件压缩包仅438KB轻量便于下载与移动端查阅。目前已有一千三百余人学习使用。答案覆盖mov指令寻址方式、堆栈压栈/出栈操作、FLAG标志位状态变化、加减法运算对标志位的影响等核心考点并对习题2.1至2.9逐一给出指令执行结果与简要解答部分题目还附有存储单元地址换算和堆栈变化过程说明。对于需要快速核对8086指令系统习题答案、理解寄存器与内存寻址细节的读者这份答案参照可提供较直接的帮助。1. 拿到这份答案之前先搞清楚教材在讲什么体系很多人大三期末拿到《新版汇编语言程序设计》的习题答参照PDF第一反应就是翻到最后一章照着答案抄。等真上了考场发现自己连MOV AX, BX和MOV BX, AX到底改了什么寄存器都说不利索。问题不出在你笨而是你跳过了教材的体系答案不是拿来背的是拿来反推题目思路的。钱晓捷这本教材经典之处在于它把x86汇编从16位实模式一路带到32位保护模式。新版的改动尤其明显前半部分还在讲8086的寻址方式、汇编程规则、DEBUG调试后半部分直接上了MASM 6.11以上版本、32位寄存器和Win32程序框架。所以做习题之前你先要弄清手里这本是偏传统16位版本还是加入了大量32位内容的新版。这决定了很多题目答案里为什么有的用AX、BX有的却出现EAX、EBX连伪指令都不一样直接抄会抄出大问题。我当时拿到这本教材的第一反应是先把目录拆成三块汇编语言基础寻址、指令系统、伪指令、程序设计方法顺序、分支、循环、子程序、宏、系统相关中断、I/O、模块化编程。习题答案PDF给的是最终结果但你真正需要建立的是这套拆解问题的骨架。这里分享一个很土但好用的办法拿到一个题目不急着看答案先把题目里出现的所有符号拆开——哪些是寄存器、哪些是内存变量、哪些是立即数写在草稿纸上。然后再想每条指令执行前后这些符号的值怎么变。我做过一个统计考研的汇编题和期末考试的汇编题百分之七八十考的根本不是复杂算法而是你知不知道一条指令会同时改变哪些寄存器和标志位。这套基本功一旦建立做任何版本的习题都只是熟练度的问题。还有一个容易忽略的地方版本不同的教材配套的习题编号、题目要求和答案风格完全不同。网上流传的“新版汇编语言程序设计钱晓捷习题答参照”这个PDF本身是个学生整理的参照版不是官方标准答案里面有些解答的注释写得并不严谨。使用它的正确心态是把它当参照不是当真理。尤其在涉及标志位变化、地址计算这类细节上我建议每个关键步骤都要自己在DEBUG里跑一遍验证这既是查答案也是练调试基本功。2. 习题里最常考的硬骨头寄存器、寻址与标志位2.1 七种寻址方式别只会背定义寻址方式这章习题最爱出的就是给你一段指令问你源操作数和目的操作数分别属于什么寻址方式。这个题看着送分但失分率一直很高因为大家混淆的点集中在“寄存器间接寻址”和“寄存器相对寻址”上。区别其实就是一句话间接寻址是把寄存器里的值当内存地址相对寻址是在寄存器值的基础上再加一个位移量。实战记忆法把寄存器想象成一个快递柜编号内存地址是柜子真正的位置。立即寻址指令里直接写着数值比如MOV AX, 1234H数值就在指令里不查内存。寄存器寻址操作数在寄存器里比如MOV AX, BX把BX的值给AX。直接寻址MOV AX, [2000H]直接拿2000H这个地址去内存里取值。寄存器间接寻址MOV AX, [BX]BX里存的是偏移地址去这个地址的内存取值。寄存器相对寻址MOV AX, [BX4]在BX所指的地址基础上偏移4个字节再取值。基址变址寻址MOV AX, [BXSI]两个寄存器相加得到偏移地址。相对基址变址寻址MOV AX, [BXSI4]基址加变址加位移量一起算出地址。习题答案里最坑的地方在于它经常不写默认段寄存器。比如MOV AX, [BX]默认访问DS段但MOV AX, [BP]默认访问SS段。很多同学抄答案时没注意到这个细节真到要改代码、要加段跨越前缀时就懵了。2.2 标志位是答案里最容易被忽略的隐藏考点教材里标志位那节文字不多但习题里反复出现。ADD、SUB、CMP这些指令执行后CF、ZF、SF、OF各变成什么是每年必考。做习题时我建议你对每一道涉及运算的题目都列一张标志位表哪怕题目没问也顺手填上。我自己做题时总结了一套方法看到ADD/ADC/SUB/SBB/CMP先看最高位有没有进位或借位这是CF的由来。看结果是否为0这是ZF的逻辑。看结果的最高位是0还是1无符号数角度它是符号位但这对应SF。OF的判断稍微麻烦一点需要比较两个加数的符号位与结果的符号位。同号相加异号或异号相减同号结果就是溢出。比如MOV AL, 7FH、ADD AL, 1结果AL变成80HCF0、ZF0、SF1、OF1。为什么OF1因为1271128对8位有符号数来说溢出了。这个例子习题答案里大概率直接给的是“AL80H”但它背后的四个标志位变化要自己补齐这才是考试真正的拉分点。2.3 条件转移指令记规律比硬背强JZ/JE、JNZ/JNE、JC、JNC、JO、JS、JG/JL/JGE/JLE、JA/JB/JAE/JBE这一堆条件转移指令是习题里的重灾区。答案PDF里经常直接给结果比如“若AXBX则跳转”但选哪条指令是有门道的。关键区别在于是无符号比较还是有符号比较。无符号数用JA/JB/JAE/JBE有符号数用JG/JL/JGE/JLE。判断方法很简单如果题目里的数据是地址、端口号、计数器这类天然无符号的量用JA/JB如果是数学运算里的正负数用JG/JL。有符号比较判断的底层机制是SF与OF共同参与。CMP AX, BX后执行JGCPU实际判断的是SFOF时转跳。因为两个负数相减可能溢出单看SF会出错。这个知识点习题答案里不会展开讲但你在草稿纸上把符号位和溢出标志位的组合推一遍比死记指令表管用得多。3. 一道综合题的完整推算从读题到调通答案是怎么来的光讲知识点太散我用一道典型章节习题完整走一遍。这类题在钱晓捷教材里出现率极高键盘输入一个十进制数把它转成二进制再按十六进制输出。很多人直接抄答案里的代码抄完也不知道为什么中间要转三遍。题目形如从键盘读入一个两位十进制数比如输入“45”以十六进制形式显示输出“2D”。我拿这个题说清楚答案背后的设计逻辑。第一步输入的本质是字符不是数值。键盘读入的4和5是ASCII码分别是34H和35H。所谓“十进制转十六进制”第一步要把ASCII码转成真正的数值SUB AL, 30H。这一步答案里一定会出现但如果只看答案你很难理解为什么等于号后面突然减了个30H。第二步十位和个位合并。“45”这个数十位是4个位是5真正的数值是4×105。所以代码里取得第一个字符减30H后要乘以10再加第二个字符减30H的结果; 设BL存十位AL存个位 MOV AL, BL MOV BL, 10 ; 十位乘以10 MUL BL ; AX 十位数 * 10 ADD AL, BL ; 这里BL可以重新存个位AL十位数*10个位数实际写的时候要注意MUL是无符号乘法隐含目的操作数是AX。答案里如果直接写MUL BL你就要知道它默认把AL当被乘数。这个细节是很多初学者抄答案时卡壳的位置。第三步十六进制显示。数值45H对应的十进制是69要显示成“45”而不是“69”。拆成高4位和低4位分别转换成ASCII输出。这里最容易被忽略的是大于9的位要加37H而不是30H因为A到F和0到9之间隔了7个字符。; AH存放一个字节的高4位AL存放低4位 CMP AL, 9 JBE digit_ok ; 0~9直接加30H ADD AL, 7 ; A~F先加7再加30H就是37H digit_ok: ADD AL, 30H MOV DL, AL MOV AH, 02H ; DOS功能调用输出一个字符 INT 21H第四步也是最容易漏的回车换行。显示器上输出十六进制数之后下一次输出会直接接在后面。DOS的INT 21H功能02H只负责输出一个字符不负责换行。所以题目答案一般会补一个MOV DL, 0DH和MOV DL, 0AH的两次输出。如果你抄到的答案里没有这两行程序跑起来就会挤成一团。调通这段代码之后你再回头看答案PDF里的完整程序会发现它无非就是四件事读字符、转数值、合并计算、拆分输出。汇编程序看着指令多实际逻辑链很短难的是你脑子里得时刻清楚数据以什么形态存在、存在哪个寄存器或内存单元里。4. 做题和写程序时最容易踩的坑我替你趟过一遍做这本教材的习题有四个坑几乎人人都踩过。我把它们单独拎出来说就是希望你在抄答案、跑程序的时候能绕开。第一个坑是段寄存器的初始化。教材里第一章写程序习惯用MOV AX, DATA、MOV DS, AX来初始化数据段但到了习题的片段题里经常只给一段指令没有给出完整的程序框架。很多人在DEBUG里单步执行时发现内存访问不对原因就是没有正确设置DS/ES。注意MOV DS, AX这样的指令不能在DEBUG里随意省略DEBUG的初始寄存器状态和你题目假设的完全不一样。跑任何一段程序前先看一下各段寄存器的当前值已经是我刻进肌肉记忆的动作。第二个坑是LOOP指令的边界和CX的初值。LOOP的执行顺序是先把CX减1再判断CX是否为0不是先判断再减。这意味着如果你想让某段代码循环N次一定要在进入循环前把CX设成N而不是N-1。习题答案里经常出现MOV CX, 10再LOOP你以为它循环了10次实际上要看循环体里是不是在第一条指令前就有DEC CX之类的操作否则可能多算一次或少算一次。还有个冷门但常考的点是JCXZ指令它在CX0时跳转如果遇到循环次数可能为0的代码用它做保护是标准做法答案里却很少写。第三个坑是INT指令和DOS功能调用号混用。题目里出现INT 21H是很常见的但21H这个中断号下面挂了几十个功能靠AH寄存器区分。输出字符用AH02H读键盘用AH01H输出字符串用AH09H结束程序用AH4CH。答案里如果只写了INT 21H而没注释AH的值就要结合上下文判断。我自己就犯过把09H和02H搞混的错结果屏幕输出一堆乱码——09H需要DS:DX指向一个以$结尾的字符串02H只需要DL里放一个字符的ASCII码差的不是一点半点。第四个坑更隐蔽是标志位在调用子程序后被破坏。很多人把一段核心逻辑封装成PROC过程返回后再用标志位判断结果怎么都调不对。原因可能是子程序里的ADD或CMP指令已经改写了CF/ZF等标志位。子程序调用之前如果依靠标志位判断正确的做法是先把PUSHF压栈保存返回后POPF恢复或者在子程序开头就把需要保留的标志位压入堆栈。习题答案里经常不提这个但你调试时一定会撞上。这四条是我反复在课堂现场和实验课里看到的问题比奇技淫巧更能拖慢进度。如果你正在做这本书的习题在DEBUG里跑一遍代码把每一条指令执行前后寄存器的变化记录下来比你对着答案看十遍都管用。5. 参考答案的正确用法从“看答案”到“会做题”拿到习题答案PDF后正确流程不是直接翻答案而是先给自己限时做题。我自己是这么操作的每道编程题先根据题目要求写伪代码再对照教材指令系统查每条指令能不能实现最后才看参考答案。如果遇到想不通的地方我建议分成三步来对照看思路是否一致答案用的算法和我的一致吗如果不一致它用了什么优化比如累加1到100的和有人用ADD加100次有人用等差数列公式有人用LOOP循环。三种都对但你得知道哪种在考场上最快写完。看寄存器分配是否合理答案为什么选AX而不是BX为什么临时变量放在BX里而不是内存段里很多时候是因为某些指令隐含使用了特定寄存器比如MUL用AXLOOP用CXXLAT用AL和BX。分配寄存器时把这些隐含规则放在心里代码会自然简洁很多。看边界条件是否覆盖答案有没有处理N0的情况有没有处理输入超范围的情况很多教材答案不会考虑这些因为题目默认输入合法但你自己写程序时不能这么天真。不要怕和答案写得不一样。汇编语言的特点是路径多同一道题完全可以用不同的寄存器组合和不同的循环结构实现。只要运行结果正确指令条数略多一点根本不是问题。我在批改作业时就发现有些学生的答案虽然绕了不少弯路但思路清晰、注释完整比教科书答案更好懂。设计程序的第一步永远是让自己能看懂其次才是让机器少跑几步。还有一个心得是建立自己的题库笔记。把做错的题按知识点分类——寻址方式记错、标志位判断错、子程序传参错、中断调用号记混每种错题各留一页。期末复习时看错题比从头刷题高效十倍。习题答案PDF只是一个静态文档你真正学到的东西来自你为每道题做的推演过程。6. 这本教材学完之后汇编的下一步还能去哪里很多人把汇编语言当成一门应付考试的专业课考完就丢这是挺可惜的。钱晓捷这本教材的习题答案确实看起来老气——还在跟DEBUG、DOS打交道但它教你的是底层思维。学完它之后你应该能看懂任何一条x86指令在CPU层面的执行效果应该能读懂编译器生成的汇编代码也应该能看懂栈帧结构、函数调用约定、缓冲区溢出漏洞的根本原理。说几个实际用处。调试C/C程序时当你打开反汇编窗口看到一堆MOV EAX, DWORD PTR [EBP-8]时你能立刻知道这是局部变量int i在栈上的位置知道为什么它存在EBP的负偏移处这时候前几章讲的各种寻址方式就全部活过来了。做逆向分析和破解时汇编语言是不可绕开的基本功必须能流畅阅读大段的反汇编代码。研究操作系统内核时启动代码和上下文切换代码本质就是汇编加C混合体没有汇编底子根本读不下去。嵌入式开发也是这个道理虽然现在的ARM汇编和x86语法有差异但寄存器操作、栈、跳转、中断这些概念完全互通。热搜词里出现“arm汇编语言实战:从零到精通”确实有道理因为你会了x86汇编看ARM汇编会顺畅很多。如果往深处走可以和计算机组成原理对照着看——每个寻址方式对应CPU的哪个硬件部件、每条指令的机器码如何编码、指令周期里有几个节拍。这能帮你建立完整的“程序在机器里到底怎么跑”的图景。走到这一步再回头做钱晓捷习题里的那些“老掉牙”题目你会突然觉得它们没那么无聊。我个人到了这个阶段最受益的一件事是试着写一段简单的内联汇编导入到一个C工程里执行把C语言的变量和汇编指令串起来看。从纯汇编习题到真实工程中混编这一步跨过去你就真正从学汇编切换到了用汇编。以后面试聊到底层优化、指令集、内存布局你都能说出自己的实践经验而不只是背过课本。本文还有配套的精品资源点击获取