stage0/Linux Bootstrap/AMD64/hex1_AMD64.hex0

330 lines
11 KiB
Plaintext

### Copyright (C) 2016 Jeremiah Orians
### Copyright (C) 2017 Jan Nieuwenhuizen <janneke@gnu.org>
### This file is part of stage0.
###
### stage0 is free software: you can redistribute it and/or modify
### it under the terms of the GNU General Public License as published by
### the Free Software Foundation, either version 3 of the License, or
### (at your option) any later version.
###
### stage0 is distributed in the hope that it will be useful,
### but WITHOUT ANY WARRANTY; without even the implied warranty of
### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
### GNU General Public License for more details.
###
### You should have received a copy of the GNU General Public License
### along with stage0. If not, see <http://www.gnu.org/licenses/>.
### elf64.hex2: 64 bit elf header in hex2
### if you wish to use this header, you need to add :ELF_end to the end of your
### M1 or hex2 files.
## ELF Header
#:ELF_base
7F 45 4C 46 ## e_ident[EI_MAG0-3] ELF's magic number
02 ## e_ident[EI_CLASS] Indicating 64 bit
01 ## e_ident[EI_DATA] Indicating little endianness
01 ## e_ident[EI_VERSION] Indicating original elf
00 ## e_ident[EI_OSABI] Set at 0 because none cares
00 ## e_ident[EI_ABIVERSION] See above
00 00 00 00 00 00 00 ## e_ident[EI_PAD]
02 00 ## e_type Indicating Executable
3E 00 ## e_machine Indicating AMD64
01 00 00 00 ## e_version Indicating original elf
78 00 60 00 00 00 00 00 ## e_entry Address of the entry point (Number of bytes this header is + Base Address)
40 00 00 00 00 00 00 00 ## e_phoff Address of program header table
00 00 00 00 00 00 00 00 ## e_shoff Address of section header table
00 00 00 00 ## e_flags
40 00 ## e_ehsize Indicating our 64 Byte header
38 00 ## e_phentsize size of a program header table
01 00 ## e_phnum number of entries in program table
00 00 ## e_shentsize size of a section header table
00 00 ## e_shnum number of entries in section table
00 00 ## e_shstrndx index of the section names
## Program Header
#:ELF_program_headers
01 00 00 00 ## p_type
06 00 00 00 ## Flags
00 00 00 00 00 00 00 00 ## p_offset
00 00 60 00 00 00 00 00 ## p_vaddr
00 00 60 00 00 00 00 00 ## p_physaddr
5D 03 00 00 00 00 00 00 ## p_filesz
5D 03 00 00 00 00 00 00 ## p_memsz
01 00 00 00 00 00 00 00 ## Required alignment
#:ELF_text
# Where the ELF Header is going to hit
# Simply jump to _start
# Our main function
# :_start
58 ; POP_RAX #·Get·the·number·of·arguments
5F ; POP_RDI #·Get·the·program·name$
5F ; POP_RDI #·Get·the·actual·input name
48C7C6 00000000 ; LOADI32_RSI %0 #·prepare·read_only
48C7C0 02000000 ; LOADI32_RAX %2 #·the·syscall·number·for·open()
0F05 ; SYSCALL # Now open that damn file
4989C1 ; COPY_RAX_to_R9 # Preserve the file pointer we were given
5F ; POP_RDI #·Get·the·actual·output name
48C7C6 41020000 ; LOADI32_RSI %577 # Prepare file as O_WRONLY|O_CREAT|O_TRUNC
48C7C2 C0010000 ; LOADI32_RDX %448 # Prepare file as RWX for owner only (700 in octal)
48C7C0 02000000 ; LOADI32_RAX %2 #·the·syscall·number·for·open()
0F05 ; SYSCALL # Now open that damn file
4989C2 ; COPY_RAX_to_R10 # Preserve the file pointer we were given
49C7C7 FFFFFFFF ; LOADI32_R15 %-1 # Our flag for byte processing
49C7C6 00000000 ; LOADI32_R14 %0 # temp storage for the sum
49C7C5 00000000 ; LOADI32_R13 %0 # Our starting IP
E8 39000000 ; CALLI32 %First_pass # Process it
# rewind input file
4C89CF ; COPY_R9_to_RDI # Using our input file
48C7C6 00000000 ; LOADI32_RSI %0 # Offset Zero
48C7C2 00000000 ; LOADI32_RDX %0 # Whence Zero
48C7C0 08000000 ; LOADI32_RAX %8 # lseek
0F05 ; SYSCALL
49C7C7 FFFFFFFF ; LOADI32_R15 %-1 # Our flag for byte processing
49C7C6 00000000 ; LOADI32_R14 %0 # temp storage for the sum
49C7C5 00000000 ; LOADI32_R13 %0 # Our starting IP
E8 EF000000 ; CALLI32 %Second_pass # Process it
E9 C7010000 ; JMP32 %Done
# :First_pass
E8 D2010000 ; CALLI32 %Read_byte
# Deal with EOF
483D FCFFFFFF ; CMPI32_RAX %-4
0F84 67000000 ; JE32 %First_pass_done
# Check for :
483D 3A000000 ; CMPI32_RAX %0x3a
0F85 05000000 ; JNE32 %First_pass_0
# Deal with label
E8 10020000 ; CALLI32 %StoreLabel
# :First_pass_0
# Check for %
483D 25000000 ; CMPI32_RAX %0x25
0F84 39000000 ; JE32 %First_pass_pointer
# Deal with everything else
E8 46000000 ; CALLI32 %hex # Process our char
# Deal with EOF
483D FCFFFFFF ; CMPI32_RAX %-4
0F84 39000000 ; JE32 %First_pass_done
# deal with -1 values
483D 00000000 ; CMPI32_RAX %0
0F8C B5FFFFFF ; JL32 %First_pass
# deal with toggle
4981FF 00000000 ; CMPI32_R15 %0
0F84 07000000 ; JE32 %First_pass_1
4981C5 01000000 ; ADDI32_to_R13 %1 # Increment IP
# :First_pass_1
49F7D7 ; NOT_R15
E9 99FFFFFF ; JMP32 %First_pass
# :First_pass_pointer
# Deal with Pointer to label
E8 6B010000 ; CALLI32 %Read_byte # Drop the char
4981C5 04000000 ; ADDI32_to_R13 %4 # Increment IP
E9 88FFFFFF ; JMP32 %First_pass # Loop again
# :First_pass_done
C3 ; RET
# :hex
# deal with EOF
483D FCFFFFFF ; CMPI32_RAX %-4
0F84 DC000000 ; JE32 %EOF
# deal with line comments starting with #
483D 23000000 ; CMPI32_RAX %0x23
0F84 E8000000 ; JE32 %ascii_comment
# deal with line comments starting with ;
483D 3B000000 ; CMPI32_RAX %0x3b
0F84 DC000000 ; JE32 %ascii_comment
# deal all ascii less than 0
483D 30000000 ; CMPI32_RAX %0x30
0F8C C8000000 ; JL32 %ascii_other
# deal with 0-9
483D 3A000000 ; CMPI32_RAX %0x3a
0F8C AD000000 ; JL32 %ascii_num
# deal with all ascii less than A
483D 41000000 ; CMPI32_RAX %0x41
0F8C B0000000 ; JL32 %ascii_other
# deal with A-F
483D 47000000 ; CMPI32_RAX %0x47
0F8C 9F000000 ; JL32 %ascii_high
#deal with all ascii less than a
483D 61000000 ; CMPI32_RAX %0x61
0F8C 98000000 ; JL32 %ascii_other
#deal with a-f
483D 67000000 ; CMPI32_RAX %0x67
0F8C 82000000 ; JL32 %ascii_low
# The rest that remains needs to be ignored
E9 87000000 ; JMP32 %ascii_other
# :Second_pass
E8 E8000000 ; CALLI32 %Read_byte
# Deal with EOF
483D FCFFFFFF ; CMPI32_RAX %-4
0F84 65000000 ; JE32 %Second_pass_done
# Simply drop the label
483D 3A000000 ; CMPI32_RAX %0x3a
0F85 0A000000 ; JNE32 %Second_pass_0
E8 CB000000 ; CALLI32 %Read_byte
E9 D9FFFFFF ; JMP32 %Second_pass
# :Second_pass_0
# Deal with % pointer
483D 25000000 ; CMPI32_RAX %0x25
0F85 0A000000 ; JNE32 %Second_pass_1
E8 19010000 ; CALLI32 %StorePointer
E9 C3FFFFFF ; JMP32 %Second_pass
# :Second_pass_1
# Deal with everything else
E8 4DFFFFFF ; CALLI32 %hex # Process our char
# Deal with EOF
483D FCFFFFFF ; CMPI32_RAX %-4
0F84 28000000 ; JE32 %Second_pass_done
# deal with -1 values
483D 00000000 ; CMPI32_RAX %0
0F8C A6FFFFFF ; JL32 %Second_pass
# deal with toggle
4981FF 00000000 ; CMPI32_R15 %0
0F84 4D000000 ; JE32 %print
# process first byte of pair
4989C6 ; COPY_RAX_to_R14
49C7C7 00000000 ; LOADI32_R15 %0
E9 8AFFFFFF ; JMP32 %Second_pass
# :Second_pass_done
C3 ; RET
# :EOF
C3 ; RET
# :ascii_num
4883E8 30 ; SUBI8_from_RAX !0x30
C3 ; RET
# :ascii_low
4883E8 57 ; SUBI8_from_RAX !0x57
C3 ; RET
# :ascii_high
4883E8 37 ; SUBI8_from_RAX !0x37
C3 ; RET
# :ascii_other
48C7C0 FFFFFFFF ; LOADI32_RAX %-1
C3 ; RET
# :ascii_comment
E8 59000000 ; CALLI32 %Read_byte
483D 0D000000 ; CMPI32_RAX %0xd
0F84 0C000000 ; JE32 %ascii_comment_cr
483D 0A000000 ; CMPI32_RAX %0xa
0F85 E3FFFFFF ; JNE32 %ascii_comment
# :ascii_comment_cr
48C7C0 FFFFFFFF ; LOADI32_RAX %-1
C3 ; RET
# process second byte of pair
# :print
# update the sum and store in output
49C1E6 04 ; SHL8_R14 !4
4C01F0 ; ADD_R14_to_RAX
880425 5D036000 ; STORE8_al_Absolute32 &table
# flip the toggle
49F7D7 ; NOT_R15
# Print our first Hex
48C7C2 01000000 ; LOADI32_RDX %1 # set the size of chars we want
E8 53000000 ; CALLI32 %print_chars
4981C5 01000000 ; ADDI32_to_R13 %1 # Increment IP
E9 23FFFFFF ; JMP32 %Second_pass
# :Done
# program completed Successfully
48C7C7 00000000 ; LOADI32_RDI %0 # All is well
48C7C0 3C000000 ; LOADI32_RAX %0x3c # put the exit syscall number in eax
0F05 ; SYSCALL # Call it a good day
# :Read_byte
# Attempt to read 1 byte from STDIN
48C7C2 01000000 ; LOADI32_RDX %1 # set the size of chars we want
48C7C6 5D036000 ; LOADI32_RSI &table # Where to put it
4C89CF ; COPY_R9_to_RDI # Where are we reading from
48C7C0 00000000 ; LOADI32_RAX %0 # the syscall number for read
0F05 ; SYSCALL # call the Kernel
4885C0 ; TEST_RAX_RAX # check what we got
0F84 0C000000 ; JE32 %Read_byte_1 # Got EOF call it done
# load byte
8A0425 5D036000 ; LOAD8_al_Absolute32 &table # load char
480FB6C0 ; MOVZBQ_RAX_AL # We have to zero extend it to use it
C3 ; RET
# Deal with EOF
# :Read_byte_1
48C7C0 FCFFFFFF ; LOADI32_RAX %-4 # Put EOF in rax
C3 ; RET
# :print_chars
48C7C6 5D036000 ; LOADI32_RSI &table # What we are writing
4C89D7 ; COPY_R10_to_RDI # Write to target file
48C7C0 01000000 ; LOADI32_RAX %1 # the syscall number for write
0F05 ; SYSCALL # call the Kernel
C3 ; RET
# :Get_table_target
E8 B0FFFFFF ; CALLI32 %Read_byte # Get single char label
48C1E0 03 ; SHL8_RAX !3 # Each label in table takes 8 bytes to store
4805 5D036000 ; ADDI32_to_RAX &table # Calculate offset
C3 ; RET
# :StoreLabel
E8 EBFFFFFF ; CALLI32 %Get_table_target
4C8928 ; STORE32_R13_to_Address_in_RAX # Write out pointer to table
C3 ; RET
# :StorePointer
4981C5 04000000 ; ADDI32_to_R13 %4 # Increment IP
E8 DBFFFFFF ; CALLI32 %Get_table_target # Get address of pointer
678B00 ; LOAD32_Address_in_RAX_into_RAX # Get pointer
4C29E8 ; SUB_R13_from_RAX # target - ip
890425 5D036000 ; STORE32_RAX_Absolute32 &table # put value in output
48C7C2 04000000 ; LOADI32_RDX %4 # set the size of chars we want
E8 AEFFFFFF ; CALLI32 %print_chars
C3 ; RET
# :table