Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # PURPOSE: This program converts an input text file to an output text file with the base64 encoding.
- #
- # PROCESSING: 1) Open the input file
- # 2) Open the output file
- # 4) While we're not at the end of the input file
- # a) read part of the file into our piece of memory
- # b) go through each byte of memory
- # convert to base64
- # c) write the piece of memory to the output file
- .section .data #Data storage
- base64: #Lookup table
- .ascii "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\0"
- #######CONSTANTS########
- # System call numbers
- .equ SYS_OPEN, 2
- .equ SYS_READ, 0
- .equ SYS_WRITE, 1
- .equ SYS_CLOSE, 3
- .equ SYS_EXIT, 60
- # Options for open (look at /usr/include/asm/fcntl.h for
- # various values. You can combine them
- # by adding them)
- .equ O_RDONLY, 0 # Open file options - read-only
- .equ O_CREAT_WRONLY_TRUNC, 03101 # Open file options - these options are:
- # CREAT - create file if it doesn't exist
- # WRONLY - we will only write to this file
- # TRUNC - destroy current file contents, if any exist
- .equ O_PERMS, 0666 # Read & Write permissions for everyone
- # End-of-file result status
- .equ END_OF_FILE, 0 # This is the return value of read() which
- # means we've hit the end of the file
- #######BUFFERS#########
- .section .bss
- # This is where the data is loaded into from
- # the data file and written from into the output file.
- # It should never exceed 16,000 for various reasons.
- .equ BUFFER_SIZE_INPUT, 600
- .lcomm BUFFER_DATA_INPUT, BUFFER_SIZE_INPUT
- .equ BUFFER_SIZE_OUTPUT, 900
- .lcomm BUFFER_DATA_OUTPUT, BUFFER_SIZE_OUTPUT
- #######PROGRAM CODE###
- .section .text
- # STACK POSITIONS
- .equ ST_SIZE_RESERVE, 16 # Space for local variables
- # Note: Offsets are RBP-based, which is set immediately at program start
- .equ ST_FD_IN, -16 # Local variable for input file descriptor
- .equ ST_FD_OUT, -8 # Local variable for output file descriptor
- .equ ST_ARGC, 0 # Number of arguments
- .equ ST_ARGV_0, 8 # Name of program
- .equ ST_ARGV_1, 16 # Input file name
- .equ ST_ARGV_2, 24 # Output file name
- .globl _start
- _start:
- ###INITIALIZE PROGRAM###
- movq %rsp, %rbp
- subq $ST_SIZE_RESERVE, %rsp # Allocate space for our file descriptors on the stack
- ###CHECK PARAMETER COUNT###
- cmpq $3, ST_ARGC(%rbp)
- je open_files
- movq $-1, %rdi # Our return value for parameter problems
- movq $SYS_EXIT, %rax
- syscall
- open_files:
- open_fd_in:
- ###OPEN INPUT FILE###
- movq ST_ARGV_1(%rbp), %rdi # Input filename into %rdi
- movq $O_RDONLY, %rsi # Read-only flag
- movq $O_PERMS, %rdx # This doesn't really matter for reading
- movq $SYS_OPEN, %rax # Specify "open"
- syscall # Call Linux
- cmpq $0, %rax # Check success
- jl exit # In case of error simply terminate
- store_fd_in:
- movq %rax, ST_FD_IN(%rbp) # Save the returned file descriptor
- open_fd_out:
- ###OPEN OUTPUT FILE###
- movq ST_ARGV_2(%rbp), %rdi # Output filename into %rdi
- movq $O_CREAT_WRONLY_TRUNC, %rsi # Flags for writing to the file
- movq $O_PERMS, %rdx # Permission set for new file (if it's created)
- movq $SYS_OPEN, %rax # Open the file
- syscall # Call Linux
- cmpq $0, %rax # Check success
- jl close_input # In case of error close input file (already open!)
- store_fd_out:
- movq %rax, ST_FD_OUT(%rbp) # Store the file descriptor
- ###BEGIN MAIN LOOP###
- read_loop_begin:
- ###READ IN A BLOCK FROM THE INPUT FILE###
- movq ST_FD_IN(%rbp), %rdi # Get the input file descriptor
- movq $BUFFER_DATA_INPUT, %rsi # The location to read into
- movq $BUFFER_SIZE_INPUT, %rdx # The size of the buffer
- movq $SYS_READ, %rax
- syscall # Size of buffer read is returned in %eax
- ###EXIT IF WE'VE REACHED THE END###
- cmpq $END_OF_FILE, %rax # Check for end of file marker
- jle end_loop # If found (or error), go to the end
- movq $0, %rcx # Registry for counting data
- continue_read_loop:
- ###CONVERT TO BASE64###
- addq $3, %rcx #adds 3 to rcx to check data bounds
- cmpq %rcx, %rax #compares counter to actual data to check bounds
- jle end_loop #jumps to end if counter exceeds data
- subq $3, %rcx #subtracts rcx to keep counter accurate
- movq $BUFFER_DATA_INPUT, %rdx # moves input data address to rdx
- #move byte 1
- movb 0(%rdx,%rcx,1), %dil # moves actual data to dil
- incq %rcx # increment pointer
- shlq $8, %rdi # moves rdi by one pos so data doesn't get overwritten
- #move byte 2
- movb 0(%rdx,%rcx,1), %dil # moves actual data to dil
- incq %rcx # increment pointer
- shlq $8, %rdi # moves rdi by one pos so data doesn't get overwritten
- #move byte 3
- movb 0(%rdx,%rcx,1), %dil # moves actual data to dil
- incq %rcx # increment pointer
- call convert_to_base64 # Note: RAX may (will) be destroyed (caller-safe!),
- # but will be returned identically as return value
- ###WRITE THE BLOCK OUT TO THE OUTPUT FILE###
- movq ST_FD_OUT(%rbp), %rdi # File to use
- movq $BUFFER_DATA_OUTPUT, %rsi # Location of buffer
- movq %rax, %rdx # Size of buffer (=number of bytes actually read/converted)
- movq $SYS_WRITE, %rax
- syscall
- ###CHECK WRITE SUCCESS###
- popq %rbx # Retrieve number of bytes read
- addq $8, %rsp # Remove stack alignment space
- cmpq %rax, %rbx # Compare number read to written
- jne end_loop # If not the same, terminate program
- ###CONTINUE THE LOOP###
- jmp read_loop_begin
- end_loop:
- ###CLOSE THE FILES###
- # NOTE - we don't need to do error checking on these, because
- # error conditions don't signify anything special here
- # and there is nothing for us to do anyway
- movq ST_FD_OUT(%rbp), %rdi
- movq $SYS_CLOSE, %rax
- syscall
- close_input:
- movq ST_FD_IN(%rbp), %rdi
- movq $SYS_CLOSE, %rax
- syscall
- exit:
- ###EXIT###
- movq $0, %rdi # Standard return value for all cases
- movq $SYS_EXIT, %rax
- syscall
- #Actual function which does the converting. Takes in 3 bytes of input and changes them to 4 bytes according to the base64 lookup table.
- convert_to_base64:
- movq %rdx, %r8 #copy 6 bits into rsi
- salq $6, %rdx #delete 6 bits being processed from source
- andq $0b0000000000000000000000000111111, %r8 #keep only last six bits
- convert_loop:
- next_byte:
- end_convert_loop:
- movq %rdi, %rax # Store number of chars converted into RAX as return value
- popq %rbx
- movq %rbp, %rsp
- popq %rbp
- ret
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement