|
CS456 - Systems Programming
Spring 2023
|
Displaying ./code/nasm32bit/filesize.asm
; getting the size of a file in bytes
; 32 bit NASM
; Compile with: nasm -f elf filesize.asm
; Link with (64 bit systems require elf_i386 option): ld -m elf_i386 filesize.o -o filesize
; including an external file with some functions we can use
; this file was from the tutorial at asmtutor.com
%include 'functions.asm'
;section for define statements
SECTION .data
usage db 'Usage: ./mycat file', 0Ah ; storing a usage statement
; note that 0Ah is 10 in decimal
; 10 is the ASCII number for newline character
; we define our variables in this section only
; resb means reserve this number of bytes
SECTION .bss
fd resb 4 ; reserving 4 bytes of memory to store a descriptor
buffer resb 10000 ; reserving bytes to store the contents of a file
; next three lines is like "int main" in C
SECTION .text
global _start ;directive section
_start:
; dealing with command line arguments
; argc - stored in ecx register
; argv - all args are stored in a stack in eax register
args:
pop ecx ; getting the value of argc by popping it off the stack
pop eax ; getting argv[0]
dec ecx ; decreasing value inside ecx by 1
cmp ecx, 0h ; checking if argc is now 0
jz printUsage ; if above is true, we jump to section labeled "print usage"
; otherwise we continue below
; opening the file for reading
; here we will invoke the "open" systemcall
; to do this we look up the Linux opcode table for 32 bit assembly
; open uses opcode 5, table also details what gets stored where
; What gets stored where: eax: 5 - the opcode for open
; ebx: filename
; ecx: flags: 0 means read only,
; edx: (optional) mode - setting permissions
openfile:
pop eax ; we still have argv[1] in eax stack, we need to pop it off first
mov ebx, eax ; open will look for a filename in ebx, so we must move it there
mov ecx, 0 ; flag for readonly access mode (O_RDONLY) in ecx
mov eax, 5 ; invoke SYS_OPEN (kernel opcode 5) by putting 5 into eax
int 80h ; call the kernel (this runs the function)
mov [fd], eax ; open will return a file descriptor that is stored in eax
; we need to store this somewhere so we create a variable fd
; we define what fd is above in SECTION .bss, and put square
; brackets around it works like a pointer in C
; reading the file into a buffer
; now we invoke the "read" systemcall
; what gets stored where: eax: 3 - the opcode for read
; ebx: file descriptor (currently in [fd])
; ecx: the buffer we will read into (define this up in SECTION .bss)
; edx: the (maximum) number of bytes we will read
readfile:
mov edx, 100000 ; maximum number of bytes to read - one for each letter of the file contents
mov ecx, buffer ; move the buffer into ecx
mov ebx, [fd] ; move the opened file descriptor into ebx (don't forget the brackets)
mov eax, 3 ; invoke SYS_READ (kernel opcode 3)
int 80h ; call the kernel
; readfile will return the number of bytes read into eax,
; here we want to print this value out, so we will use the
; iprintLF function found in functions.asm
call iprintLF
; close open file
; now we invoke the "close" systemcall
; what gets stored where: eax: 6 - the opcode for close
; ebx: the file descriptor we're closing
close:
mov ebx, [fd] ; moving file descriptor to ebx
mov eax, 6 ; invoke SYS_CLOSE (kernel opcode 6)
int 80h ; call the kernel
jmp done ; we don't want to print a usage statement, so we'll go directly to "done"
;if no argument was provided, we print a usage statement then go to done
printUsage:
mov eax, usage ; move usage statement to eax
call sprint ; using external function in functions.asm
jmp done ; go to section labeled "done"
;exit the program
done:
call quit ; external function that cleanly exits the program
|