hex0.hex0 (9763B)
1 ## Copyright (C) 2016 Jeremiah Orians 2 ## Copyright (C) 2017 Jan Nieuwenhuizen <janneke@gnu.org> 3 ## Copyright (C) 2020 Sanne Wouda 4 ## This file is part of stage0. 5 ## 6 ## stage0 is free software: you can redistribute it and/or modify 7 ## it under the terms of the GNU General Public License as published by 8 ## the Free Software Foundation, either version 3 of the License, or 9 ## (at your option) any later version. 10 ## 11 ## stage0 is distributed in the hope that it will be useful, 12 ## but WITHOUT ANY WARRANTY; without even the implied warranty of 13 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 ## GNU General Public License for more details. 15 ## 16 ## You should have received a copy of the GNU General Public License 17 ## along with stage0. If not, see <http://www.gnu.org/licenses/>. 18 19 ## ELF Header 20 21 #:ELF_base 22 7F 45 4C 46 ## e_ident[EI_MAG0-3] ELF's magic number 23 24 02 ## e_ident[EI_CLASS] Indicating 64 bit 25 01 ## e_ident[EI_DATA] Indicating little endianness 26 01 ## e_ident[EI_VERSION] Indicating original elf 27 28 03 ## e_ident[EI_OSABI] Set at 0 because none cares 29 00 ## e_ident[EI_ABIVERSION] See above 30 31 00 00 00 00 00 00 00 ## e_ident[EI_PAD] 32 02 00 ## e_type Indicating Executable 33 B7 00 ## e_machine Indicating AArch64 34 01 00 00 00 ## e_version Indicating original elf 35 36 78 00 60 00 00 00 00 00 ## e_entry Address of the entry point (Number of bytes this header is + Base Address) 37 40 00 00 00 00 00 00 00 ## e_phoff Address of program header table 38 00 00 00 00 00 00 00 00 ## e_shoff Address of section header table 39 40 00 00 00 00 ## e_flags 41 40 00 ## e_ehsize Indicating our 64 Byte header 42 43 38 00 ## e_phentsize size of a program header table 44 01 00 ## e_phnum number of entries in program table 45 46 00 00 ## e_shentsize size of a section header table 47 00 00 ## e_shnum number of entries in section table 48 49 00 00 ## e_shstrndx index of the section names 50 51 ## Program Header 52 #:ELF_program_headers 53 01 00 00 00 ## p_type 54 07 00 00 00 ## Flags 55 00 00 00 00 00 00 00 00 ## p_offset 56 57 00 00 60 00 00 00 00 00 ## p_vaddr 58 00 00 60 00 00 00 00 00 ## p_physaddr 59 60 0E 02 00 00 00 00 00 00 ## p_filesz 61 0E 02 00 00 00 00 00 00 ## p_memsz 62 63 01 00 00 00 00 00 00 00 ## Required alignment 64 65 #:ELF_text 66 67 # Where the ELF Header is going to hit 68 # Simply jump to _start 69 # Our main function 70 #:_start 71 E10B40F9 ; LDR_X1_[SP,16] # Get the actual input name 72 600C8092 ; SET_X0_TO_FCNTL_H_AT_FDCWD # AT_FDCWD, relative to current working directory 73 020080D2 ; SET_X2_TO_0 # Prepare file as read only 74 080780D2 ; SET_X8_TO_SYS_OPENAT # The syscall number for openat(), aarch64 has no open() 75 010000d4 ; SYSCALL # Open file! 76 E90300AA ; SET_X9_FROM_X0 # Preserve the file pointer we were given 77 78 E10F40F9 ; LDR_X1_[SP,24] # Get the output name 79 600C8092 ; SET_X0_TO_FCNTL_H_AT_FDCWD # AT_FDCWD, relative to current working directory 80 224880D2 ; SET_X2_TO_577 # Prepare file as O_WRONLY|O_CREAT|O_TRUNC 81 033880D2 ; SET_X3_TO_448 # Prepare file as RWX for owner only (700 in octal) 82 080780D2 ; SET_X8_TO_SYS_OPENAT # The syscall number for openat(), aarch64 has no open() 83 010000D4 ; SYSCALL # Open file! 84 EA0300AA ; SET_X10_FROM_X0 # Preserve the file pointer we were given 85 86 # Our flag for byte processing 87 0F008092 ; SET_X15_TO_MINUS_1 88 89 # temp storage for the sum 90 0E0080D2 ; SET_X14_TO_0 91 92 #:loop 93 # Read a byte 94 470000 94 ; ^~Read_byte CALL 95 96 # process byte 97 120000 94 ; ^~hex CALL 98 99 # Deal with -1 values 100 1F0000F1 ; CMP_X0_TO_0 101 4A000054 ; SKIP_INST_GE 102 FCFFFF 17 ; ^~loop RBRANCH 103 104 # deal with toggle 105 FF0100F1 ; CMP_X15_TO_0 106 4B000054 ; SKIP_INST_LT 107 040000 14 ; ^~print BRANCH 108 109 # process first byte of pair 110 EE0300AA ; SET_X14_FROM_X0 111 0F0080D2 ; SET_X15_TO_0 112 113 F6FFFF 17 ; ^~loop RBRANCH 114 115 # process second byte of pair 116 #:print 117 # update the sum and store in output 118 00100E8B ; ADD_X0_X0_X14_LSL4 119 41000018 ; LOAD_W1_AHEAD 120 02000014 ; SKIP_32_DATA 121 0C02 6000 ; $output DATA_OFFSET 40 00 122 20000039 ; STR_BYTE_W0_[X1] 123 124 # flip the toggle 125 0F008092 ; SET_X15_TO_MINUS_1 126 127 2E0000 94 ; ^~write_byte CALL 128 129 EEFFFF 17 ; ^~loop RBRANCH 130 131 #:hex 132 # Purge Comment Lines (#) 133 1F8C00F1 ; CMP_X0_TO_35 134 41000054 ; SKIP_INST_NE 135 170000 14 ; ^~purge_comment BRANCH 136 137 # Purge Comment Lines (;) 138 1FEC00F1 ; CMP_X0_TO_59 139 41000054 ; SKIP_INST_NE 140 140000 14 ; ^~purge_comment BRANCH 141 142 # deal all ascii less than 0 143 1FC000F1 ; CMP_X0_TO_48 144 4A000054 ; SKIP_INST_GE 145 1F0000 14 ; ^~ascii_other BRANCH 146 147 # deal with 0-9 148 1FE800F1 ; CMP_X0_TO_58 149 4A000054 ; SKIP_INST_GE 150 160000 14 ; ^~ascii_num BRANCH 151 152 # deal with all ascii less than A 153 1F0401F1 ; CMP_X0_TO_65 154 4A000054 ; SKIP_INST_GE 155 190000 14 ; ^~ascii_other BRANCH 156 157 # deal with A-F 158 1F1C01F1 ; CMP_X0_TO_71 159 4A000054 ; SKIP_INST_GE 160 140000 14 ; ^~ascii_high BRANCH 161 162 # deal with all ascii less than a 163 1F8401F1 ; CMP_X0_TO_97 164 4A000054 ; SKIP_INST_GE 165 130000 14 ; ^~ascii_other BRANCH 166 167 # deal with a-f 168 1F9C01F1 ; CMP_X0_TO_103 169 4A000054 ; SKIP_INST_GE 170 0C0000 14 ; ^~ascii_low BRANCH 171 172 # The rest that remains needs to be ignored 173 0F0000 14 ; ^~ascii_other BRANCH 174 175 #:purge_comment 176 FE0F1FF8 ; PUSH_LR # push lr 177 178 #:purge_comment_loop 179 # Read a byte 180 1A0000 94 ; ^~Read_byte CALL 181 182 # Loop if not LF 183 1F2800F1 ; CMP_X0_TO_10 184 40000054 ; SKIP_INST_EQ 185 FDFFFF 17 ; ^~purge_comment_loop RBRANCH 186 187 # Otherwise return -1 188 00008092 ; SET_X0_TO_MINUS_1 189 190 FE0741F8 ; POP_LR # pop lr 191 C0035FD6 ; RETURN 192 193 #:ascii_num 194 00C000D1 ; SUB_X0_48 195 C0035FD6 ; RETURN 196 197 #:ascii_low 198 005C01D1 ; SUB_X0_87 199 C0035FD6 ; RETURN 200 201 #:ascii_high 202 00DC00D1 ; SUB_X0_55 203 C0035FD6 ; RETURN 204 205 #:ascii_other 206 00008092 ; SET_X0_TO_MINUS_1 207 C0035FD6 ; RETURN 208 209 #:Done 210 # program completed Successfully 211 000080D2 ; SET_X0_TO_0 # All is well 212 A80B80D2 ; SET_X8_TO_SYS_EXIT # put the exit syscall number in x8 213 010000d4 ; SYSCALL 214 215 #:write_byte 216 # Print our Hex 217 E0030AAA ; SET_X0_FROM_X10 # Where are we writing to 218 41000018 ; LOAD_W1_AHEAD # What we are writing 219 02000014 ; SKIP_32_DATA 220 0C02 6000 ; $output DATA_OFFSET 221 220080D2 ; SET_X2_TO_1 # set the size of chars we want 222 080880D2 ; SET_X8_TO_SYS_WRITE # the syscall number for write 223 010000d4 ; SYSCALL # call the Kernel 224 C0035FD6 ; RETURN 225 226 #:Read_byte 227 # Attempt to read 1 byte from input file 228 E00309AA ; SET_X0_FROM_X9 # Where are we reading from 229 41000018 ; LOAD_W1_AHEAD # Where to put it 230 02000014 ; SKIP_32_DATA 231 0D02 6000 ; $input DATA_OFFSET 232 220080D2 ; SET_X2_TO_1 # set the size of chars we want 233 E80780D2 ; SET_X8_TO_SYS_READ # the syscall number for read 234 010000D4 ; SYSCALL # call the Kernel 235 236 1F0000F1 ; CMP_X0_TO_0 # Got EOF call it done 237 41000054 ; SKIP_INST_NE 238 ECFFFF 17 ; ^~Done RBRANCH 239 240 # load byte 241 40000098 ; LOAD_W0_AHEAD 242 02000014 ; SKIP_32_DATA 243 0D02 6000 ; $input DATA_OFFSET 244 00004039 ; LDR_BYTE_W0_[X0] # load char, unsigned so zero-extended already 245 C0035FD6 ; RETURN 246 247 #:ELF_data 248 # Where we are putting our output 249 #:output 250 # Reserve a byte 251 00 252 253 # Where we get our input 254 #:input 255 # Reserve a byte 256 00 257 258 #:ELF_end