汇编加法程序异常咨询:单数字结果输出ASCII值异常
问题排查与修复方案
核心问题分析
错误使用32位寄存器读取单字节输入
num1、num2是2字节缓冲区,但你用mov eax,[num1]和mov ebx,[num2]读取的是32位(4字节)数据,会把缓冲区后面的num2、res1的内容也读进来,导致eax初始值远大于57,cmp eax,57后jle singledigit永远跳不过去,直接执行两位数处理逻辑,输出错误字符。字符转数字逻辑不完整
只给num2做了sub ebx,48转数字,num1还是ASCII值直接参与运算,结果自然不对。结果未转回ASCII字符
加法得到的是十进制数字(比如8),没加48转成ASCII的'8',直接输出的话就是ASCII码8(退格符),小于48。sys_read的文件描述符错了
标准输入的文件描述符是0,你用了2(标准错误),虽然可能能输入,但不符合规范。判断两位数的逻辑错误
用cmp eax,57是和ASCII的'9'比较,正确逻辑应该是判断数值是否大于等于10。
修复后的代码
section .bss num1 resb 2 num2 resb 2 res1 resb 1 res2 resb 1 section .data fir db 'Ingrese el primer numero: ' lfir equ $ - fir sec db 'Ingrese el segundo numero: ' lsec equ $ - sec newline db 10 section .text global _start _start: ; 打印第一个提示 mov edx,lfir mov ecx,fir mov ebx,1 mov eax,4 int 0x80 ; 读取第一个数字 mov edx,2 mov ecx,num1 mov ebx,0 mov eax,3 int 0x80 ; 打印第二个提示 mov edx,lsec mov ecx,sec mov ebx,1 mov eax,4 int 0x80 ; 读取第二个数字 mov edx,2 mov ecx,num2 mov ebx,0 mov eax,3 int 0x80 ; 字符转数字并相加 mov al,[num1] ; 取num1的第一个字节(输入的数字字符) sub al,48 ; 转成十进制数字 mov bl,[num2] ; 取num2的第一个字节 sub bl,48 ; 转成十进制数字 add al,bl ; 相加得到结果 ; 判断是否为两位数 cmp al, 10 jl singledigit ; 小于10跳转到单分支 ; 两位数处理 mov ah, al ; 保存结果到ah sub ah, 10 ; 个位数字 add ah, 48 ; 转回ASCII mov [res1], ah mov byte [res2], '1' ; 十位固定是1 ; 打印十位 mov edx,1 mov ecx,res2 mov ebx,1 mov eax,4 int 0x80 ; 打印个位 mov edx,1 mov ecx,res1 mov ebx,1 mov eax,4 int 0x80 jmp finish singledigit: add al,48 ; 转成ASCII字符 mov [res1], al ; 打印结果 mov edx,1 mov ecx,res1 mov ebx,1 mov eax,4 int 0x80 jmp finish finish: ; 打印换行 mov edx,1 mov ecx,newline mov ebx,1 mov eax,4 int 0x80 ; 退出程序 mov eax,1 int 0x80
修复说明
- 改用8位寄存器
al、bl读取输入的单个字符,避免读取多余数据; - 对两个输入字符都执行ASCII转数字操作;
- 计算结果后转回ASCII字符再输出;
- 修正sys_read的文件描述符为0(标准输入);
- 调整res1、res2为单字节(因为最多只需要存一位数字);
- 调整提示字符串的定义为
db(字节类型),之前用dw会导致字符存储为16位,打印时出错; - 修正判断条件为
cmp al,10,符合两位数的数值判断逻辑。
内容的提问来源于stack exchange,提问作者Fotatata
相关产品推荐
相关产品推荐

