NASM Linux x64如何检测EOF并停止向屏幕输出文件内容
问题分析与修复方案
你的代码核心问题有两个:
- 错误的EOF判断逻辑:你现在拿缓冲区
info的地址和0比较,这完全不对——info是BSS段里的固定地址,永远不会是0,所以循环会无限执行,导致最后一次读取的内容被重复输出。 - 未正确指定读写的字节数:sys_read和sys_write都需要通过rdx寄存器传递要操作的字节数,你把这部分代码注释掉了,会导致行为不可预测。
正确的EOF检测方式
Linux的sys_read系统调用(x86下编号3)执行后,eax寄存器会返回实际读取的字节数:
- 返回值为0:表示已经读到文件末尾(EOF),此时应该终止循环。
- 返回值为正数:表示成功读取了对应字节数的数据,需要输出这些字节。
- 返回值为负数:表示读取出错,也应该终止循环。
修复后的代码
section .data Nile_2 db '/home/mark/Desktop/mynewfile.txt', 0 section .bss fd_in resd 4 ; 存储文件描述符(x86下用32位足够) info resb 26 ; 用resb分配字节缓冲区,26字节 section .text global _start _start: ; 打开文件(只读) mov eax, 5 ; sys_open的系统调用号(x86) mov ebx, Nile_2 ; 文件路径 mov ecx, 0 ; O_RDONLY 只读权限 int 0x80 ; 调用内核 mov [fd_in], eax ; 保存文件描述符 READ: ; 从文件读取数据 mov eax, 3 ; sys_read的系统调用号 mov ebx, [fd_in] ; 文件描述符 mov ecx, info ; 缓冲区地址 mov edx, 26 ; 最多读取26字节 int 0x80 cmp eax, 0 ; 检查sys_read的返回值 jle EXIT_READ ; 返回值<=0(EOF或错误)则退出循环 ; 输出读取到的内容 mov edx, eax ; 用实际读取的字节数作为输出长度 mov eax, 4 ; sys_write的系统调用号 mov ebx, 1 ; 标准输出的文件描述符 mov ecx, info ; 缓冲区地址 int 0x80 jmp READ ; 继续读取 EXIT_READ: ; 关闭文件 mov eax, 6 ; sys_close的系统调用号 mov ebx, [fd_in] int 0x80 ; 退出程序 mov eax, 1 ; sys_exit的系统调用号 int 0x80
关键修改点说明
- 把
info的定义从resd 26改成resb 26:resd是分配26个双字(104字节),而你只需要26字节的缓冲区,用resb更准确。 - 恢复
mov edx,26:sys_read必须指定最大读取字节数,否则内核不知道要读多少。 - 用
sys_read的返回值(eax)判断EOF:读取后立即检查eax,等于0就跳出循环。 - 输出时用实际读取的字节数:把eax的值传给edx,这样最后一次读取不足26字节时,只会输出实际读到的内容,不会带上缓冲区里的旧数据。
内容的提问来源于stack exchange,提问作者NanoNebulas
相关产品推荐
相关产品推荐

