|
CS456 - Systems Programming
Spring 2025
|
Displaying ./code/h4/copy.asm
; copy (the cp command in Unix/Linux Systems)
; here, we will impliment the "cp" command
; syntax:
; ./copy src dest
; Compile with: nasm -f elf copy.asm
; Link with (64 bit systems require elf_i386 option): ld -m elf_i386 copy.o -o copy
;
; include external files
%include 'functions.asm' ; using the functions file from the tutorial
; section for define statements
SECTION .data
usage db 'Usage: ./copy src dst', 0Ah ; storing a usage statement
; note that 0Ah is 10 in decimal
; 10 is the ASCII number for newline character
; section for variables
; resb means "reserve number of bytes"
SECTION .bss
src resb 8 ; buffer for file descriptor of source file
dst resb 8 ; buffer for file descriptor of destination file
sz resb 16 ; reserving 16 bytes to store integer for file size
buffer resb 10000 ; reserving 10000 bytes to store the contents of a file
; our main program is below
SECTION .text
global _start
; main function
_start:
; deal with command line arguments here
; argc is stored in the ecx register
; argv is stored as a stack in the eax register
; recall that cp takes two arguments, so argc will be 3,
args:
pop ecx ; pop ecx to get argc off of the stack
pop eax ; pop eax to get argv[0] (the filename), off of the stack
cmp ecx, 3h ; checking if argc is 3 (number of args needed)
jne printUsage ; if above is false, go to printUsage, else continue below
; "jne" - jump if not equal
; open the source file for reading
opensrc:
pop eax ; pop eax to get argv[1] off the stack, this has our filename
mov ebx, eax ; open expects the filename to be in ebx,
mov eax, 5 ; open expects the opcode for open to be in eax,
mov ecx, 0 ; open expects the mode (read only is 0) to be in ecx
int 80h ; call the kernel to invoke the system call
mov [src], eax ; open returns a file descriptor in eax
; move it to the src variable we declared above
; read the source file into a buffer
readsrc:
mov eax, 3 ; move opcode for read into eax
mov ebx, [src] ; file descriptor for source goes to ebx
mov ecx, buffer ; buffer goes to ecx
mov edx, 10000 ; number of bytes read goes to edx
int 80h ; now call the kernel
; read returns number of bytes read,
mov [sz], eax ; store this value in sz, so we can use this later
; create the destination file
createdst:
pop eax ; now pop eax to get the destination file
; here we need to invoke the "creat" system call first
; creat expects 2 arguments, file permissions in ecx, and filename in ebx
mov ecx, 0644o ; set file permissions to 0644o
mov ebx, eax ; move filename currently in eax to ebx
mov eax, 8 ; opcode for creat goes in eax
int 80h ; call the kernel
mov [dst], eax ; creat returns a file descriptor in eax
; store that in dst, so we can use it to write the buffer to the new file
; write the buffer into the destination file
writedst:
mov eax, 4 ; opcode for write goes to eax
mov ebx, [dst] ; file descriptor for destination goes to ebx
mov ecx, buffer ; buffer goes to ecx
mov edx, [sz] ; number of bytes read earlier (stored in sz), goes to edx
int 80h ; then call the kernel
; close the source file
closesrc:
mov eax, 6 ; opcode for close goes in eax
mov ebx, [src] ; file descriptor for src goes in ebx
int 80h ; now call the kernel
; close the destination file
closedst:
mov eax, 6 ; opcode for close goes in eax
mov ebx, [dst] ; file descriptor for src goes in ebx
int 80h ; now call the kernel
jmp done
; print a usage statement
printUsage:
mov eax, usage ; move usage statement to eax
call sprint ; call sprint (external function in functions.asm)
jmp done ; go to section labeled "done"
; exit the program
done:
call quit
|