NASM汇编乘除运算中ASCII与整数转换输出异常问题求助
加减'0'的底层原理
ASCII编码中,数字字符'0'到'9'的编码值是连续的,对应十进制范围为48~57。因此转换逻辑非常固定:
- 从输入读取到的数字是ASCII字符形式,要转成可运算的整数,直接对字符值执行
sub '0'即可得到对应的十进制数值 - 运算完成后的整数结果要输出为可见字符,对结果执行
add '0'即可转成对应的ASCII数字字符
你代码中的核心错误
你的转换逻辑思路是对的,但是放置位置和寄存器操作存在多处错误:
- 多余的
sub ax, '0'操作:你已经对num1、num2执行了转整数操作,乘法得到的结果已经是整数,你在mul bx之后又做了一次sub ax, '0',直接把2*3=6的结果变成了6-48=-42,后续运算完全错误。 - 除法前未清零DX寄存器:16位乘法
mul bx的结果是32位,存在DX:AX寄存器组中;16位除法div cx默认用DX:AX除以CX,你没有清零DX,寄存器里的垃圾值会导致除法结果完全异常。 - 读取输入时取到多余的换行符:你每次读取2字节,其中第一字节是输入的数字,第二字节是换行符,你直接用
mov ax, [num1]把包含换行符的两个字节都读进AX,高8位的换行符会干扰数值计算,应该只取低8位的数字字符。 - 第一次
sys_write调用参数不全:你第一次调用sys_write的时候没有设置ecx(输出缓冲区地址)和edx(输出长度),属于无效调用。
修正后的完整代码
segment .bss num1 resb 2 num2 resb 2 num3 resb 2 res resb 1 section .text global _start _start: ; 读取num1 mov eax, 3 mov ebx, 0 mov ecx, num1 mov edx, 2 int 0x80 ; 读取num2 mov eax, 3 mov ebx, 0 mov ecx, num2 mov edx, 2 int 0x80 ; 读取num3 mov eax, 3 mov ebx, 0 mov ecx, num3 mov edx, 2 int 0x80 ; 转换num1为整数,存入al mov al, [num1] sub al, '0' ; 转换num2为整数,存入bl mov bl, [num2] sub bl, '0' ; 乘法 al*bl,结果存入ax mul bl ; 转换num3为整数,存入cl mov cl, [num3] sub cl, '0' ; 除法前清零dx xor dx, dx div cl ; 结果转ASCII add al, '0' mov [res], al ; 输出结果 mov ecx, res mov edx, 1 mov ebx, 1 mov eax, 4 int 0x80 ; 退出 mov eax, 1 int 0x80
修正后输入2 3 2即可得到正确输出3。
内容的提问来源于stack exchange,提问作者Forevar Aloen
相关产品推荐
相关产品推荐

