如何在NASM v2.15.05汇编中输入并相加多位数?
多位数加法输入问题解决方案
问题描述
已花费4小时尝试实现多位数输入功能,目前仅能成功处理0-9的个位数。尝试将字节数改为2,但程序未受影响,仍无法解决问题,求助可行方案。
原代码:
;adding two numbers(user input) section .data msg1 db "Enter the first number : ",0xa len1 equ $ - msg1 msg2 db "Enter the 2nd number : ",0xa len2 equ $ - msg2 msg3 db "The sum is: " len3 equ $- msg3 section .bss num1 resb 2 num2 resb 2 res resb 2 section .text global _start _start : ;typing the first msg mov edx,len1 mov ecx,msg1 mov ebx,1 mov eax,4 int 0x80 ;getting the user input for the first number mov edx,2 mov ecx,num1 mov ebx,0 mov eax,3 int 0x80 ;typing the second msg mov edx,len2 mov ecx,msg2 mov ebx,1 mov eax,4 int 0x80 ;getting the 2nd user input mov edx,2 mov ecx,num2 mov ebx,0 mov eax,3 int 0x80 ; moving the first number to eax register and second number to ebx mov eax,[num1] sub eax,'0' ; subtract to convert ascii into decimal mov ebx,[num2] sub ebx,'0' add eax,ebx add eax,'0' ; to convert decimal into ascii again mov [res],eax ; storing the sum in res memory location ;typing the third msg mov edx,len3 mov ecx,msg3 mov ebx,1 mov eax,4 int 0x80 ;printing the sum mov edx,2 mov ecx,res mov ebx,1 mov eax,4 int 0x80 ;exiting mov ebx,0 mov eax,1 int 0x80
问题根源
- 原代码仅读取输入的第一个字符(
mov eax,[num1]取的是num1指向的第一个字节),完全未处理多位数的后续位 - 多位数转十进制需要逐位计算:比如输入"12",要执行
1*10 + 2的逻辑,原代码没有这个转换步骤 - 结果输出时,若和为多位数(比如12+34=46),直接加'0'只能得到单个字符,无法输出完整数字
解决方案步骤
- 扩展输入缓冲区:给num1、num2分配足够空间(比如10字节),支持更长的多位数输入
- 实现多位数转十进制函数:遍历输入的每个字符,直到遇到换行符,通过
结果*10 + 当前位数字的逻辑计算出十进制数值 - 实现十进制转ASCII输出函数:把计算出的和(十进制)逐位转成ASCII字符,反向存储后再正向输出,确保多位数能正确显示
修改后的完整代码
; 多位数加法程序 section .data msg1 db "Enter the first number: ", 0xa len1 equ $ - msg1 msg2 db "Enter the second number: ", 0xa len2 equ $ - msg2 msg3 db "The sum is: " len3 equ $ - msg3 newline db 0xa section .bss num1 resb 10 ; 支持最多9位数字+换行符 num2 resb 10 sum_buffer resb 10 ; 存储转换后的和的ASCII section .text global _start _start: ; 提示输入第一个数 mov edx, len1 mov ecx, msg1 mov ebx, 1 mov eax, 4 int 0x80 ; 读取第一个数 mov edx, 10 mov ecx, num1 mov ebx, 0 mov eax, 3 int 0x80 ; 提示输入第二个数 mov edx, len2 mov ecx, msg2 mov ebx, 1 mov eax, 4 int 0x80 ; 读取第二个数 mov edx, 10 mov ecx, num2 mov ebx, 0 mov eax, 3 int 0x80 ; 转换num1为十进制 mov ecx, num1 call str_to_int mov esi, eax ; 保存第一个数到esi ; 转换num2为十进制 mov ecx, num2 call str_to_int add esi, eax ; 计算两数之和,保存到esi ; 输出结果提示 mov edx, len3 mov ecx, msg3 mov ebx, 1 mov eax, 4 int 0x80 ; 将和转换为ASCII字符串 mov eax, esi mov ecx, sum_buffer call int_to_str ; 输出转换后的和 mov edx, eax ; int_to_str返回字符串长度 mov ecx, sum_buffer mov ebx, 1 mov eax, 4 int 0x80 ; 输出换行 mov edx, 1 mov ecx, newline mov ebx, 1 mov eax, 4 int 0x80 ; 退出程序 mov ebx, 0 mov eax, 1 int 0x80 ; 字符串转十进制函数 ; 输入:ecx = 字符串地址 ; 输出:eax = 转换后的十进制数 str_to_int: xor eax, eax ; 初始化结果为0 .next_char: movzx edx, byte [ecx] ; 读取当前字符 cmp dl, 0xa ; 判断是否是换行符 je .done sub dl, '0' ; ASCII转数字 imul eax, 10 ; 结果*10 add eax, edx ; 加上当前数字 inc ecx ; 指针后移 jmp .next_char .done: ret ; 十进制转ASCII字符串函数 ; 输入:eax = 十进制数,ecx = 输出缓冲区地址 ; 输出:eax = 字符串长度 int_to_str: mov ebx, 10 ; 除数10 xor esi, esi ; 计数器,记录数字位数 .next_digit: xor edx, edx div ebx ; eax=商,edx=余数 add dl, '0' ; 余数转ASCII mov [ecx + esi], dl ; 存储到缓冲区(反向) inc esi test eax, eax ; 判断商是否为0 jnz .next_digit ; 反转字符串(因为是反向存储的) mov eax, esi ; 保存长度 xor esi, esi dec eax .reverse_loop: cmp esi, eax jge .reverse_done mov dl, [ecx + esi] mov dh, [ecx + eax] mov [ecx + esi], dh mov [ecx + eax], dl inc esi dec eax jmp .reverse_loop .reverse_done: mov eax, esi ; 返回字符串长度 ret
代码说明
str_to_int函数:遍历输入字符串,把每个ASCII字符转成数字,通过结果*10 + 当前数字的方式计算出十进制数值int_to_str函数:把十进制数不断除以10取余数,转成ASCII后反向存储,再反转得到正确顺序的字符串- 缓冲区扩展到10字节,支持输入9位以内的整数(需要更长位数可继续扩大缓冲区)
内容的提问来源于stack exchange,提问作者drkcutie
相关产品推荐
相关产品推荐

