Irvine32汇编杨辉三角程序:第5行后输出乱码问题排查
问题分析与解决方案
1. 核心问题:binCoeff 变量赋值错误
程序在计算杨辉三角边界值(即每行首尾的1)时,仅向binCoeff(DWORD类型,4字节)写入了单字节的1,导致高3字节保留了之前计算的残留值,最终输出错误的大数或乱码。
在nChooseK过程的SetOne段中:
SetOne: MOV [binCoeff], 1 ; 错误:仅写入单字节,未覆盖全部4字节
由于MASM默认将立即数1视为BYTE类型,这条指令只会修改binCoeff的最低1字节,剩余3字节仍为之前计算的残留数据,导致读取时得到错误的DWORD值。
2. 修复方案
方案一:通过寄存器写入完整DWORD值
修改SetOne段,先将1加载到EAX(32位寄存器),再写入binCoeff:
SetOne: MOV EAX, 1 ; 将1加载到32位寄存器 MOV [binCoeff], EAX ; 写入完整的4字节DWORD值 JMP EndCalculation
方案二:显式指定DWORD类型
直接使用DWORD PTR强制写入4字节:
SetOne: MOV DWORD PTR [binCoeff], 1 ; 显式指定为DWORD类型 JMP EndCalculation
3. 附加优化:遵循寄存器调用约定
PrintPascalRow过程修改了EBX(属于callee-saved寄存器),但未保存和恢复该寄存器。虽然当前逻辑中EBX值未被改变,但遵循调用约定能避免潜在问题:
PrintPascalRow PROC ; 新增保存EBX PUSH EAX PUSH EDX PUSH ESI PUSH EDI PUSH EBX ; 保存EBX MOV ESI, 0 RowElementLoop: MOV EBX, [currentRow] ; ... 原有逻辑 ... EndRow: ; 新增恢复EBX POP EBX ; 恢复EBX POP EDI POP ESI POP EDX POP EAX RET PrintPascalRow ENDP
问题解答
- 第5行及以后输出乱码的原因:边界值赋值时仅写入单字节,导致
binCoeff残留高字节数据,打印出错误的大数,表现为乱码或数字拼接。 - 空格打印是否有问题:空格打印逻辑正确(通过
MOV DL,32和WriteChar),仅存在末尾多余空格的 cosmetic 问题,不影响功能。 - 寄存器管理问题:
PrintPascalRow未遵循调用约定保存EBX,虽当前未引发错误,但修复后更健壮;核心问题是binCoeff的DWORD赋值错误。
内容的提问来源于stack exchange,提问作者rezivor
相关产品推荐
相关产品推荐

