ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

8086汇编多位十进制加法:ADC+DAA实现与实验报告指南

8086汇编多位十进制加法:ADC+DAA实现与实验报告指南 简介这份PDF是一份微机原理实验的试做报告围绕「两个多位十进制数相加」这一验证性实验展开面向正在学习汇编语言与PC机程序调试的本科及高职学生可用于实验预习、报告撰写参考与上机后的复盘。压缩包内仅1个PDF文件约9KB篇幅紧凑但内容完整涵盖实验目的、实验说明、程序清单与运行结果。报告给出WJSY0.ASM、WJSY1.ASM、WJSY2.ASM三个递进的汇编程序清单从低位在前存储的基础实现到改为高位在前存放数据再到增加被加数、加数与「471932805675249」格式的显示完整演示了MOV、ADD、ADC、DAA、AAA等指令的用法及DEBUG调试方法。读者可借此掌握ASCII码十进制数相加的逐字节运算与调整思路理解BCD码修正、进位处理并学习宏定义、子程序与指针寻址在程序结构中的组织方式。目前已有1096人学习下载适合作为实验课配套参考与汇编入门练习素材。1. 从一份「两个多位十进制数相加」实验报告说起微机原理实验里「两个多位十进制数相加」几乎是每个人绕不过去的第一道坎。它看起来比汇编入门例题还简单——两个数加一加而已可一动手就发现8086 没有一条指令能直接对几十位的十进制数做加法。你手里的数在内存里是以 BCD 码或 ASCII 码形式一个字节存一位进位要自己传长度要自己判断结果还得按十进制显示出来。这份实验报告的核心就是把「多字节十进制加法」从课本上的一个框图画成可运行的汇编程序数据段怎么摆两个加数循环体怎么取字节、怎么用 ADC 带进位加、DAA 怎么修正、最后怎么用 DOS 调用或显存写入把结果打印出来。它适合刚学完寻址方式和标志位、准备交第一份硬件相关实验的同学也适合多年没碰汇编、想快速回忆起 BCD 与 ASCII 调整指令差别的从业者。下面按选型、编码、单步验证、报告成文一路讲透。2. 多位十进制数相加的三种数据表示与选型2.1 ASCII 码串、压缩 BCD 与拆开 BCD 的取舍多位十进制数在 8086 内存里通常有三种存法选哪种直接决定后面用不用调整指令、用哪一条。表示方式每字节存放每位数占字节加法后需调整典型场景ASCII 码串一个 0~9 字符1AAA加后 AL 调整键盘输入、屏幕显示拆开 BCD低 4 位一位高 4 位为 01DAA多字节十进制运算压缩 BCD高低各一位BCD 码0.5需先拆字节再 DAA节省内存的财务数据多数实验用 ASCII 码串因为键盘读进来的就是 ASCII显示出去也是 ASCII不需要额外的转换代码。缺点是浪费一半内存而且必须用 AAA 而不是 DAA。拆开 BCD 是教科书最常画的版本因为它和 DAA 配合最直观一条 DAA 就能修正 AL。压缩 BCD 内存最省但循环里要处理半字节对齐长度必须偶数出错率最高。我一般建议第一次做这个实验用拆开 BCD代码最短、单步最清楚等跑通了再把输入输出改成 ASCII体会 AAA 和 DAA 的差别。2.2 为什么必须用 ADC 而不是 ADD多位相加的关键在于进位不能在字节之间丢失。ADD 只影响 CF但下一次循环如果再 ADD前一次的 CF 就被新结果覆盖了。所以循环体要从最低字节开始每次用ADC把上一次留在 CF 里的进位一起加进来。; 假设 DS:SI 指向加数1最低字节DS:DI 指向加数2最低字节 ; CX 为字节数从低位往高位加 CLC ; 第一次进入循环前清进位 ADD_LOOP: MOV AL, [SI] ; 取加数1当前字节 ADC AL, [DI] ; 加加数2当前字节并带上一次进位 DAA ; 拆开BCD修正AL9 或 AF1 时加6并置CF MOV [BX], AL ; 存结果 INC SI ; 指向更高一位 INC DI INC BX LOOP ADD_LOOP ; CX减1不为0继续逻辑说明CLC只清一次之后的进位由ADC自动串起来。DAA必须紧跟ADC它检查 AL 的低 4 位是否大于 9 或辅助进位 AF 是否为 1是则 AL 加 6、CF 置 1再检查高 4 位。参数上 SI、DI、BX 的递增方向必须和存储时的字节序一致——如果数据按「高位在低地址」存就要改成DEC从高地址往低地址走。提示DAA只对 AL 有效别对 AX 或内存直接 DAA如果用的是 ASCII 码这里要换成AAA并且加之前先把两字节的高 4 位清零。2.3 循环次数、进位溢出与结果长度循环次数 CX 应该取两个加数中较长的那个字节数。相加结束后若 CF 为 1说明最高位还产生了进位结果需要多一个字节存放。常见错误是 CX 取短的那个数高位被截断结果看着对其实丢了数据。结果长度可以取 max(len1, len2) 1最后一个字节留给可能的进位。显示时从最高有效位开始跳过前导零否则打印出来是「00386」这种带前导零的串。判断最高有效位可以循环扫描结果缓冲区找到第一个非零字节的下标再从那里开始逐字节输出 ASCII 字符。3. 从数据段到显示一段完整可跑的 8086 汇编3.1 数据段布局与两个加数的存放DATA SEGMENT NUM1 DB 05H, 07H, 09H, 02H ; 拆开BCD低地址是最低位27095 NUM2 DB 03H, 08H, 01H, 06H ; 68 10 3 - 61083 LEN EQU 4 ; 每个加数4个字节 RES DB 5 DUP(0) ; 结果预留5字节含可能的进位 DATA ENDS这段内存里 NUM1 实际表示 27095最低位 5 在最低地址NUM2 表示 61083。两个数相加是 88178进位不会超出 4 位但 RES 仍留 5 字节更安全。LEN EQU 4用 EQU 定义常量改长度只需改一处循环里MOV CX, LEN即可。3.2 主循环ADC、DAA 与结果写回CODE SEGMENT ASSUME CS:CODE, DS:DATA START: MOV AX, DATA MOV DS, AX MOV SI, OFFSET NUM1 MOV DI, OFFSET NUM2 MOV BX, OFFSET RES MOV CX, LEN CLC ADD_LOOP: MOV AL, [SI] ADC AL, [DI] DAA MOV [BX], AL INC SI INC DI INC BX LOOP ADD_LOOP ; 处理最后的进位 MOV AL, 0 ADC AL, 0 ; 把CF加进AL MOV [BX], AL ; 存入RES第5字节关键点在于循环结束后那两句DAA 已经把 CF 设成最高位产生的进位用ADC AL, 0把这个 0/1 取出写进 RES 的最高字节。若忽略这段结果会少一位。DI 和 SI 的偏移必须指向各自数据段的起始位置这两个寄存器在 8086 的实模式下是可以自由做基址偏移的。3.3 结果转 ASCII 并用 DOS 调用打印; 从RES最高字节开始跳过前导零逐位输出ASCII MOV SI, OFFSET RES ADD SI, LEN ; 指向最高字节(第5字节) MOV CX, LEN1 PRINT_INIT: MOV BL, [SI] CMP BL, 0 JNE PRINT_LOOP ; 找到第一个非零开始打印 DEC SI LOOP PRINT_INIT PRINT_LOOP: MOV AL, [SI] OR AL, 30H ; 拆开BCD低位加0x30转ASCII MOV DL, AL MOV AH, 02H INT 21H ; DOS 显示字符 DEC SI LOOP PRINT_LOOP MOV AH, 4CH INT 21H CODE ENDS END STARTOR AL, 30H把 0~9 的低 4 位直接变成 0~9 的 ASCII 码因为 0x30 的低四位是 0不会破坏原数值。INT 21H 功能号 02H 输出 DL 中的单个字符是 DOS 下最直接的显示方式。注意循环方向从高地址往低地址走先用DEC SI找最高非零位再逐个降序打印。如果写成升序输出会整个反过来。注意若实验环境直接在裸机上跑没有 DOS 中断就要改成写显存 0B800H 段字符放偶地址、属性放奇地址。两类环境不能混用。3.4 用 Debug 单步验证每一位代码跑通与否最稳的验证是 DOS 下的 Debugdebug add.com -t # 单步跟踪每条指令后看 AX/BX/CX/SI/DI 和标志位 -d ds:0 # 查看数据段确认 RES 从第几个字节开始非零 -g # 连续执行到 INT 21H 前每次执行完 DAA 后重点看 AL 和 CF如果 AL 是 0x0A 以上说明 DAA 没生效多半是先把结果存进了 AX 或跳过 DAA。CF 在循环结束时保留的是最高字节的进位一旦被中间的 MOV 或 INT 覆盖最后的进位就丢了。Debug 的-t会显示每条指令后的寄存器快照比在屏幕上猜结果可靠得多。4. 汇编源程序怎么带进实验报告ASCII 原理图与 PDF 组织4.1 把汇编清单和运行截图整理成一页纸报告要的不是代码越长越好而是「数据段——循环核心——结果截图」三块能一眼看懂。源程序用等宽字体数据段单独一段附注每个字节代表哪一位。运行截图建议截两次一次是 Debug 里 RES 内存的-d输出一次是最终屏幕上的十进制结果。两张图一放评委不用跑程序也知道你做对了。常见做法是先用MASM编译链接出 EXE 或 COM在命令行运行截屏Debug 截图则单独开一个窗口避免和运行结果混在一张图里看不清。4.2 ASCII 原理图转 PDF 时的排版与导出参数原理图或流程框图从画图软件或 OrCAD 导出 PDF 时常见坑是页面只导出了一部分区域或者线条被切成多页。导出前把页面设置成「按对象边界」或自定义纸张尺寸比 A4 固定尺寸更保险导出后如果 PDF 里的字发虚、线条发灰可以对整个 PDF 做一次转曲线和漂白加深处理让它打印出来更清楚。如果流程图是 ASCII 字符画的很多老实验指导书就是这种直接用等宽字体粘进 Markdown 再导出 PDF比截图再转 PDF 清晰得多也不会有歪斜。正文用 Markdown 写、代码块标成asm最后统一导出排版比 Word 手动调表格省事。报告环节推荐做法常见坑源程序清单等宽字体 行号asm代码块用 Word 默认宋体缩进错乱数据段说明表格列出每字节含义只贴代码不解释运行截图命令行结果 Debug 内存各一张截图太糊、只截一半原理图 PDF按对象边界导出、转曲线只导出局部区域整体导出Markdown 转 PDF直接截图贴 Word4.3 报告里最容易被打回的三处细节第一处是结果缓冲区长度写死成 LEN没考虑最高位进位导致最高位被覆盖正确做法是 RES 留 LEN1 字节。第二处是进位处理放在循环内把中间进位也存进了结果的高字节正确做法是循环结束再单独取一次 CF。第三处是打印时没跳过前导零结果带着一串 0 显示出来看起来像没算对。这三处只要在报告里各写一句「此处为何这样处理」就不会被当成抄来的代码。实验报告的加分项从来不是代码多长而是你能说清每个寄存器在每一步的值、每个标志位为什么是这个状态。5. 从 Debug 到硬件多位十进制加法的验证技巧与延伸单步跟踪只能看几个字节想验证任意长度的加法对不对可以写一小段校验逻辑先在 PC 上算出期望结果再把结果缓冲区的每个字节按十进制拼成字符串比对。更省事的办法是把两个加数改成边界值分别跑——全是 9、全是 0、最高位产生进位——三组数据覆盖完基本能暴露所有类型的错误。对拆开 BCD 版本边界用例是这样设计的用例NUM1NUM2期望验证点无进位12 3456 7869 12基本正确性连续进位99 9900 01100 00跨字节进位最高位进位99 9901 00100 99RES 多一字节全零00 0000 0000 00前导零处理跑完这四组再看一次最终 CF 和 RES 最高字节就能确认循环长度和进位链都没问题。如果实验课后面要接 8255 或数码管显示把 INT 21H 那段换成端口输出即可加法核心一行不用改这也是先写纯软件版本再上硬件的一条稳路。5.1 关键技巧用 AF 标志快速定位 DAA 失效DAA 依赖 AF辅助进位标志判断低 4 位是否需要修正。如果单步时发现 DAA 没起作用直接看 AFADC 之后 AF 为 1 却看到 AL 没加 6说明你在 ADC 和 DAA 之间插了别的指令把标志冲掉了。DAA 必须紧贴 ADC中间不能有 MOV 以外的操作。把这两条指令写成连续两行是这套实验里成本最低的排错手段。5.2 从实验报告到真实场景的一步延伸真实项目里多字节十进制加法常见于计量、财务和仪表显示数据往往按压缩 BCD 或 ASCII 存放长度不定。把循环次数从常量改成从输入字符串长度算出来的动态值把拆字节逻辑加进去就是一套通用的大数加法子程序。做实验时多花十分钟把长度写成参数而不是写死后面复用的时候能省很多重写。本文还有配套的精品资源点击获取
返回列表