segment .data
align 8
infd dq 0
outfd dq 0
in_name dq 0
out_name:
dq 0
in_size dq 0
data dq 0
segment .text
global main
extern open, malloc, lseek, read, write, close, printf
main:
push rbp
mov rbp, rsp
; Check the command line parameter count
cmp rdi, 3
jne .param_error
; Save the input and output file names
mov r8, [rsi+8]
mov r9, [rsi+16]
mov [in_name], r8
mov [out_name], r9
; Report the files being copied
segment .data
.files_fmt:
db "copying %s to %s",0x0a,0
segment .text
lea rdi, [.files_fmt]
mov rsi, [in_name]
mov rdx, [out_name]
xor eax, eax
call printf
; Try to open the input file
mov rdi, [in_name]
xor esi, esi
call open
cmp rax, 0
jl .input_open_failed
mov [infd], rax
; Try to open the output file
mov rdi, [out_name]
xor esi, esi
call open
cmp rax, 0
jge .output_exists
; Try to create the output file
mov rdi, [out_name]
mov esi, 0x41
mov edx, 700o
call open
cmp rax, 0
jl .output_open_failed
mov [outfd], rax
; Determine the input file size
mov rdi, [infd]
xor esi, esi
mov edx, 2
call lseek
mov [in_size], rax
mov rdi, [infd]
xor esi, esi
mov edx, 0
call lseek
; Allocate the data array
mov rdi, [in_size]
call malloc
cmp rax, 0
je .malloc_failed
mov [data], rax
; Read the input file
mov rdi, [infd]
mov rsi, [data]
mov rdx, [in_size]
call read
; Write the output file
mov rdi, [outfd]
mov rsi, [data]
mov rdx, [in_size]
call write
; Close the input and output files
mov rdi, [infd]
call close
mov rdi, [outfd]
call close
xor eax, eax
leave
ret
segment .data
.malloc_failed_fmt:
db "malloc failed for %ld bytes",0x0a,0
segment .text
.malloc_failed:
lea rdi, [.malloc_failed_fmt]
mov rsi, [in_size]
xor eax, eax
call printf
mov eax, 1
leave
ret
segment .data
.output_exist_fmt:
db "%s already exists",0x0a,0
segment .text
.output_exists:
lea rdi, [.output_exist_fmt]
mov rsi, [out_name]
xor eax, eax
call printf
mov eax, 1
leave
ret
segment .data
.output_open_fmt:
db "Could not open output_file %s",0x0a,0
segment .text
.output_open_failed:
lea rdi, [.output_open_fmt]
mov rsi, [out_name]
xor eax, eax
call printf
mov eax, 1
leave
ret
segment .data
.input_open_fmt:
db "Could not open input_file %s",0x0a,0
segment .text
.input_open_failed:
lea rdi, [.input_open_fmt]
mov rsi, [in_name]
xor eax, eax
call printf
mov eax, 1
leave
ret
segment .data
.param_fmt:
db "Usage: copy input_file output_file",0x0a,0
segment .text
.param_error:
lea rdi, [.param_fmt]
xor eax, eax
call printf
mov eax, 1
leave
ret