x86汇编处理三位数ASCII数字减1时整百数运算结果错误的解决方法
问题:x86汇编整百数减1操作输出错误
原代码如下:
section .bss num: resb 3 section .text global _start _start: ; Read input mov eax, 3 mov ebx, 0 mov ecx, num mov edx, 3 int 80h sub byte [num+2], 1 cmp byte [num+2], 255 jne skip_borrow sub byte [num+1], 1 cmp byte [num+1], 255 jne skip_borrow sub byte [num], 1 skip_borrow: cmp byte [num], 0 jne skip_carry mov byte [num+1], 9 mov byte [num+2], 9 skip_carry: mov eax, 4 mov ebx, 1 mov ecx, num mov edx, 3 int 80h mov eax, 1 mov ebx, 0 int 80h
上述代码用于读取三位ASCII数字组成的输入数并执行减1操作,对非整百的三位数运算正常,但对100、200这类整百数运算时输出错误,例如100减1得到10/而非099或99,200减1得到20/而非199。
错误原因分析
- 借位判断逻辑完全错误:代码直接对ASCII字符减1后,判断是否等于255(无符号下的-1),但ASCII数字范围是48('0')到57('9'),当'0'减1后得到47(对应字符'/'),远不等于255,因此不会触发借位流程,导致个位变成'/',十位和百位未正确更新。
- 冗余且错误的
skip_carry段:这段逻辑试图在百位为0时将十位和个位设为9,完全不符合减1的借位逻辑,反而会干扰正常计算。
修复方案
重新设计借位逻辑,正确处理ASCII数字的减1和连续借位:
- 从个位开始减1,若结果小于'0'(48),则将该位设为'9',并向前一位借位(前一位减1)。
- 重复上述逻辑处理十位,若十位减1后也小于'0',同样设为'9'并向百位借位。
- 删除错误的
skip_carry段逻辑。
修复后的代码:
section .bss num: resb 3 section .text global _start _start: ; 读取3位ASCII数字输入(如'100') mov eax, 3 mov ebx, 0 mov ecx, num mov edx, 3 int 80h ; 处理个位减1 sub byte [num+2], 1 cmp byte [num+2], '0' - 1 ; 判断是否小于'0'(减1后为47) jge skip_borrow_ones ; 不小于'0',无需借位 mov byte [num+2], '9' ; 个位设为9,触发借位 sub byte [num+1], 1 ; 十位减1 ; 处理十位借位后的减1 cmp byte [num+1], '0' - 1 jge skip_borrow_tens mov byte [num+1], '9' ; 十位设为9,继续向百位借位 sub byte [num], 1 ; 百位减1 skip_borrow_tens: skip_borrow_ones: ; 输出结果 mov eax, 4 mov ebx, 1 mov ecx, num mov edx, 3 int 80h ; 退出程序 mov eax, 1 mov ebx, 0 int 80h
修复逻辑说明
- 个位减1后,通过
'0'-1(即47)判断是否低于ASCII数字的最小值,比直接写数值更具可读性。 - 触发借位时,将当前位设为'9',并向前一位减1,确保连续借位逻辑正确(如100→099、200→199)。
- 去掉冗余的
skip_carry段,避免干扰正常计算流程。
内容的提问来源于stack exchange,提问作者Ki Kim
相关产品推荐
相关产品推荐

