hex1.hex0 (10784B)
1 # SPDX-FileCopyrightText: 2017 Jeremiah Orians <jeremiah@pdp10.guru> 2 # SPDX-FileCopyrightText: 2023 Andrius Štikonas <andrius@stikonas.eu> 3 # 4 # SPDX-License-Identifier: GPL-3.0-or-later 5 6 ## ELF Header 7 #:ELF_base 8 7F 45 4C 46 ## e_ident[EI_MAG0-3] ELF's magic number 9 10 02 ## e_ident[EI_CLASS] Indicating 64 bit 11 01 ## e_ident[EI_DATA] Indicating little endianness 12 01 ## e_ident[EI_VERSION] Indicating original elf 13 14 03 ## e_ident[EI_OSABI] Set at 3 because FreeBSD is strict 15 00 ## e_ident[EI_ABIVERSION] Set at 0 because none cares 16 17 00 00 00 00 00 00 00 ## e_ident[EI_PAD] 18 02 00 ## e_type Indicating Executable 19 3E 00 ## e_machine Indicating AMD64 20 01 00 00 00 ## e_version Indicating original elf 21 22 78 00 60 00 00 00 00 00 ## e_entry Address of the entry point (Number of bytes this header is + Base Address) 23 40 00 00 00 00 00 00 00 ## e_phoff Address of program header table 24 00 00 00 00 00 00 00 00 ## e_shoff Address of section header table 25 26 00 00 00 00 ## e_flags 27 40 00 ## e_ehsize Indicating our 64 Byte header 28 29 38 00 ## e_phentsize size of a program header table 30 01 00 ## e_phnum number of entries in program table 31 32 00 00 ## e_shentsize size of a section header table 33 00 00 ## e_shnum number of entries in section table 34 35 00 00 ## e_shstrndx index of the section names 36 37 ## Program Header 38 #:ELF_program_headers 39 01 00 00 00 ## p_type 40 07 00 00 00 ## ph_flags: PF-X|PF-W|PF-R = 7 41 00 00 00 00 00 00 00 00 ## p_offset 42 43 00 00 60 00 00 00 00 00 ## p_vaddr 44 00 00 60 00 00 00 00 00 ## p_physaddr 45 46 6E 02 00 00 00 00 00 00 ## p_filesz 47 6E 02 00 00 00 00 00 00 ## p_memsz 48 49 01 00 00 00 00 00 00 00 ## Required alignment 50 51 #:ELF_text 52 53 # Where the ELF Header is going to hit 54 # Simply jump to _start 55 # Our main function 56 57 # :_start (0x600078) 58 58 ; pop_rax # Get the number of arguments 59 5F ; pop_rdi # Get the program name$ 60 5F ; pop_rdi # Get the actual input name 61 48C7C6 00000000 ; mov_rsi, %0 # prepare read_only 62 48C7C0 02000000 ; mov_rax, %2 # the syscall number for open() 63 0F05 ; syscall # Now open that damn file 64 4989C1 ; mov_r9,rax # Preserve the file pointer we were given 65 66 5F ; pop_rdi # Get the actual output name 67 48C7C6 41020000 ; mov_rsi, %577 # Prepare file as O_WRONLY|O_CREAT|O_TRUNC 68 48C7C2 C0010000 ; mov_rdx, %448 # Prepare file as RWX for owner only (700 in octal) 69 48C7C0 02000000 ; mov_rax, %2 # the syscall number for open() 70 0F05 ; syscall # Now open that damn file 71 4989C2 ; mov_r10,rax # Preserve the file pointer we were given 72 73 49C7C7 FFFFFFFF ; mov_r15, %-1 # Our flag for byte processing 74 49C7C6 00000000 ; mov_r14, %0 # temp storage for the sum 75 49C7C5 00000000 ; mov_r13, %0 # Our starting IP 76 E8 39000000 ; call %First_pass # Process it 77 78 # rewind input file 79 4C89CF ; mov_rdi,r9 # Using our input file 80 48C7C6 00000000 ; mov_rsi, %0 # Offset Zero 81 48C7C2 00000000 ; mov_rdx, %0 # Whence Zero 82 48C7C0 08000000 ; mov_rax, %8 # lseek 83 0F05 ; syscall 84 85 49C7C7 FFFFFFFF ; mov_r15, %-1 # Our flag for byte processing 86 49C7C6 00000000 ; mov_r14, %0 # temp storage for the sum 87 49C7C5 00000000 ; mov_r13, %0 # Our starting IP 88 E8 69000000 ; call %Second_pass # Process it 89 90 E9 E4000000 ; jmp %Done 91 92 # :First_pass (0x6000FC) 93 E8 EF000000 ; call %Read_byte 94 95 # Deal with EOF 96 3C FC ; cmp_al, !-4 97 74 34 ; je8 !First_pass_done 98 99 # Check for : 100 3C 3A ; cmp_al, !0x3a 101 75 05 ; jne8 !First_pass_0 102 103 # Deal with label 104 E8 32010000 ; call %StoreLabel 105 106 # :First_pass_0 (0x60010E) 107 # Check for % 108 3C 25 ; cmp_al, !0x25 109 74 1C ; je8 !First_pass_pointer 110 111 # Deal with everything else 112 E8 23000000 ; call %hex # Process our char 113 114 # Deal with EOF 115 3C FC ; cmp_al, !-4 116 74 1E ; je8 !First_pass_done 117 118 # deal with -1 values 119 3C 00 ; cmp_al, !0 120 7C DD ; jl8 !First_pass 121 122 # deal with toggle 123 4983FF 00 ; cmp_r15, !0 124 74 04 ; je8 !First_pass_1 125 4983C5 01 ; add_r13, !1 # Increment IP 126 127 # :First_pass_1 (0x600129) 128 49F7D7 ; not_r15 129 EB CE ; jmp8 !First_pass 130 131 # :First_pass_pointer (0x60012E) 132 # Deal with Pointer to label 133 E8 BD000000 ; call %Read_byte # Drop the char 134 4983C5 04 ; add_r13, !4 # Increment IP 135 EB C3 ; jmp8 !First_pass # Loop again 136 137 # :First_pass_done (0x600139) 138 C3 ; ret 139 140 # :hex (0x60013A) 141 # deal with EOF 142 3C FC ; cmp_al, !-4 143 74 60 ; je8 !EOF 144 # deal with line comments starting with # 145 3C 23 ; cmp_al, !0x23 146 74 69 ; je8 !ascii_comment 147 # deal with line comments starting with ; 148 3C 3B ; cmp_al, !0x3b 149 74 65 ; je8 !ascii_comment 150 # deal all ascii less than 0 151 3C 30 ; cmp_al, !0x30 152 7C 5E ; jl8 !ascii_other 153 # deal with 0-9 154 3C 3A ; cmp_al, !0x3a 155 7C 51 ; jl8 !ascii_num 156 # deal with all ascii less than A 157 3C 41 ; cmp_al, !0x41 158 7C 56 ; jl8 !ascii_other 159 # deal with A-F 160 3C 47 ; cmp_al, !0x47 161 7C 4F ; jl8 !ascii_high 162 # deal with all ascii less than a 163 3C 61 ; cmp_al, !0x61 164 7C 4E ; jl8 !ascii_other 165 # deal with a-f 166 3C 67 ; cmp_al, !0x67 167 7C 44 ; jl8 !ascii_low 168 # The rest that remains needs to be ignored 169 EB 48 ; jmp8 !ascii_other 170 171 # :Second_pass (0x600160) 172 E8 8B000000 ; call %Read_byte 173 174 # Deal with EOF 175 3C FC ; cmp_al, !-4 176 74 35 ; je8 !Second_pass_done 177 178 # Simply drop the label 179 3C 3A ; cmp_al, !0x3a 180 75 07 ; jne8 !Second_pass_0 181 182 E8 7E000000 ; call %Read_byte 183 EB EC ; jmp8 !Second_pass 184 185 # :Second_pass_0 (0x600174) 186 # Deal with % pointer 187 3C 25 ; cmp_al, !0x25 188 75 07 ; jne8 !Second_pass_1 189 190 E8 CE000000 ; call %StorePointer 191 EB E1 ; jmp8 !Second_pass 192 193 # :Second_pass_1 (0x60017F) 194 # Deal with everything else 195 E8 B6FFFFFF ; call %hex # Process our char 196 197 # Deal with EOF 198 3C FC ; cmp_al, !-4 199 74 16 ; je8 !Second_pass_done 200 201 # deal with -1 values 202 3C 00 ; cmp_al, !0 203 7C D4 ; jl8 !Second_pass 204 205 # deal with toggle 206 4983FF 00 ; cmp_r15, !0 207 74 29 ; je8 !print 208 209 # process first byte of pair 210 4989C6 ; mov_r14,rax 211 49C7C7 00000000 ; mov_r15, %0 212 EB C2 ; jmp8 !Second_pass 213 214 # :Second_pass_done (0x60019E) 215 # :EOF 216 C3 ; ret 217 # :ascii_num (0x60019F) 218 2C 30 ; sub_al, !0x30 219 C3 ; ret 220 # :ascii_low (0x6001A2) 221 2C 57 ; sub_al, !0x57 222 C3 ; ret 223 # :ascii_high (0x6001A5) 224 2C 37 ; sub_al, !0x37 225 C3 ; ret 226 # :ascii_other (0x6001A8) 227 B0 FF ; mov_al, !-1 228 C3 ; ret 229 # :ascii_comment (0x6001AB) 230 E8 40000000 ; call %Read_byte 231 3C 0D ; cmp_al, !0xd 232 74 04 ; je8 !ascii_comment_cr 233 3C 0A ; cmp_al, !0xa 234 75 F3 ; jne8 !ascii_comment 235 # :ascii_comment_cr (0x6001B8) 236 B0 FF ; mov_al, !-1 237 C3 ; ret 238 239 # process second byte of pair 240 # :print (0x6001BB) 241 # update the sum and store in output 242 49C1E6 04 ; shl_r14, !4 243 4C01F0 ; add_rax,r14 244 8805 A6000000 ; mov_[rip+DWORD],al %table 245 246 # flip the toggle 247 49F7D7 ; not_r15 248 249 # Print our first Hex 250 48C7C2 01000000 ; mov_rdx, %1 # set the size of chars we want 251 E8 41000000 ; call %print_chars 252 253 4983C5 01 ; add_r13, !1 # Increment IP 254 E9 80FFFFFF ; jmp %Second_pass 255 256 # :Done (0x6001E0) 257 # program completed Successfully 258 48C7C7 00000000 ; mov_rdi, %0 # All is well 259 48C7C0 3C000000 ; mov_rax, %0x3c # put the exit syscall number in rax 260 0F05 ; syscall # Call it a good day 261 262 # :Read_byte (0x6001F0) 263 # Attempt to read 1 byte from STDIN 264 48C7C2 01000000 ; mov_rdx, %1 # set the size of chars we want 265 488D35 70000000 ; lea_rsi,[rip+DWORD] %table # Where to put it 266 4C89CF ; mov_rdi,r9 # Where are we reading from 267 31C0 ; xor_eax,eax # the syscall number for read 268 0F05 ; syscall # call the Kernel 269 270 4885C0 ; test_rax,rax # check what we got 271 74 0B ; je8 !Read_byte_1 # Got EOF call it done 272 273 # load byte 274 8A05 5E000000 ; mov_al,[rip+DWORD] %table # load char 275 480FB6C0 ; movzx_rax,al # We have to zero extend it to use it 276 C3 ; ret 277 278 # Deal with EOF 279 # :Read_byte_1 (0x600215) 280 B0 FC ; mov_al, !-4 # Put EOF in rax 281 C3 ; ret 282 283 # :print_chars (0x600218) 284 488D35 4F000000 ; lea_rsi,[rip+DWORD] %table # What we are writing 285 4C89D7 ; mov_rdi,r10 # Write to target file 286 48C7C0 01000000 ; mov_rax, %1 # the syscall number for write 287 0F05 ; syscall # call the Kernel 288 C3 ; ret 289 290 # :Get_table_target (0x60022C) 291 E8 BFFFFFFF ; call %Read_byte # Get single char label 292 48C1E0 03 ; shl_rax, !3 # Each label in table takes 8 bytes to store 293 488D0D 32000000 ; lea_rcx,[rip+DWORD] %table # Get table 294 4801C8 ; add_rax,rcx # Calculate offset 295 C3 ; ret 296 297 # :StoreLabel (0x600240) 298 E8 E7FFFFFF ; call %Get_table_target 299 4C8928 ; mov_[rax],r13 # Write out pointer to table 300 31C0 ; xor_eax,eax # wipe higher bits of rax, so that cmp al works 301 C3 ; ret 302 303 # :StorePointer (0x60024B) 304 4983C5 04 ; add_r13, !4 # Increment IP 305 E8 D8FFFFFF ; call %Get_table_target # Get address of pointer 306 488B00 ; mov_rax,[rax] # Get pointer 307 4C29E8 ; sub_rax,r13 # target - ip 308 488905 0D000000 ; mov_[rip+DWORD],rax %table # put value in output 309 48C7C2 04000000 ; mov_rdx, %4 # set the size of chars we want 310 E8 ABFFFFFF ; call %print_chars 311 C3 ; ret 312 313 # :table (0x60026E) 314 315 # :ELF_end