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
相关产品推荐
相关产品推荐

