编写比较两数的汇编代码遇问题:仅比较数字最后一位
汇编多位数比较错误修复:仅比较最后一位问题
问题描述
我正在编写一段用于比较两个数字的汇编代码,目前该代码仅能正确处理单数字输入。当输入两位数时会出现错误:例如输入25和12时输出25,但输入21和13时却输出13。经排查发现,程序仅比较数字的最后一位(如25和12比较5和2,21和13比较1和3),而非整个数字。
原始代码
section .text global _start _start: ;Prompt user to input first number mov eax , 4 mov ebx , 1 mov ecx , msg1 mov edx , lenmsg1 int 0x80 ;input first number mov eax, 3 mov ebx, 2 mov ecx,num1 mov edx, 5 int 0x80 ;prompt user to input second number mov eax, 4 mov ebx, 1 mov ecx, msg2 mov edx, lenmsg2 int 0x80 ;input second number mov eax, 3 mov ebx, 2 mov ecx, num2 mov edx, 5 int 0x80 mov ecx, [num1] CMP ecx ,[num2] JG outcondition ;resmsg mov eax, 4 mov ebx, 1 mov ecx, resmsg mov edx, lenresmsg int 0x80 ;resultmsg mov ecx, num2 mov eax , 4 mov ebx, 1 mov ecx, ecx mov edx ,2 int 0x80 JMP exit outcondition: mov ecx , num1 mov eax, 4 mov ebx, 1 mov ecx, resmsg mov edx, lenresmsg int 0x80 ;resultmsg mov ecx, num1 mov eax , 4 mov ebx, 1 mov ecx,ecx mov edx ,2 int 0x80 exit: mov eax, 1 int 0x80 section .bss num1 resb 5 num2 resb 5 section .data msg1 db "Enter your first number ", 0xA , 0xD lenmsg1 equ $ - msg1 msg2 db "Enter your second number ", 0xA , 0xD lenmsg2 equ $ - msg2 resmsg db "The bigger number is " , 0xA , 0xD lenresmsg equ $ - resmsg
问题根源
你直接通过CMP ecx, [num2]比较内存中的原始输入数据,但输入的数字是以ASCII字符串形式存储的(比如"25"对应ASCII码0x32 0x35,加上换行符0x0A)。直接比较双字内存值时,是把这些字节当作无符号整数对比,这和数值大小的逻辑完全不符。单数字能正常工作只是因为单个数字的ASCII值和数值大小正相关('0'-'9'对应0x30-0x39)。
修复方案
需要先将ASCII字符串转换为整数,再进行数值比较。以下是修改后的代码:
section .text global _start _start: ; Prompt user to input first number mov eax, 4 mov ebx, 1 mov ecx, msg1 mov edx, lenmsg1 int 0x80 ; Input first number mov eax, 3 mov ebx, 2 mov ecx, num1 mov edx, 5 int 0x80 ; Convert first string to integer mov ecx, num1 call str_to_int mov [num1_val], eax ; Prompt user to input second number mov eax, 4 mov ebx, 1 mov ecx, msg2 mov edx, lenmsg2 int 0x80 ; Input second number mov eax, 3 mov ebx, 2 mov ecx, num2 mov edx, 5 int 0x80 ; Convert second string to integer mov ecx, num2 call str_to_int mov [num2_val], eax ; Compare the two integers mov eax, [num1_val] cmp eax, [num2_val] jg print_num1 ; Print result for num2 mov eax, 4 mov ebx, 1 mov ecx, resmsg mov edx, lenresmsg int 0x80 mov eax, 4 mov ebx, 1 mov ecx, num2 ; Find length of num2 (until newline) mov edx, 0 count_num2: cmp byte [num2 + edx], 0xA je count_num2_done inc edx jmp count_num2 count_num2_done: int 0x80 jmp exit print_num1: ; Print result for num1 mov eax, 4 mov ebx, 1 mov ecx, resmsg mov edx, lenresmsg int 0x80 mov eax, 4 mov ebx, 1 mov ecx, num1 ; Find length of num1 (until newline) mov edx, 0 count_num1: cmp byte [num1 + edx], 0xA je count_num1_done inc edx jmp count_num1 count_num1_done: int 0x80 exit: mov eax, 1 int 0x80 ; String to integer function ; Input: ecx = pointer to ASCII string ; Output: eax = integer value str_to_int: mov eax, 0 mov esi, 0 loop_start: movzx ebx, byte [ecx + esi] cmp ebx, 0xA ; Check for newline (end of input) je loop_end cmp ebx, 0x20 ; Check for space (ignore) je skip_char ; Convert ASCII digit to number (subtract 0x30) sub ebx, 0x30 ; Multiply current value by 10 and add new digit imul eax, 10 add eax, ebx skip_char: inc esi jmp loop_start loop_end: ret section .bss num1 resb 5 num2 resb 5 num1_val resd 1 ; Store integer value of num1 num2_val resd 1 ; Store integer value of num2 section .data msg1 db "Enter your first number: ", 0xA, 0xD lenmsg1 equ $ - msg1 msg2 db "Enter your second number: ", 0xA, 0xD lenmsg2 equ $ - msg2 resmsg db "The bigger number is: ", 0xA, 0xD lenresmsg equ $ - resmsg
关键修改点
- 字符串转整数函数:新增
str_to_int函数,遍历ASCII字符串,将每个字符转换为数字并累加为整数,自动跳过空格和终止于换行符。 - 存储数值:在
.bss段添加num1_val和num2_val存储转换后的整数。 - 数值比较:基于转换后的整数进行
cmp和jg判断,确保逻辑正确。 - 动态输出长度:输出结果时计算输入字符串的实际长度(直到换行符),避免固定输出2个字符的问题。
内容的提问来源于stack exchange,提问作者Retr0_Xan
相关产品推荐
相关产品推荐

