Punica_Granatum

assembly base64

Nov 7th, 2018
108
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. # PURPOSE: This program converts an input text file to an output text file with the base64 encoding.
  2. #
  3. # PROCESSING: 1) Open the input file
  4. # 2) Open the output file
  5. # 4) While we're not at the end of the input file
  6. # a) read part of the file into our piece of memory
  7. # b) go through each byte of memory
  8. # convert to base64
  9. # c) write the piece of memory to the output file
  10.  
  11. .section .data #Data storage
  12.  
  13. base64: #Lookup table
  14. .ascii "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\0"
  15.  
  16.  
  17. #######CONSTANTS########
  18.  
  19. # System call numbers
  20. .equ SYS_OPEN, 2
  21. .equ SYS_READ, 0
  22. .equ SYS_WRITE, 1
  23. .equ SYS_CLOSE, 3
  24. .equ SYS_EXIT, 60
  25.  
  26. # Options for open (look at /usr/include/asm/fcntl.h for
  27. # various values. You can combine them
  28. # by adding them)
  29. .equ O_RDONLY, 0 # Open file options - read-only
  30. .equ O_CREAT_WRONLY_TRUNC, 03101 # Open file options - these options are:
  31. # CREAT - create file if it doesn't exist
  32. # WRONLY - we will only write to this file
  33. # TRUNC - destroy current file contents, if any exist
  34.  
  35. .equ O_PERMS, 0666 # Read & Write permissions for everyone
  36.  
  37. # End-of-file result status
  38. .equ END_OF_FILE, 0 # This is the return value of read() which
  39. # means we've hit the end of the file
  40.  
  41. #######BUFFERS#########
  42.  
  43. .section .bss
  44. # This is where the data is loaded into from
  45. # the data file and written from into the output file.
  46. # It should never exceed 16,000 for various reasons.
  47. .equ BUFFER_SIZE_INPUT, 600
  48. .lcomm BUFFER_DATA_INPUT, BUFFER_SIZE_INPUT
  49.  
  50. .equ BUFFER_SIZE_OUTPUT, 1000
  51. .lcomm BUFFER_DATA_OUTPUT, BUFFER_SIZE_OUTPUT
  52.  
  53.  
  54. #######PROGRAM CODE###
  55.  
  56. .section .text
  57.  
  58. # STACK POSITIONS
  59. .equ ST_SIZE_RESERVE, 16 # Space for local variables
  60. # Note: Offsets are RBP-based, which is set immediately at program start
  61. .equ ST_FD_IN, -16 # Local variable for input file descriptor
  62. .equ ST_FD_OUT, -8 # Local variable for output file descriptor
  63. .equ ST_ARGC, 0 # Number of arguments
  64. .equ ST_ARGV_0, 8 # Name of program
  65. .equ ST_ARGV_1, 16 # Input file name
  66. .equ ST_ARGV_2, 24 # Output file name
  67.  
  68. .globl _start
  69. _start:
  70. ###INITIALIZE PROGRAM###
  71. movq %rsp, %rbp
  72. subq $ST_SIZE_RESERVE, %rsp # Allocate space for our file descriptors on the stack
  73. ###CHECK PARAMETER COUNT###
  74. cmpq $3, ST_ARGC(%rbp)
  75. je open_files
  76. movq $-1, %rdi # Our return value for parameter problems
  77. movq $SYS_EXIT, %rax
  78. syscall
  79.  
  80. open_files:
  81. open_fd_in:
  82. ###OPEN INPUT FILE###
  83. movq ST_ARGV_1(%rbp), %rdi # Input filename into %rdi
  84. movq $O_RDONLY, %rsi # Read-only flag
  85. movq $O_PERMS, %rdx # This doesn't really matter for reading
  86. movq $SYS_OPEN, %rax # Specify "open"
  87. syscall # Call Linux
  88. cmpq $0, %rax # Check success
  89. jl exit # In case of error simply terminate
  90.  
  91. store_fd_in:
  92. movq %rax, ST_FD_IN(%rbp) # Save the returned file descriptor
  93.  
  94. open_fd_out:
  95. ###OPEN OUTPUT FILE###
  96. movq ST_ARGV_2(%rbp), %rdi # Output filename into %rdi
  97. movq $O_CREAT_WRONLY_TRUNC, %rsi # Flags for writing to the file
  98. movq $O_PERMS, %rdx # Permission set for new file (if it's created)
  99. movq $SYS_OPEN, %rax # Open the file
  100. syscall # Call Linux
  101. cmpq $0, %rax # Check success
  102. jl close_input # In case of error close input file (already open!)
  103.  
  104. store_fd_out:
  105. movq %rax, ST_FD_OUT(%rbp) # Store the file descriptor
  106.  
  107. ###BEGIN MAIN LOOP###
  108. read_loop_begin:
  109.  
  110. ###READ IN A BLOCK FROM THE INPUT FILE###
  111. movq ST_FD_IN(%rbp), %rdi # Get the input file descriptor
  112. movq $BUFFER_DATA_INPUT, %rsi # The location to read into
  113. movq $BUFFER_SIZE_INPUT, %rdx # The size of the buffer
  114. movq $SYS_READ, %rax
  115. syscall # Size of buffer read is returned in %eax
  116.  
  117. ###EXIT IF WE'VE REACHED THE END###
  118. cmpq $END_OF_FILE, %rax # Check for end of file marker
  119. jle end_loop # If found (or error), go to the end
  120. movq $0, %rcx # Registry for counting data
  121.  
  122.  
  123. continue_read_loop:
  124. ###CONVERT TO BASE64###
  125. addq $3, %rcx #adds 3 to rcx to check data bounds
  126. cmpq %rcx, %rax #compares counter to actual data to check bounds
  127. jge end_loop #jumps to end if counter exceeds data
  128. subq $3, %rcx #subtracts rcx to keep counter accurate
  129.  
  130. movq $BUFFER_DATA_INPUT, %rdx # moves input data address to rdx
  131. #move byte 1
  132. movb 0(%rdx,%rcx,1), %dil # moves actual data to dil
  133. incq %rcx # increment pointer
  134. shlq $8, %rdi # moves rdi by one pos so data doesn't get overwritten
  135. #move byte 2
  136. movb 0(%rdx,%rcx,1), %dil # moves actual data to dil
  137. incq %rcx # increment pointer
  138. shlq $8, %rdi # moves rdi by one pos so data doesn't get overwritten
  139. #move byte 3
  140. movb 0(%rdx,%rcx,1), %dil # moves actual data to dil
  141. incq %rcx # increment pointer
  142.  
  143.  
  144. pushq $-1 # Dummy value for stack alignment
  145. pushq %rax # Store number of bytes read for write check
  146. call convert_to_upper # Note: RAX may (will) be destroyed (caller-safe!),
  147. # but will be returned identically as return value
  148. ###WRITE THE BLOCK OUT TO THE OUTPUT FILE###
  149. movq ST_FD_OUT(%rbp), %rdi # File to use
  150. movq $BUFFER_DATA_OUTPUT, %rsi # Location of buffer
  151. movq %rax, %rdx # Size of buffer (=number of bytes actually read/converted)
  152. movq $SYS_WRITE, %rax
  153. syscall
  154.  
  155. ###CHECK WRITE SUCCESS###
  156. popq %rbx # Retrieve number of bytes read
  157. addq $8, %rsp # Remove stack alignment space
  158. cmpq %rax, %rbx # Compare number read to written
  159. jne end_loop # If not the same, terminate program
  160. ###CONTINUE THE LOOP###
  161. jmp read_loop_begin
  162.  
  163. end_loop:
  164. ###CLOSE THE FILES###
  165. # NOTE - we don't need to do error checking on these, because
  166. # error conditions don't signify anything special here
  167. # and there is nothing for us to do anyway
  168. movq ST_FD_OUT(%rbp), %rdi
  169. movq $SYS_CLOSE, %rax
  170. syscall
  171. close_input:
  172. movq ST_FD_IN(%rbp), %rdi
  173. movq $SYS_CLOSE, %rax
  174. syscall
  175.  
  176. exit:
  177. ###EXIT###
  178. movq $0, %rdi # Standard return value for all cases
  179. movq $SYS_EXIT, %rax
  180. syscall
  181.  
  182. #####FUNCTION convert_to_upper
  183. #
  184. #PURPOSE: This function actually does the conversion to upper case for a block
  185. #
  186. #INPUT: The first parameter (rdi) is the location of the block of memory to convert
  187. # The second parameter (rsi) is the length of that buffer
  188. #
  189. #OUTPUT: This function overwrites the current buffer with the upper-casified
  190. # version.
  191. # Return value: The number of bytes converted (=content of RBX), as
  192. # nothing in here can happen to stop/interrupt this.
  193. #
  194. #VARIABLES:
  195. # %rax - beginning of buffer
  196. # %rbx - length of buffer (old value must be saved!)
  197. # %rdi - current buffer offset
  198. # %r10b - current byte being examined (%r10b is the first byte of %r10)
  199. # Note: This variable assignment is for exemplary purposes only and very suboptimal!
  200. #
  201.  
  202. ###CONSTANTS##
  203. .equ LOWERCASE_A, 'a' # The lower boundary of our search
  204. .equ LOWERCASE_Z, 'z' # The upper boundary of our search
  205. .equ UPPER_CONVERSION, 'A' - 'a' # Conversion between upper and lower case
  206.  
  207. convert_to_upper:
  208. pushq %rbp # Prepare stack
  209. movq %rsp, %rbp
  210. pushq %rbx # Save RBX
  211.  
  212. ###SET UP VARIABLES###
  213. movq %rdi, %rax
  214. movq %rsi, %rbx
  215. movq $0, %rdi
  216.  
  217. # If a buffer with zero length was given us, just leave
  218. cmpq $0, %rbx
  219. je end_convert_loop
  220.  
  221. convert_loop:
  222. # Get the current byte
  223. movb (%rax,%rdi,1), %r10b
  224.  
  225. # Go to the next byte unless it is between 'a' and 'z'
  226. cmpb $LOWERCASE_A, %r10b
  227. jl next_byte
  228. cmpb $LOWERCASE_Z, %r10b
  229. jg next_byte
  230.  
  231. # Otherwise convert the byte to uppercase
  232. addb $UPPER_CONVERSION, %r10b
  233. # And store it back
  234. movb %r10b, (%rax,%rdi,1)
  235. next_byte:
  236. incq %rdi # Next byte
  237. cmpq %rdi, %rbx # Continue unless we've reached the end
  238. jne convert_loop
  239.  
  240. end_convert_loop:
  241. movq %rdi, %rax # Store number of chars converted into RAX as return value
  242. popq %rbx
  243. movq %rbp, %rsp
  244. popq %rbp
  245. ret
RAW Paste Data