Linux下NASM汇编程序文件打开失败问题求助
NASM汇编程序无法打开文件问题排查
错误输出
Error: Could not open file.
O5
程序预期功能
- 检查是否通过命令行参数提供文件名
- 未指定文件时,打印错误信息并退出
- 尝试以只读方式打开指定文件
- 文件打开成功后,读取内容、定位第二行并输出到标准输出
- 无法打开或读取文件时,打印对应错误信息及错误码
问题详情
即使目标文件存在于程序同目录且具备读写权限,程序仍无法打开文件并输出上述错误。怀疑问题出在文件名传递/解析逻辑,或是sys_open系统调用的实现错误。完整代码如下:
section .data error_no_arg db "Error: File not specified.", 10, 0 error_open db "Error: Could not open file.", 10, 0 error_open_code db "Open failed with error code: ", 0 error_read db "Error: Failed to read file.", 10, 0 newline db 10 section .bss buffer resb 1024 error_code resb 4 section .text global _start _start: ; Check if a file name is provided mov eax, [esp + 4] ; argc cmp eax, 2 ; argc >= 2 jae open_file ; Proceed to open file if true ; Error: File not specified mov eax, 4 ; sys_write mov ebx, 1 ; stdout mov ecx, error_no_arg ; Error message mov edx, 26 ; Length of the message int 0x80 jmp exit_program open_file: ; Debug: Print the file name (argv[1]) lea ebx, [esp + 8] ; Load address of argv[1] mov eax, 4 ; sys_write mov ecx, ebx ; Pointer to file name mov edx, 100 ; Limit length int 0x80 ; Attempt to open file mov eax, 5 ; sys_open lea ebx, [esp + 8] ; Load address of argv[1] mov ecx, 0 ; O_RDONLY int 0x80 ; Check if the file was opened successfully cmp eax, 0 ; File descriptor should be >= 0 jl file_open_error ; If error, handle it ; Save the file descriptor mov ebx, eax ; Debug: Print confirmation of file opening mov eax, 4 ; sys_write mov ebx, 1 ; stdout lea ecx, [esp + 8] ; Pointer to file name mov edx, 100 ; Limit length int 0x80 read_file: mov eax, 3 ; sys_read mov ecx, buffer ; Buffer pointer mov edx, 1024 ; Bytes to read int 0x80 cmp eax, 0 ; EOF reached? jle file_read_error ; If error, handle it ; Look for the second line mov esi, buffer ; esi points to the buffer xor ecx, ecx ; Line counter find_second_line: mov al, byte [esi] ; Read a byte from the buffer cmp al, 0 ; End of data? je end_of_buffer cmp al, [newline] ; Check for newline jne skip_char inc ecx ; Increment line counter cmp ecx, 2 ; Found the second line? je print_second_line skip_char: inc esi ; Next character jmp find_second_line print_second_line: ; Print the second line mov edx, 0 ; Line length counter find_line_end: mov al, byte [esi + edx] cmp al, 0 ; End of data? je do_write cmp al, [newline] ; End of line? je do_write inc edx ; Increment line length jmp find_line_end do_write: mov eax, 4 ; sys_write mov ebx, 1 ; stdout lea ecx, [esi] ; Pointer to second line int 0x80 jmp close_file end_of_buffer: close_file: ; Close the file mov eax, 6 ; sys_close mov ebx, [esp + 4] ; File descriptor in ebx int 0x80 jmp exit_program file_open_error: ; Error: Could not open file mov eax, 4 ; sys_write mov ebx, 1 ; stdout mov ecx, error_open ; Error message mov edx, 30 ; Length of the message int 0x80 ; Print error code mov eax, 5 ; sys_open returns the error code in eax lea ebx, [error_code] ; Pointer to error code variable mov [error_code], eax ; Store the error code mov eax, [error_code] ; Load the error code ; Convert error code to string and print call print_error_code jmp exit_program file_read_error: ; Error: Failed to read file mov eax, 4 ; sys_write mov ebx, 1 ; stdout mov ecx, error_read ; Error message mov edx, 29 ; Length of the message int 0x80 exit_program: ; Exit the program mov eax, 1 ; sys_exit xor ebx, ebx ; Exit code: 0 int 0x80 print_error_code: ; Print error code as a string add eax, '0' ; Convert error code to character mov [error_code], al ; Write character to buffer mov eax, 4 ; sys_write mov ebx, 1 ; stdout lea ecx, [error_code] ; Pointer to buffer mov edx, 1 ; Output size int 0x80 ret
问题分析与修复
1. 核心错误:文件名指针传递错误
open_file段中,lea ebx, [esp + 8]获取的是argv[1]在栈中的存储地址(即指针的指针),但sys_open系统调用要求ebx直接指向文件名字符串的首地址。正确写法是取出栈中存储的指针值:
; 错误写法 lea ebx, [esp + 8] ; 正确写法 mov ebx, [esp + 8]
这个错误导致内核无法识别你传递的"文件名",直接触发打开失败。
2. 错误码处理逻辑错误
file_open_error段中,你错误地将eax赋值为5(sys_open的调用号),但实际上sys_open失败时,eax返回的是负数错误码(比如-2对应文件不存在,-13对应权限不足)。正确处理需要保留原错误码并取绝对值:
; 错误写法 mov eax, 5 ; 正确处理 neg eax ; 将负数错误码转为正数 add eax, '0'
3. 文件描述符保存与关闭错误
close_file段中,你将ebx赋值为[esp + 4](这是argc的值),而非之前打开文件得到的文件描述符。需要新增一个变量存储文件描述符:
; 在.bss段新增 fd resb 4 ; 文件打开成功后保存描述符 mov [fd], eax ; 关闭文件时使用 mov eax, 6 mov ebx, [fd] int 0x80
4. 调试输出的冗余问题
调试打印文件名时,edx设为100会打印文件名后的垃圾数据,建议改为手动计算文件名长度,或暂时注释该调试代码避免干扰。
修复后的核心代码片段
section .bss buffer resb 1024 error_code resb 4 fd resb 4 ; 新增存储文件描述符的变量 ; ... open_file: ; 获取正确的文件名指针 mov ebx, [esp + 8] ; 调试打印文件名(可选,建议控制长度) mov eax, 4 mov ecx, ebx mov edx, 20 ; 假设文件名不超过20字符 int 0x80 ; 打开文件 mov eax, 5 mov ecx, 0 ; O_RDONLY int 0x80 cmp eax, 0 jl file_open_error ; 保存文件描述符 mov [fd], eax ; ... close_file: mov eax, 6 mov ebx, [fd] int 0x80 jmp exit_program file_open_error: mov eax, 4 mov ebx, 1 mov ecx, error_open mov edx, 30 int 0x80 ; 处理错误码 neg eax call print_error_code jmp exit_program
内容的提问来源于stack exchange,提问作者MiniX D
相关产品推荐
相关产品推荐

