hex1.hex1 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. ## Copyright (C) 2017 Jeremiah Orians
  2. ## This file is part of stage0.
  3. ##
  4. ## stage0 is free software: you can redistribute it and/or modify
  5. ## it under the terms of the GNU General Public License as published by
  6. ## the Free Software Foundation, either version 3 of the License, or
  7. ## (at your option) any later version.
  8. ##
  9. ## stage0 is distributed in the hope that it will be useful,
  10. ## but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. ## GNU General Public License for more details.
  13. ##
  14. ## You should have received a copy of the GNU General Public License
  15. ## along with stage0. If not, see <http://www.gnu.org/licenses/>.
  16. ## ELF Header
  17. 7F 45 4C 46 # e_ident[EI_MAG0-3] ELF's magic number
  18. 02 # e_ident[EI_CLASS] Indicating 64 bit
  19. 01 # e_ident[EI_DATA] Indicating little endianness
  20. 01 # e_ident[EI_VERSION] Indicating original elf
  21. 03 # e_ident[EI_OSABI] Set at 3 because FreeBSD is strict
  22. 00 # e_ident[EI_ABIVERSION] See above
  23. 00 00 00 00 00 00 00 # e_ident[EI_PAD]
  24. 02 00 # e_type Indicating Executable
  25. 3E 00 # e_machine Indicating AMD64
  26. 01 00 00 00 # e_version Indicating original elf
  27. 78 00 60 00 00 00 00 00 # e_entry Address of the entry point (Number of bytes this header is + Base Address)
  28. 40 00 00 00 00 00 00 00 # e_phoff Address of program header table
  29. 00 00 00 00 00 00 00 00 # e_shoff Address of section header table
  30. 00 00 00 00 # e_flags
  31. 40 00 # e_ehsize Indicating our 64 Byte header
  32. 38 00 # e_phentsize size of a program header table
  33. 01 00 # e_phnum number of entries in program table
  34. 00 00 # e_shentsize size of a section header table
  35. 00 00 # e_shnum number of entries in section table
  36. 00 00 # e_shstrndx index of the section names
  37. ## Program Header table
  38. 01 00 00 00 # p_type
  39. 07 00 00 00 # ph_flags: PF-X|PF-W|PF-R = 7
  40. 00 00 00 00 00 00 00 00 # p_offset
  41. 00 00 60 00 00 00 00 00 # p_vaddr
  42. 00 00 00 00 00 00 00 00 # Undefined
  43. 00 00 00 0F 00 00 00 00 # p_filesz
  44. 00 00 00 0F 00 00 00 00 # p_memsz
  45. 00 00 20 00 00 00 00 00 # Required alignment
  46. :a # :_start
  47. 58 ; POP_RAX # Get the number of arguments
  48. 5F ; POP_RDI # Get the program name$
  49. 5F ; POP_RDI # Get the actual input name
  50. 48C7C6 00000000 ; LOADI32_RSI %0 # prepare read_only
  51. 48C7C0 02000000 ; LOADI32_RAX %2 # the syscall number for open()
  52. 0F05 ; SYSCALL # Now open that damn file
  53. 4989C1 ; COPY_RAX_to_R9 # Preserve the file pointer we were given
  54. 49C7C7 FFFFFFFF ; LOADI32_R15 %-1 # Our flag for byte processing
  55. 49C7C6 00000000 ; LOADI32_R14 %0 # temp storage for the sum
  56. 49C7C5 00000000 ; LOADI32_R13 %0 # Our starting IP
  57. E8 %b ; CALLI32 %First_pass # Process it
  58. # rewind input file
  59. 4C89CF ; COPY_R9_to_RDI # Using our input file
  60. 48C7C6 00000000 ; LOADI32_RSI %0 # Offset Zero
  61. 48C7C2 00000000 ; LOADI32_RDX %0 # Whence Zero
  62. 48C7C0 08000000 ; LOADI32_RAX %8 # lseek
  63. 0F05 ; SYSCALL
  64. 49C7C7 FFFFFFFF ; LOADI32_R15 %-1 # Our flag for byte processing
  65. 49C7C6 00000000 ; LOADI32_R14 %0 # temp storage for the sum
  66. 49C7C5 00000000 ; LOADI32_R13 %0 # Our starting IP
  67. E8 %h ; CALLI32 %Second_pass # Process it
  68. E9 %t ; JMP32 %Done
  69. :b # :First_pass
  70. E8 %u ; CALLI32 %Read_byte
  71. # Deal with EOF
  72. 483D FCFFFFFF ; CMPI32_RAX %-4
  73. 0F84 %f ; JE32 %First_pass_done
  74. # Check for :
  75. 483D 3A000000 ; CMPI32_RAX %0x3a
  76. 0F85 %c ; JNE32 %First_pass_0
  77. # Deal with label
  78. E8 %y ; CALLI32 %StoreLabel
  79. :c # :First_pass_0
  80. # Check for %
  81. 483D 25000000 ; CMPI32_RAX %0x25
  82. 0F84 %e ; JE32 %First_pass_pointer
  83. # Deal with everything else
  84. E8 %g ; CALLI32 %hex # Process our char
  85. # Deal with EOF
  86. 483D FCFFFFFF ; CMPI32_RAX %-4
  87. 0F84 %f ; JE32 %First_pass_done
  88. # deal with -1 values
  89. 483D 00000000 ; CMPI32_RAX %0
  90. 0F8C %b ; JL32 %First_pass
  91. # deal with toggle
  92. 4981FF 00000000 ; CMPI32_R15 %0
  93. 0F84 %d ; JE32 %First_pass_1
  94. 4981C5 01000000 ; ADDI32_to_R13 %1 # Increment IP
  95. :d # :First_pass_1
  96. 49F7D7 ; NOT_R15
  97. E9 %b ; JMP32 %First_pass
  98. :e # :First_pass_pointer
  99. # Deal with Pointer to label
  100. E8 %u ; CALLI32 %Read_byte # Drop the char
  101. 4981C5 04000000 ; ADDI32_to_R13 %4 # Increment IP
  102. E9 %b ; JMP32 %First_pass # Loop again
  103. :f # :First_pass_done
  104. C3 ; RET
  105. :g # :hex
  106. # deal with EOF
  107. 483D FCFFFFFF ; CMPI32_RAX %-4
  108. 0F84 %l ; JE32 %EOF
  109. # deal with line comments starting with #
  110. 483D 23000000 ; CMPI32_RAX %0x23
  111. 0F84 %q ; JE32 %ascii_comment
  112. # deal with line comments starting with ;
  113. 483D 3B000000 ; CMPI32_RAX %0x3b
  114. 0F84 %q ; JE32 %ascii_comment
  115. # deal all ascii less than 0
  116. 483D 30000000 ; CMPI32_RAX %0x30
  117. 0F8C %p ; JL32 %ascii_other
  118. # deal with 0-9
  119. 483D 3A000000 ; CMPI32_RAX %0x3a
  120. 0F8C %m ; JL32 %ascii_num
  121. # deal with all ascii less than A
  122. 483D 41000000 ; CMPI32_RAX %0x41
  123. 0F8C %p ; JL32 %ascii_other
  124. # deal with A-F
  125. 483D 47000000 ; CMPI32_RAX %0x47
  126. 0F8C %o ; JL32 %ascii_high
  127. #deal with all ascii less than a
  128. 483D 61000000 ; CMPI32_RAX %0x61
  129. 0F8C %p ; JL32 %ascii_other
  130. #deal with a-f
  131. 483D 67000000 ; CMPI32_RAX %0x67
  132. 0F8C %n ; JL32 %ascii_low
  133. # The rest that remains needs to be ignored
  134. E9 %p ; JMP32 %ascii_other
  135. :h # :Second_pass
  136. E8 %u ; CALLI32 %Read_byte
  137. # Deal with EOF
  138. 483D FCFFFFFF ; CMPI32_RAX %-4
  139. 0F84 %k ; JE32 %Second_pass_done
  140. # Simply drop the label
  141. 483D 3A000000 ; CMPI32_RAX %0x3a
  142. 0F85 %i ; JNE32 %Second_pass_0
  143. E8 %u ; CALLI32 %Read_byte
  144. E9 %h ; JMP32 %Second_pass
  145. :i # :Second_pass_0
  146. # Deal with % pointer
  147. 483D 25000000 ; CMPI32_RAX %0x25
  148. 0F85 %j ; JNE32 %Second_pass_1
  149. E8 %z ; CALLI32 %StorePointer
  150. E9 %h ; JMP32 %Second_pass
  151. :j # :Second_pass_1
  152. # Deal with everything else
  153. E8 %g ; CALLI32 %hex # Process our char
  154. # Deal with EOF
  155. 483D FCFFFFFF ; CMPI32_RAX %-4
  156. 0F84 %k ; JE32 %Second_pass_done
  157. # deal with -1 values
  158. 483D 00000000 ; CMPI32_RAX %0
  159. 0F8C %h ; JL32 %Second_pass
  160. # deal with toggle
  161. 4981FF 00000000 ; CMPI32_R15 %0
  162. 0F84 %s ; JE32 %print
  163. # process first byte of pair
  164. 4989C6 ; COPY_RAX_to_R14
  165. 49C7C7 00000000 ; LOADI32_R15 %0
  166. E9 %h ; JMP32 %Second_pass
  167. :k # :Second_pass_done
  168. C3 ; RET
  169. :l # :EOF
  170. C3 ; RET
  171. :m # :ascii_num
  172. 4883E8 30 ; SUBI8_from_RAX !0x30
  173. C3 ; RET
  174. :n # :ascii_low
  175. 4883E8 57 ; SUBI8_from_RAX !0x57
  176. C3 ; RET
  177. :o # :ascii_high
  178. 4883E8 37 ; SUBI8_from_RAX !0x37
  179. C3 ; RET
  180. :p # :ascii_other
  181. 48C7C0 FFFFFFFF ; LOADI32_RAX %-1
  182. C3 ; RET
  183. :q # :ascii_comment
  184. E8 %u ; CALLI32 %Read_byte
  185. 483D 0D000000 ; CMPI32_RAX %0xd
  186. 0F84 %r ; JE32 %ascii_comment_cr
  187. 483D 0A000000 ; CMPI32_RAX %0xa
  188. 0F85 %q ; JNE32 %ascii_comment
  189. :r # :ascii_comment_cr
  190. 48C7C0 FFFFFFFF ; LOADI32_RAX %-1
  191. C3 ; RET
  192. # process second byte of pair
  193. :s # :print
  194. # update the sum and store in output
  195. 49C1E6 04 ; SHL8_R14 !4
  196. 4C01F0 ; ADD_R14_to_RAX
  197. 880425 46036000 ; STORE8_al_Absolute32 &table
  198. # flip the toggle
  199. 49F7D7 ; NOT_R15
  200. # Print our first Hex
  201. 48C7C2 01000000 ; LOADI32_RDX %1 # set the size of chars we want
  202. E8 %w ; CALLI32 %print_chars
  203. 4981C5 01000000 ; ADDI32_to_R13 %1 # Increment IP
  204. E9 %h ; JMP32 %Second_pass
  205. :t # :Done
  206. # program completed Successfully
  207. 48C7C7 00000000 ; LOADI32_RDI %0 # All is well
  208. 48C7C0 3C000000 ; LOADI32_RAX %0x3c # put the exit syscall number in eax
  209. 0F05 ; SYSCALL # Call it a good day
  210. :u # :Read_byte
  211. # Attempt to read 1 byte from STDIN
  212. 48C7C2 01000000 ; LOADI32_RDX %1 # set the size of chars we want
  213. 48C7C6 46036000 ; LOADI32_RSI &table # Where to put it
  214. 4C89CF ; COPY_R9_to_RDI # Where are we reading from
  215. 48C7C0 00000000 ; LOADI32_RAX %0 # the syscall number for read
  216. 0F05 ; SYSCALL # call the Kernel
  217. 4885C0 ; TEST_RAX_RAX # check what we got
  218. 0F84 %v ; JE32 %Read_byte_1 # Got EOF call it done
  219. # load byte
  220. 8A0425 46036000 ; LOAD8_al_Absolute32 &table # load char
  221. 480FB6C0 ; MOVZBQ_RAX_AL # We have to zero extend it to use it
  222. C3 ; RET
  223. # Deal with EOF
  224. :v # :Read_byte_1
  225. 48C7C0 FCFFFFFF ; LOADI32_RAX %-4 # Put EOF in rax
  226. C3 ; RET
  227. :w # :print_chars
  228. 48C7C6 46036000 ; LOADI32_RSI &table # What we are writing
  229. 48C7C7 01000000 ; LOADI32_RDI %1 # Stdout File Descriptor
  230. 48C7C0 01000000 ; LOADI32_RAX %1 # the syscall number for write
  231. 0F05 ; SYSCALL # call the Kernel
  232. C3 ; RET
  233. :x # :Get_table_target
  234. E8 %u ; CALLI32 %Read_byte # Get single char label
  235. 48C1E0 02 ; SHL8_RAX !2 # Each label in table takes 4 bytes to store
  236. 4805 46036000 ; ADDI32_to_RAX &table # Calculate offset
  237. C3 ; RET
  238. :y # :StoreLabel
  239. E8 %x ; CALLI32 %Get_table_target
  240. 4C8928 ; STORE32_R13_to_Address_in_RAX # Write out pointer to table
  241. C3 ; RET
  242. :z # :StorePointer
  243. 4981C5 04000000 ; ADDI32_to_R13 %4 # Increment IP
  244. E8 %x ; CALLI32 %Get_table_target # Get address of pointer
  245. 678B00 ; LOAD32_Address_in_RAX_into_RAX # Get pointer
  246. 4C29E8 ; SUB_R13_from_RAX # target - ip
  247. 890425 46036000 ; STORE32_RAX_Absolute32 &table # put value in output
  248. 48C7C2 04000000 ; LOADI32_RDX %4 # set the size of chars we want
  249. E8 %w ; CALLI32 %print_chars
  250. C3 ; RET
  251. # :table