You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NASM用户输入转整数异常:输入与变量对比出现随机值问题

问题根源与修复方案

核心问题:输入的ASCII字符串未转成数值

你直接把用户输入的ASCII字符串加载到寄存器里和num比较,这是错误的。比如输入"64",内存里存的是0x36('6'的ASCII码)、0x34('4'的ASCII码)、0x0a(换行符)这些字节,mov eax, [guess]会把连续4个字节拼成一个32位整数(比如0x0a343600),这自然和num的64(0x40)不相等,所以调试时看到的是“随机值”。

你提到的那段“能工作”的代码,其实只是在比较两个ASCII字符串的二进制值,不是真正的数值比较——比如输入"100"和"99",因为'1'的ASCII码(0x31)比'9'(0x39)小,代码会错误判断100比99小,只是你测试的是位数相同的数字,结果碰巧一致而已。

具体错误与修复步骤

  1. 添加ASCII转整数的逻辑
    必须把用户输入的字符串转换成二进制整数,才能和num做数值比较。可以写一个简单的转换函数:遍历输入的每个字符,减去'0'的ASCII码(0x30),逐步累加计算数值。

  2. 修复win段的打印错误
    print num, 2是错误的,num是equ定义的常量,不是内存地址。需要把num的值转成ASCII字符串存入内存,再调用打印宏。

  3. 初始化并更新猜测次数
    guesses变量从未初始化,打印的是垃圾值。需要在程序开始时把它设为0,每次猜测后加1。

  4. 处理输入的换行符
    系统调用read会把用户输入的换行符也读入缓冲区,转换数值时要跳过这个字符,同时还要过滤非数字输入。

修正后的代码示例

section .data
enter_msg                   DB      "Enter Your Guess : ", 0
enter_msg_len               equ     $-enter_msg
invalid_input_msg           DB      "Invalid Input !!!", 0x0a, 0
invalid_input_msg_len       equ     $-invalid_input_msg
input_out_of_range          DB      "Input Out Of Range !!!", 0x0a, 0
input_out_of_range_len      equ     $-input_out_of_range
too_high_msg                DB      "Your Guess Is Too High !!!", 0x0a, 0
too_high_msg_len            equ     $-too_high_msg
too_low_msg                 DB      "Your Guess Is Too Low !!!", 0x0a, 0
too_low_msg_len             equ     $-too_low_msg
win_msg_1                   DB      "You Won ! The Number Was ", 0
win_msg_1_len               equ     $-win_msg_1
win_msg_2                   DB      " And You Guessed It In ", 0
win_msg_2_len               equ     $-win_msg_2
win_msg_3                   DB      " Guesses !", 0x0a, 0
win_msg_3_len               equ     $-win_msg_3

num                         equ     64
num_str                     DB      "64", 0x0a  ; 预存num的ASCII字符串用于打印
num_str_len                 equ     $-num_str

section .bss
    guess resb 32
    guesses resb 4  ; 用4字节存储整数足够
    converted_num resb 4
    temp_str resb 4  ; 临时存储猜测次数的ASCII字符串

section .text
global _start

_start:
    %macro print 2
        mov eax, 4
        mov ebx, 1
        mov ecx, %1
        mov edx, %2
        int 0x80
    %endmacro

    %macro input 2
        mov eax, 3
        mov ebx, 2
        mov ecx, %1
        mov edx, %2
        int 0x80
    %endmacro

    %macro exit 0
        mov eax, 1
        mov ebx, 0
        int 0x80
    %endmacro

    ; 初始化猜测次数为0
    mov dword [guesses], 0

main_loop:
    print enter_msg, enter_msg_len
    input guess, 32 
    ; 猜测次数加1
    inc dword [guesses]

    ; 调用字符串转整数函数
    push guess
    call str_to_int
    mov [converted_num], eax

    ; 检查输入是否有效
    cmp eax, -1
    je invalid_input
    ; 检查输入范围(限定0-100)
    cmp eax, 0
    jl out_of_range
    cmp eax, 100
    jg out_of_range

    ; 比较转换后的数值和num
    mov ebx, num
    mov eax, [converted_num]
    cmp eax, ebx
    jl lower
    jg higher
    jz win

invalid_input:
    print invalid_input_msg, invalid_input_msg_len
    jmp main_loop

out_of_range:
    print input_out_of_range, input_out_of_range_len
    jmp main_loop

lower:
    print too_low_msg, too_low_msg_len
    jmp main_loop

higher:
    print too_high_msg, too_high_msg_len
    jmp main_loop

win:
    print win_msg_1, win_msg_1_len
    print num_str, num_str_len
    print win_msg_2, win_msg_2_len
    ; 把猜测次数转成ASCII字符串
    push dword [guesses]
    push temp_str
    call int_to_str
    print temp_str, eax
    print win_msg_3, win_msg_3_len
    jmp end

end:
    exit

; 字符串转整数函数:输入栈上的字符串地址,返回eax=转换后的数值,失败返回-1
str_to_int:
    push ebp
    mov ebp, esp
    mov esi, [ebp+8]
    xor eax, eax
    xor ecx, ecx

convert_loop:
    mov cl, [esi]
    ; 跳过换行符
    cmp cl, 0x0a
    je convert_done
    ; 检查是否是数字字符
    cmp cl, '0'
    jl convert_fail
    cmp cl, '9'
    jg convert_fail
    ; 计算数值:eax = eax*10 + (cl-0x30)
    imul eax, 10
    sub cl, 0x30
    add eax, ecx
    inc esi
    jmp convert_loop

convert_done:
    pop ebp
    ret 4  ; 清理栈上的参数

convert_fail:
    mov eax, -1
    pop ebp
    ret 4

; 整数转字符串函数:输入栈上的缓冲区地址、整数,返回eax=字符串长度
int_to_str:
    push ebp
    mov ebp, esp
    mov eax, [ebp+12]
    mov edi, [ebp+8]
    xor ecx, ecx
    ; 处理0的特殊情况
    cmp eax, 0
    je handle_zero

int_loop:
    xor edx, edx
    mov ebx, 10
    div ebx
    add dl, 0x30
    push dx
    inc ecx
    cmp eax, 0
    jne int_loop

    ; 把栈中的字符存入缓冲区
    mov esi, ecx
store_loop:
    pop dx
    mov [edi], dl
    inc edi
    dec ecx
    jnz store_loop
    ; 字符串结尾加换行符(可选)
    mov byte [edi], 0x0a
    inc esi
    mov eax, esi
    pop ebp
    ret 8

handle_zero:
    mov byte [edi], '0'
    mov byte [edi+1], 0x0a
    mov eax, 2
    pop ebp
    ret 8

补充说明

  • 转换函数处理了非数字输入的情况,返回-1触发错误提示
  • 增加了输入范围检查(0-100),符合猜数字游戏的常规逻辑
  • 新增了整数转字符串函数,支持多位数的猜测次数打印

内容的提问来源于stack exchange,提问作者GoodErnest64

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 19:47:06