I’m working on an assembly program using NASM on Linux. The program is supposed to open a file (which is located in the same directory and has all necessary permissions) and process its contents. However, when I run the program, it fails to open the file and outputs the following error:
Error: Could not open file.
O5
What the Program Should Do:
Check if a file name is provided as a command-line argument.
If no file is specified, print an error message and exit.
Attempt to open the specified file for reading.
If the file opens successfully, read its contents, locate the second line, and print it to the standard output.
If the file cannot be opened or read, print the corresponding error message and the error code.
The Issue:
Even though the file exists in the same directory and has read and write permissions, the program fails to open it and displays the error message:Error: Could not open file.
O5
I suspect the issue might be related to how the file name is passed or interpreted, or there may be a mistake in the sys_open implementation.
Any help to resolve this issue or suggestions on what might be wrong would be greatly appreciated!
Here is the complete code:
{
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
}
MiniX D is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
lea ebx, [esp + 8] ; Load address of argv[1]
Nah man that’s a misleading comment. The argv array is unlikely to be a filename.
mov ebx, [esp + 8] ; Load address of argv[1]
That’s more like it.
1