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

x86汇编程序无输出问题:STDIN读入数字后输出异常排查

汇编程序输出问题排查

问题背景

我正在学习汇编语言,编写了一个简单程序,预期实现以下功能:

  • 从STDIN读取一个两位数
  • 将读取的数字减一
  • 将减一结果输出至STDOUT

目前代码尚未实现减一功能,核心困惑是_stdout标签部分没有任何输出,生成的stdout文件为空,需要排查程序错误及逻辑理解误区。

现有代码

section .data
    max_number_size: equ 2 ; max length of read input

section .bss
    input_buffer: resb max_number_size ; used to store input number

section .text
    global _start
    _start:
        mov eax, 3                  ; sys call read
        mov ebx, 0                  ; from FD 0
        mov ecx, input_buffer       ; indicate the adress of the memory buffer where the bytes will be stored
        mov edx, max_number_size    ; read this quantity of character
        int 80H                     ; store max_number_size to input_buffer from STDIN

    atoi:
        mov eax, 0                  ; Set initial total to 0
        mov ebx, 0                  ; keep track of nbr of char processed
        
        atoi_convert:
            mov esi, [ecx]              ; Get the current character
            test ebx, max_number_size   ; break the loop
            je _stdout


            cmp esi, 48                 ; Anything less than char 0 is invalid (check ASCII table)
            jl _exit_1

            cmp esi, 57                 ; Anything greater than char 9 is invalid (check ASCII table)
            jg _exit_1

            sub esi, 48                 ; Convert from ASCII to decimal (0 starts at 48d in ASCII)
            imul eax, 10                ; Multiply total by 10d
            add eax, esi                ; Add current digit to total

            inc ecx                     ; Get the address of the next character
            inc ebx                     ; keep track of nbr of char processed
            jmp atoi_convert

    _stdout:
        mov ecx, eax
        mov eax, 4
        mov ebx, 1
        mov edx, 32
        int 80h

    _exit_0:
        mov eax, 1
        mov ebx, 0
        int 80H

    _exit_1:
        mov eax, 1
        mov ebx, 1
        int 80H

运行现象

/app # make
nasm -f elf -g -F stabs main.asm
ld -o main.exe main.o -m elf_i386
/app # ./main.exe > stdout
49
/app #
/app # ls -l | grep stdout
-rwxr-xr-x    1 root     root             0 Feb  7 12:05 stdout

错误分析与修正建议

1. write系统调用参数完全错误

Linux的write系统调用(eax=4)要求的参数是:

  • ebx:文件描述符(你设置为1,对应STDOUT,这部分正确)
  • ecx:要输出数据的内存起始地址,而非直接的数值。你当前把eax中的数值(比如输入"49"后得到的49)直接赋值给ecx,相当于让系统去读取内存地址0x31(49的十六进制)处的内容,这个地址属于无效内存区域,自然没有输出。
  • edx:要输出的字节数,你设置为32,完全不符合两位数的输出需求,正确值应该是转换后的ASCII字符串长度(比如2字节)。

2. 数值需转换为ASCII字符串才能输出

通过atoi得到的是二进制数值(比如输入"12"得到十进制12),但STDOUT只能识别ASCII字符。要输出数字,必须先把数值转换为对应的ASCII字符串:比如把11转换成字符'1'和'1'(ASCII码49),存储到某个缓冲区后,再把缓冲区地址传给ecx调用write。

3. ATOI循环终止条件逻辑错误

test ebx, max_number_size的判断逻辑不成立:test是按位与操作,当ebx等于2(max_number_size)时,test ebx,2的结果是2,不为0,je不会触发跳转。正确的终止条件应该是:

cmp ebx, max_number_size
je _stdout

4. 补充:减一功能的实现位置

在atoi转换完成后,进入_stdout之前,只需执行dec eax即可完成减一操作。

内容的提问来源于stack exchange,提问作者Itération 122442

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 21:40:58