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
; rcx/xmm0, rdx/xmm1, r8/xmm2, r9/xmm3 then stack
; must had 4 quadwords free on the stack top before a call
main:
push rbp
mov rbp, rsp
sub rsp, 32
; Check the command line parameter count
cmp rcx, 3
jne .param_error
; Save the input and output file names
mov r8, [rdx+8]
mov r9, [rdx+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 rcx, [.files_fmt]
mov rdx, [in_name]
mov r8, [out_name]
xor eax, eax
call printf
; Try to open the input file
mov rcx, [in_name]
xor edx, edx
call open
cmp eax, 0
jl .input_open_failed
mov [infd], rax
; Try to open the output file
mov rcx, [out_name]
xor edx, edx
call open
cmp eax, 0
jge .output_exists
; Try to create the output file
mov rcx, [out_name]
mov edx, 0x8101 ; 0x8000 = O_BINARY
; 0x0100 = O_CREAT
; 0x0000 = O_RDONLY
; 0x0001 = O_WRONLY
; 0x0002 = O_RDWR
mov r8d, 700o
call open
cmp eax, 0
jl .output_open_failed
mov [outfd], rax
; Determine the input file size
mov rcx, [infd]
xor edx, edx
mov r8d, 2
call lseek
mov [in_size], rax
mov rcx, [infd]
xor edx, edx
mov r8d, 0
call lseek
; Allocate the data array
mov rcx, [in_size]
call malloc
cmp rax, 0
je .malloc_failed
mov [data], rax
; Read the input file
mov rcx, [infd]
mov rdx, [data]
mov r8, [in_size]
call read
; Write the output file
mov rcx, [outfd]
mov rdx, [data]
mov r8, [in_size]
call write
; Close the input and output files
mov rcx, [infd]
call close
mov rcx, [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 rcx, [.malloc_failed_fmt]
mov rdx, [in_size]
call printf
mov eax, 1
leave
ret
segment .data
.output_exist_fmt:
db "%s already exists",0x0a,0
segment .text
.output_exists:
lea rcx, [.output_exist_fmt]
mov rdx, [out_name]
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 rcx, [.output_open_fmt]
mov rdx, [out_name]
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 rcx, [.input_open_fmt]
mov rdx, [in_name]
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 rcx, [.param_fmt]
call printf
mov eax, 1
leave
ret