New paste Repaste Download
## Copyright (C) 2026 Christian Westrom
## 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/>.
# hex0 - A minimal hex loader for RISC-V (bare metal, QEMU virt)
# This file is generated from baremetal/hex0.hex0.
# Regenerate it with: just annotate_hex0
# Reads hex digits from UART, converts pairs to bytes, stores in memory.
# On Ctrl-D, jumps to the loaded code.
# Audited by Christian Westrom: 2026-03-15, 08:53 UTC
; Register use:
; s0: holder (first nibble)
; s1: toggle (1 = first nibble, 0 = second nibble)
; s2: pointer to code buffer
# _start: (0x0)
    # Setup stack pointer with 0x1903
    # Combined intent at 0x0000-0x0004: auipc/addi builds pc-relative sp = 0x3190 (PC + 0x3000 + 0x190)
    # Instruction at 0x0000: auipc sp, 0x3
    # Hex (LE):  17 31 00 00  →  Word: 0x00003117
    # Binary: 00000000 00000000 00110001 00010111
    # Fields: [imm[31:12]=0x3] [rd=2(sp)] [opcode=0x17]
    17 31 00 00
    # Instruction at 0x0004: addi sp, sp, 0x190
    # Hex (LE):  13 01 01 19  →  Word: 0x19010113
    # Binary: 00011001 00000001 00000001 00010011
    # Fields: [imm[11:0]=0x190] [rs1=2(sp)] [f3=0b000] [rd=2(sp)] [opcode=0x13]
    13 01 01 19
    # Setup code buffer pointer
    # Combined intent at 0x0008-0x000C: auipc/addi builds pc-relative s2 = 0x1190 (PC + 0x1000 + 0x188)
    # Instruction at 0x0008: auipc s2, 0x1
    # Hex (LE):  17 19 00 00  →  Word: 0x00001917
    # Binary: 00000000 00000000 00011001 00010111
    # Fields: [imm[31:12]=0x1] [rd=18(s2)] [opcode=0x17]
    17 19 00 00
    # Instruction at 0x000C: addi s2, s2, 0x188
    # Hex (LE):  13 09 89 18  →  Word: 0x18890913
    # Binary: 00011000 10001001 00001001 00010011
    # Fields: [imm[11:0]=0x188] [rs1=18(s2)] [f3=0b000] [rd=18(s2)] [opcode=0x13]
    13 09 89 18
    # Initialize toggle
    # Instruction at 0x0010: addi s1, x0, 1
    # Hex (LE):  93 04 10 00  →  Word: 0x00100493
    # Binary: 00000000 00010000 00000100 10010011
    # Fields: [imm[11:0]=0x1] [rs1=0(x0)] [f3=0b000] [rd=9(s1)] [opcode=0x13]
    93 04 10 00
    # Initialize holder
    # Instruction at 0x0014: addi s0, x0, 0
    # Hex (LE):  13 04 00 00  →  Word: 0x00000413
    # Binary: 00000000 00000000 00000100 00010011
    # Fields: [imm[11:0]=0x0] [rs1=0(x0)] [f3=0b000] [rd=8(s0)] [opcode=0x13]
    13 04 00 00
# main: (0x18)
    # Read a character
    # Instruction at 0x0018: jal ra, 0x0060
    # Hex (LE):  EF 00 80 04  →  Word: 0x048000EF
    # Binary: 00000100 10000000 00000000 11101111
    # Fields: [imm[20]=0b0] [imm[10:1]=0b0000100100] [imm[11]=0b0] [imm[19:12]=0x0] [rd=1(ra)] [opcode=0x6F]
    EF 00 80 04
    # Check for Ctrl-D (0x4)
    # Load 0x4 into t0
    # Instruction at 0x001C: addi t0, x0, 4
    # Hex (LE):  93 02 40 00  →  Word: 0x00400293
    # Binary: 00000000 01000000 00000010 10010011
    # Fields: [imm[11:0]=0x4] [rs1=0(x0)] [f3=0b000] [rd=5(t0)] [opcode=0x13]
    93 02 40 00
    # If we did not get 0x4, start processing input
    # Instruction at 0x0020: bne a0, t0, 0x002C
    # Hex (LE):  63 16 55 00  →  Word: 0x00551663
    # Binary: 00000000 01010101 00010110 01100011
    # Fields: [imm[12]=0b0] [imm[10:5]=0b000000] [rs2=5(t0)] [rs1=10(a0)] [f3=0b001] [imm[4:1]=0b0110] [imm[11]=0b0] [opcode=0x63]
    63 16 55 00
    # If we're here, we did get 0x4, so we can go execute the code
    # Instruction at 0x0024: jal ra, 0x010C
    # Hex (LE):  EF 00 80 0E  →  Word: 0x0E8000EF
    # Binary: 00001110 10000000 00000000 11101111
    # Fields: [imm[20]=0b0] [imm[10:1]=0b0001110100] [imm[11]=0b0] [imm[19:12]=0x0] [rd=1(ra)] [opcode=0x6F]
    EF 00 80 0E
    # Otherwise, go back to the top of the main loop to read characters
    # Instruction at 0x0028: jal x0, 0x0018
    # Hex (LE):  6F F0 1F FF  →  Word: 0xFF1FF06F
    # Binary: 11111111 00011111 11110000 01101111
    # Fields: [imm[20]=0b1] [imm[10:1]=0b1111111000] [imm[11]=0b1] [imm[19:12]=0xFF] [rd=0(x0)] [opcode=0x6F]
    6F F0 1F FF
# process_input: (0x2C)
    # The first thing we do is go to the hex processing routine
    # Instruction at 0x002C: jal ra, 0x0080
    # Hex (LE):  EF 00 40 05  →  Word: 0x054000EF
    # Binary: 00000101 01000000 00000000 11101111
    # Fields: [imm[20]=0b0] [imm[10:1]=0b0000101010] [imm[11]=0b0] [imm[19:12]=0x0] [rd=1(ra)] [opcode=0x6F]
    EF 00 40 05
    # If a0 comes back less than 0 from the hex routine, go back to the main loop
    # Instruction at 0x0030: blt a0, x0, 0x0018
    # Hex (LE):  E3 44 05 FE  →  Word: 0xFE0544E3
    # Binary: 11111110 00000101 01000100 11100011
    # Fields: [imm[12]=0b1] [imm[10:5]=0b111111] [rs2=0(x0)] [rs1=10(a0)] [f3=0b100] [imm[4:1]=0b0100] [imm[11]=0b1] [opcode=0x63]
    E3 44 05 FE
    # Else, if s1 has been set to zero, we process the second nibble
    # Instruction at 0x0034: beq s1, x0, 0x0044
    # Hex (LE):  63 88 04 00  →  Word: 0x00048863
    # Binary: 00000000 00000100 10001000 01100011
    # Fields: [imm[12]=0b0] [imm[10:5]=0b000000] [rs2=0(x0)] [rs1=9(s1)] [f3=0b000] [imm[4:1]=0b1000] [imm[11]=0b0] [opcode=0x63]
    63 88 04 00
    # In any case, we extract the first nibble from the lower 4 bits by using a mask
    # Instruction at 0x0038: andi s0, a0, 0xF
    # Hex (LE):  13 74 F5 00  →  Word: 0x00F57413
    # Binary: 00000000 11110101 01110100 00010011
    # Fields: [imm[11:0]=0xF] [rs1=10(a0)] [f3=0b111] [rd=8(s0)] [opcode=0x13]
    13 74 F5 00
    # We then reset s1 back to zero to prepare to go back to the main loop
    # Instruction at 0x003C: addi s1, x0, 0
    # Hex (LE):  93 04 00 00  →  Word: 0x00000493
    # Binary: 00000000 00000000 00000100 10010011
    # Fields: [imm[11:0]=0x0] [rs1=0(x0)] [f3=0b000] [rd=9(s1)] [opcode=0x13]
    93 04 00 00
    # Processing one hex is done
    # Instruction at 0x0040: jal x0, 0x0018
    # Hex (LE):  6F F0 9F FD  →  Word: 0xFD9FF06F
    # Binary: 11111101 10011111 11110000 01101111
    # Fields: [imm[20]=0b1] [imm[10:1]=0b1111101100] [imm[11]=0b1] [imm[19:12]=0xFF] [rd=0(x0)] [opcode=0x6F]
    6F F0 9F FD
# process_second_nibble: (0x44)
    # We shift the first nibble by 4
    # Instruction at 0x0044: slli s0, s0, 4
    # Hex (LE):  13 14 44 00  →  Word: 0x00441413
    # Binary: 00000000 01000100 00010100 00010011
    # Fields: [imm[11:0]=0x4] [rs1=8(s0)] [f3=0b001] [rd=8(s0)] [opcode=0x13]
    13 14 44 00
    # Then we extract the lower for bits from a0
    # Instruction at 0x0048: andi a0, a0, 0xF
    # Hex (LE):  13 75 F5 00  →  Word: 0x00F57513
    # Binary: 00000000 11110101 01110101 00010011
    # Fields: [imm[11:0]=0xF] [rs1=10(a0)] [f3=0b111] [rd=10(a0)] [opcode=0x13]
    13 75 F5 00
    # We combine the first (shifted) and second nibbles
    # Instruction at 0x004C: add a0, s0, a0
    # Hex (LE):  33 05 A4 00  →  Word: 0x00A40533
    # Binary: 00000000 10100100 00000101 00110011
    # Fields: [funct7=0b0000000] [rs2=10(a0)] [rs1=8(s0)] [f3=0b000] [rd=10(a0)] [opcode=0x33]
    33 05 A4 00
    # Now that we've processed the second nibble we'll flag it in s1
    # Instruction at 0x0050: addi s1, x0, 1
    # Hex (LE):  93 04 10 00  →  Word: 0x00100493
    # Binary: 00000000 00010000 00000100 10010011
    # Fields: [imm[11:0]=0x1] [rs1=0(x0)] [f3=0b000] [rd=9(s1)] [opcode=0x13]
    93 04 10 00
    # Write out the byte to the buffer
    # Instruction at 0x0054: sb a0, 0(s2)
    # Hex (LE):  23 00 A9 00  →  Word: 0x00A90023
    # Binary: 00000000 10101001 00000000 00100011
    # Fields: [imm[11:5]=0b0000000] [rs2=10(a0)] [rs1=18(s2)] [f3=0b000] [imm[4:0]=0b00000] [opcode=0x23]
    23 00 A9 00
    # Update the pointer to the buffer
    # Instruction at 0x0058: addi s2, s2, 1
    # Hex (LE):  13 09 19 00  →  Word: 0x00190913
    # Binary: 00000000 00011001 00001001 00010011
    # Fields: [imm[11:0]=0x1] [rs1=18(s2)] [f3=0b000] [rd=18(s2)] [opcode=0x13]
    13 09 19 00
    # Jump back to the main loop
    # Instruction at 0x005C: jal x0, 0x0018
    # Hex (LE):  6F F0 DF FB  →  Word: 0xFBDFF06F
    # Binary: 11111011 11011111 11110000 01101111
    # Fields: [imm[20]=0b1] [imm[10:1]=0b1111011110] [imm[11]=0b1] [imm[19:12]=0xFF] [rd=0(x0)] [opcode=0x6F]
    6F F0 DF FB
# read_char: (0x60)
    # Load UART RX into t0
    # Combined intent at 0x0060-0x0064: lui/addiw builds t0 = 0x10000005 (0x10000000 + 5)
    # Instruction at 0x0060: lui t0, 0x10000
    # Hex (LE):  B7 02 00 10  →  Word: 0x100002B7
    # Binary: 00010000 00000000 00000010 10110111
    # Fields: [imm[31:12]=0x10000] [rd=5(t0)] [opcode=0x37]
    B7 02 00 10
    # Instruction at 0x0064: addiw t0, t0, 5
    # Hex (LE):  9B 82 52 00  →  Word: 0x0052829B
    # Binary: 00000000 01010010 10000010 10011011
    # Fields: [imm[11:0]=0x5] [rs1=5(t0)] [f3=0b000] [rd=5(t0)] [opcode=0x1B]
    9B 82 52 00
# poll_rx: (0x68)
    # Load a byte from RX to a0
    # Instruction at 0x0068: lb a0, 0(t0)
    # Hex (LE):  03 85 02 00  →  Word: 0x00028503
    # Binary: 00000000 00000010 10000101 00000011
    # Fields: [imm[11:0]=0x0] [rs1=5(t0)] [f3=0b000] [rd=10(a0)] [opcode=0x03]
    03 85 02 00
    # Check if a0 is odd
    # Instruction at 0x006C: andi a0, a0, 0x1
    # Hex (LE):  13 75 15 00  →  Word: 0x00157513
    # Binary: 00000000 00010101 01110101 00010011
    # Fields: [imm[11:0]=0x1] [rs1=10(a0)] [f3=0b111] [rd=10(a0)] [opcode=0x13]
    13 75 15 00
    # If a0 is 0 then RX is not ready so jump back
    # Instruction at 0x0070: beq a0, x0, 0x0068
    # Hex (LE):  E3 0C 05 FE  →  Word: 0xFE050CE3
    # Binary: 11111110 00000101 00001100 11100011
    # Fields: [imm[12]=0b1] [imm[10:5]=0b111111] [rs2=0(x0)] [rs1=10(a0)] [f3=0b000] [imm[4:1]=0b1100] [imm[11]=0b1] [opcode=0x63]
    E3 0C 05 FE
    # Set t0 to 0x10000000 (UART data register)
    # Instruction at 0x0074: lui t0, 0x10000
    # Hex (LE):  B7 02 00 10  →  Word: 0x100002B7
    # Binary: 00010000 00000000 00000010 10110111
    # Fields: [imm[31:12]=0x10000] [rd=5(t0)] [opcode=0x37]
    B7 02 00 10
    # Load a byte from the data register
    # Instruction at 0x0078: lb a0, 0(t0)
    # Hex (LE):  03 85 02 00  →  Word: 0x00028503
    # Binary: 00000000 00000010 10000101 00000011
    # Fields: [imm[11:0]=0x0] [rs1=5(t0)] [f3=0b000] [rd=10(a0)] [opcode=0x03]
    03 85 02 00
    # Jump back to address in ra
    # Instruction at 0x007C: jalr x0, ra, 0
    # Hex (LE):  67 80 00 00  →  Word: 0x00008067
    # Binary: 00000000 00000000 10000000 01100111
    # Fields: [imm[11:0]=0x0] [rs1=1(ra)] [f3=0b000] [rd=0(x0)] [opcode=0x67]
    67 80 00 00
# hex: (0x80)
    # Deal with line comments starting with #
    # Instruction at 0x0080: addi t0, x0, 0x23
    # Hex (LE):  93 02 30 02  →  Word: 0x02300293
    # Binary: 00000010 00110000 00000010 10010011
    # Fields: [imm[11:0]=0x23] [rs1=0(x0)] [f3=0b000] [rd=5(t0)] [opcode=0x13]
    93 02 30 02
    # Instruction at 0x0084: beq a0, t0, 0x00E4
    # Hex (LE):  63 00 55 06  →  Word: 0x06550063
    # Binary: 00000110 01010101 00000000 01100011
    # Fields: [imm[12]=0b0] [imm[10:5]=0b000011] [rs2=5(t0)] [rs1=10(a0)] [f3=0b000] [imm[4:1]=0b0000] [imm[11]=0b0] [opcode=0x63]
    63 00 55 06
    # Deal with line comments starting with ;
    # Instruction at 0x0088: addi t0, x0, 0x3B
    # Hex (LE):  93 02 B0 03  →  Word: 0x03B00293
    # Binary: 00000011 10110000 00000010 10010011
    # Fields: [imm[11:0]=0x3B] [rs1=0(x0)] [f3=0b000] [rd=5(t0)] [opcode=0x13]
    93 02 B0 03
    # Instruction at 0x008C: beq a0, t0, 0x00E4
    # Hex (LE):  63 0C 55 04  →  Word: 0x04550C63
    # Binary: 00000100 01010101 00001100 01100011
    # Fields: [imm[12]=0b0] [imm[10:5]=0b000010] [rs2=5(t0)] [rs1=10(a0)] [f3=0b000] [imm[4:1]=0b1100] [imm[11]=0b0] [opcode=0x63]
    63 0C 55 04
    # Deal with all ASCII less than '0'
    # Instruction at 0x0090: addi t0, x0, 0x30
    # Hex (LE):  93 02 00 03  →  Word: 0x03000293
    # Binary: 00000011 00000000 00000010 10010011
    # Fields: [imm[11:0]=0x30] [rs1=0(x0)] [f3=0b000] [rd=5(t0)] [opcode=0x13]
    93 02 00 03
    # Instruction at 0x0094: blt a0, t0, 0x00DC
    # Hex (LE):  63 44 55 04  →  Word: 0x04554463
    # Binary: 00000100 01010101 01000100 01100011
    # Fields: [imm[12]=0b0] [imm[10:5]=0b000010] [rs2=5(t0)] [rs1=10(a0)] [f3=0b100] [imm[4:1]=0b0100] [imm[11]=0b0] [opcode=0x63]
    63 44 55 04
    # Deal with '0' through '9'
    # Instruction at 0x0098: addi t0, x0, 0x3A
    # Hex (LE):  93 02 A0 03  →  Word: 0x03A00293
    # Binary: 00000011 10100000 00000010 10010011
    # Fields: [imm[11:0]=0x3A] [rs1=0(x0)] [f3=0b000] [rd=5(t0)] [opcode=0x13]
    93 02 A0 03
    # Instruction at 0x009C: blt a0, t0, 0x00C4
    # Hex (LE):  63 44 55 02  →  Word: 0x02554463
    # Binary: 00000010 01010101 01000100 01100011
    # Fields: [imm[12]=0b0] [imm[10:5]=0b000001] [rs2=5(t0)] [rs1=10(a0)] [f3=0b100] [imm[4:1]=0b0100] [imm[11]=0b0] [opcode=0x63]
    63 44 55 02
    # Deal with all ASCII less than 'A'
    # Instruction at 0x00A0: addi t0, x0, 0x41
    # Hex (LE):  93 02 10 04  →  Word: 0x04100293
    # Binary: 00000100 00010000 00000010 10010011
    # Fields: [imm[11:0]=0x41] [rs1=0(x0)] [f3=0b000] [rd=5(t0)] [opcode=0x13]
    93 02 10 04
    # Instruction at 0x00A4: blt a0, t0, 0x00DC
    # Hex (LE):  63 4C 55 02  →  Word: 0x02554C63
    # Binary: 00000010 01010101 01001100 01100011
    # Fields: [imm[12]=0b0] [imm[10:5]=0b000001] [rs2=5(t0)] [rs1=10(a0)] [f3=0b100] [imm[4:1]=0b1100] [imm[11]=0b0] [opcode=0x63]
    63 4C 55 02
    # Deal with 'A' through 'F'
    # Instruction at 0x00A8: addi t0, x0, 0x47
    # Hex (LE):  93 02 70 04  →  Word: 0x04700293
    # Binary: 00000100 01110000 00000010 10010011
    # Fields: [imm[11:0]=0x47] [rs1=0(x0)] [f3=0b000] [rd=5(t0)] [opcode=0x13]
    93 02 70 04
    # Instruction at 0x00AC: blt a0, t0, 0x00D4
    # Hex (LE):  63 44 55 02  →  Word: 0x02554463
    # Binary: 00000010 01010101 01000100 01100011
    # Fields: [imm[12]=0b0] [imm[10:5]=0b000001] [rs2=5(t0)] [rs1=10(a0)] [f3=0b100] [imm[4:1]=0b0100] [imm[11]=0b0] [opcode=0x63]
    63 44 55 02
    # Deal with all ASCII less than 'a'
    # Instruction at 0x00B0: addi t0, x0, 0x61
    # Hex (LE):  93 02 10 06  →  Word: 0x06100293
    # Binary: 00000110 00010000 00000010 10010011
    # Fields: [imm[11:0]=0x61] [rs1=0(x0)] [f3=0b000] [rd=5(t0)] [opcode=0x13]
    93 02 10 06
    # Instruction at 0x00B4: blt a0, t0, 0x00DC
    # Hex (LE):  63 44 55 02  →  Word: 0x02554463
    # Binary: 00000010 01010101 01000100 01100011
    # Fields: [imm[12]=0b0] [imm[10:5]=0b000001] [rs2=5(t0)] [rs1=10(a0)] [f3=0b100] [imm[4:1]=0b0100] [imm[11]=0b0] [opcode=0x63]
    63 44 55 02
    # Deal with 'a' through 'f'
    # Instruction at 0x00B8: addi t0, x0, 0x67
    # Hex (LE):  93 02 70 06  →  Word: 0x06700293
    # Binary: 00000110 01110000 00000010 10010011
    # Fields: [imm[11:0]=0x67] [rs1=0(x0)] [f3=0b000] [rd=5(t0)] [opcode=0x13]
    93 02 70 06
    # Instruction at 0x00BC: blt a0, t0, 0x00CC
    # Hex (LE):  63 48 55 00  →  Word: 0x00554863
    # Binary: 00000000 01010101 01001000 01100011
    # Fields: [imm[12]=0b0] [imm[10:5]=0b000000] [rs2=5(t0)] [rs1=10(a0)] [f3=0b100] [imm[4:1]=0b1000] [imm[11]=0b0] [opcode=0x63]
    63 48 55 00
    # Deal with everything else
    # Instruction at 0x00C0: jal x0, 0x00DC
    # Hex (LE):  6F 00 C0 01  →  Word: 0x01C0006F
    # Binary: 00000001 11000000 00000000 01101111
    # Fields: [imm[20]=0b0] [imm[10:1]=0b0000001110] [imm[11]=0b0] [imm[19:12]=0x0] [rd=0(x0)] [opcode=0x6F]
    6F 00 C0 01
# ascii_num: (0xC4)
    # Numbers are passed back as is
    # Instruction at 0x00C4: addi a0, a0, -48
    # Hex (LE):  13 05 05 FD  →  Word: 0xFD050513
    # Binary: 11111101 00000101 00000101 00010011
    # Fields: [imm[11:0]=0xFD0] [rs1=10(a0)] [f3=0b000] [rd=10(a0)] [opcode=0x13]
    13 05 05 FD
    # Instruction at 0x00C8: jalr x0, ra, 0
    # Hex (LE):  67 80 00 00  →  Word: 0x00008067
    # Binary: 00000000 00000000 10000000 01100111
    # Fields: [imm[11:0]=0x0] [rs1=1(ra)] [f3=0b000] [rd=0(x0)] [opcode=0x67]
    67 80 00 00
# ascii_low: (0xCC)
    # Simple ascii arithmetic. Lowercase 'a' through 'f' -87 gives us the hex number we want
    # Instruction at 0x00CC: addi a0, a0, -87
    # Hex (LE):  13 05 95 FA  →  Word: 0xFA950513
    # Binary: 11111010 10010101 00000101 00010011
    # Fields: [imm[11:0]=0xFA9] [rs1=10(a0)] [f3=0b000] [rd=10(a0)] [opcode=0x13]
    13 05 95 FA
    # Instruction at 0x00D0: jalr x0, ra, 0
    # Hex (LE):  67 80 00 00  →  Word: 0x00008067
    # Binary: 00000000 00000000 10000000 01100111
    # Fields: [imm[11:0]=0x0] [rs1=1(ra)] [f3=0b000] [rd=0(x0)] [opcode=0x67]
    67 80 00 00
# ascii_high: (0xD4)
    # Simple ascii arithmetic. Uppercase 'A' through 'F' -55 gives us the hex number we want
    # Instruction at 0x00D4: addi a0, a0, -55
    # Hex (LE):  13 05 95 FC  →  Word: 0xFC950513
    # Binary: 11111100 10010101 00000101 00010011
    # Fields: [imm[11:0]=0xFC9] [rs1=10(a0)] [f3=0b000] [rd=10(a0)] [opcode=0x13]
    13 05 95 FC
    # Instruction at 0x00D8: jalr x0, ra, 0
    # Hex (LE):  67 80 00 00  →  Word: 0x00008067
    # Binary: 00000000 00000000 10000000 01100111
    # Fields: [imm[11:0]=0x0] [rs1=1(ra)] [f3=0b000] [rd=0(x0)] [opcode=0x67]
    67 80 00 00
# ignore_byte: (0xDC)
    # Returns -1 to signal the caller to discard this character.
    # s0 (holder) and s1 (toggle) are NOT modified here or in ascii_comment,
    # so nibble state is preserved across ignored characters and comments.
    #
    # Behavioral note: non-hex characters (including whitespace, newlines, and
    # comments) are transparent to nibble pairing. This means hex digits CAN be
    # split across a comment or newline and will still combine into one byte.
    # Example: "A # comment\nB" produces byte 0xAB.
    # This matches the hex0 spec (non-hex = ignored), but may be surprising.
    #
    # Also: if Ctrl-D arrives while s1==0 (a first nibble was stored but no
    # second arrived), the partial nibble in s0 is silently discarded.
    # Instruction at 0x00DC: addi a0, x0, -1
    # Hex (LE):  13 05 F0 FF  →  Word: 0xFFF00513
    # Binary: 11111111 11110000 00000101 00010011
    # Fields: [imm[11:0]=0xFFF] [rs1=0(x0)] [f3=0b000] [rd=10(a0)] [opcode=0x13]
    13 05 F0 FF
    # Instruction at 0x00E0: jalr x0, ra, 0
    # Hex (LE):  67 80 00 00  →  Word: 0x00008067
    # Binary: 00000000 00000000 10000000 01100111
    # Fields: [imm[11:0]=0x0] [rs1=1(ra)] [f3=0b000] [rd=0(x0)] [opcode=0x67]
    67 80 00 00
# ascii_comment: (0xE4)
    # We're going to loop multiple times, so we'll allocate 16 bytes of stack space
    # Instruction at 0x00E4: addi sp, sp, -16
    # Hex (LE):  13 01 01 FF  →  Word: 0xFF010113
    # Binary: 11111111 00000001 00000001 00010011
    # Fields: [imm[11:0]=0xFF0] [rs1=2(sp)] [f3=0b000] [rd=2(sp)] [opcode=0x13]
    13 01 01 FF
    # Then we'll save the return address before reading more characters
    # Instruction at 0x00E8: sd ra, 0(sp)
    # Hex (LE):  23 30 11 00  →  Word: 0x00113023
    # Binary: 00000000 00010001 00110000 00100011
    # Fields: [imm[11:5]=0b0000000] [rs2=1(ra)] [rs1=2(sp)] [f3=0b011] [imm[4:0]=0b00000] [opcode=0x23]
    23 30 11 00
# ascii_comment_loop: (0xEC)
    # This loop will read characters until we're done with comments
    # Instruction at 0x00EC: jal ra, 0x0060
    # Hex (LE):  EF F0 5F F7  →  Word: 0xF75FF0EF
    # Binary: 11110111 01011111 11110000 11101111
    # Fields: [imm[20]=0b1] [imm[10:1]=0b1110111010] [imm[11]=0b1] [imm[19:12]=0xFF] [rd=1(ra)] [opcode=0x6F]
    EF F0 5F F7
    # Set t0 to carriage return
    # Instruction at 0x00F0: addi t0, x0, 0xD
    # Hex (LE):  93 02 D0 00  →  Word: 0x00D00293
    # Binary: 00000000 11010000 00000010 10010011
    # Fields: [imm[11:0]=0xD] [rs1=0(x0)] [f3=0b000] [rd=5(t0)] [opcode=0x13]
    93 02 D0 00
    # Check if we got carriage return we're done
    # Instruction at 0x00F4: beq a0, t0, 0x0100
    # Hex (LE):  63 06 55 00  →  Word: 0x00550663
    # Binary: 00000000 01010101 00000110 01100011
    # Fields: [imm[12]=0b0] [imm[10:5]=0b000000] [rs2=5(t0)] [rs1=10(a0)] [f3=0b000] [imm[4:1]=0b0110] [imm[11]=0b0] [opcode=0x63]
    63 06 55 00
    # Set t0 to newline
    # Instruction at 0x00F8: addi t0, x0, 0xA
    # Hex (LE):  93 02 A0 00  →  Word: 0x00A00293
    # Binary: 00000000 10100000 00000010 10010011
    # Fields: [imm[11:0]=0xA] [rs1=0(x0)] [f3=0b000] [rd=5(t0)] [opcode=0x13]
    93 02 A0 00
    # Loop back if we didn't get a newline
    # Instruction at 0x00FC: bne a0, t0, 0x00EC
    # Hex (LE):  E3 18 55 FE  →  Word: 0xFE5518E3
    # Binary: 11111110 01010101 00011000 11100011
    # Fields: [imm[12]=0b1] [imm[10:5]=0b111111] [rs2=5(t0)] [rs1=10(a0)] [f3=0b001] [imm[4:1]=0b1000] [imm[11]=0b1] [opcode=0x63]
    E3 18 55 FE
# ascii_comment_done: (0x100)
    # We're here if we got \r or \n, so we'll restore the return address
    # Instruction at 0x0100: ld ra, 0(sp)
    # Hex (LE):  83 30 01 00  →  Word: 0x00013083
    # Binary: 00000000 00000001 00110000 10000011
    # Fields: [imm[11:0]=0x0] [rs1=2(sp)] [f3=0b011] [rd=1(ra)] [opcode=0x03]
    83 30 01 00
    # Deallocate the 16 bytes of stack space
    # Instruction at 0x0104: addi sp, sp, 0x10
    # Hex (LE):  13 01 01 01  →  Word: 0x01010113
    # Binary: 00000001 00000001 00000001 00010011
    # Fields: [imm[11:0]=0x10] [rs1=2(sp)] [f3=0b000] [rd=2(sp)] [opcode=0x13]
    13 01 01 01
    # Jump back to ignore_byte, which returns -1 to ignore as it's not program bytes
    # Instruction at 0x0108: jal x0, 0x00DC
    # Hex (LE):  6F F0 5F FD  →  Word: 0xFD5FF06F
    # Binary: 11111101 01011111 11110000 01101111
    # Fields: [imm[20]=0b1] [imm[10:1]=0b1111101010] [imm[11]=0b1] [imm[19:12]=0xFF] [rd=0(x0)] [opcode=0x6F]
    6F F0 5F FD
# execute_code: (0x10C)
    # Zero all registers before jump (except sp and code location)
    # Instruction at 0x010C: addi a0, x0, 0
    # Hex (LE):  13 05 00 00  →  Word: 0x00000513
    # Binary: 00000000 00000000 00000101 00010011
    # Fields: [imm[11:0]=0x0] [rs1=0(x0)] [f3=0b000] [rd=10(a0)] [opcode=0x13]
    13 05 00 00
    # Instruction at 0x0110: addi a1, x0, 0
    # Hex (LE):  93 05 00 00  →  Word: 0x00000593
    # Binary: 00000000 00000000 00000101 10010011
    # Fields: [imm[11:0]=0x0] [rs1=0(x0)] [f3=0b000] [rd=11(a1)] [opcode=0x13]
    93 05 00 00
    # Instruction at 0x0114: addi a2, x0, 0
    # Hex (LE):  13 06 00 00  →  Word: 0x00000613
    # Binary: 00000000 00000000 00000110 00010011
    # Fields: [imm[11:0]=0x0] [rs1=0(x0)] [f3=0b000] [rd=12(a2)] [opcode=0x13]
    13 06 00 00
    # Instruction at 0x0118: addi a3, x0, 0
    # Hex (LE):  93 06 00 00  →  Word: 0x00000693
    # Binary: 00000000 00000000 00000110 10010011
    # Fields: [imm[11:0]=0x0] [rs1=0(x0)] [f3=0b000] [rd=13(a3)] [opcode=0x13]
    93 06 00 00
    # Instruction at 0x011C: addi a4, x0, 0
    # Hex (LE):  13 07 00 00  →  Word: 0x00000713
    # Binary: 00000000 00000000 00000111 00010011
    # Fields: [imm[11:0]=0x0] [rs1=0(x0)] [f3=0b000] [rd=14(a4)] [opcode=0x13]
    13 07 00 00
    # Instruction at 0x0120: addi a5, x0, 0
    # Hex (LE):  93 07 00 00  →  Word: 0x00000793
    # Binary: 00000000 00000000 00000111 10010011
    # Fields: [imm[11:0]=0x0] [rs1=0(x0)] [f3=0b000] [rd=15(a5)] [opcode=0x13]
    93 07 00 00
    # Instruction at 0x0124: addi a6, x0, 0
    # Hex (LE):  13 08 00 00  →  Word: 0x00000813
    # Binary: 00000000 00000000 00001000 00010011
    # Fields: [imm[11:0]=0x0] [rs1=0(x0)] [f3=0b000] [rd=16(a6)] [opcode=0x13]
    13 08 00 00
    # Instruction at 0x0128: addi a7, x0, 0
    # Hex (LE):  93 08 00 00  →  Word: 0x00000893
    # Binary: 00000000 00000000 00001000 10010011
    # Fields: [imm[11:0]=0x0] [rs1=0(x0)] [f3=0b000] [rd=17(a7)] [opcode=0x13]
    93 08 00 00
    # Instruction at 0x012C: addi t0, x0, 0
    # Hex (LE):  93 02 00 00  →  Word: 0x00000293
    # Binary: 00000000 00000000 00000010 10010011
    # Fields: [imm[11:0]=0x0] [rs1=0(x0)] [f3=0b000] [rd=5(t0)] [opcode=0x13]
    93 02 00 00
    # Instruction at 0x0130: addi t1, x0, 0
    # Hex (LE):  13 03 00 00  →  Word: 0x00000313
    # Binary: 00000000 00000000 00000011 00010011
    # Fields: [imm[11:0]=0x0] [rs1=0(x0)] [f3=0b000] [rd=6(t1)] [opcode=0x13]
    13 03 00 00
    # Instruction at 0x0134: addi t2, x0, 0
    # Hex (LE):  93 03 00 00  →  Word: 0x00000393
    # Binary: 00000000 00000000 00000011 10010011
    # Fields: [imm[11:0]=0x0] [rs1=0(x0)] [f3=0b000] [rd=7(t2)] [opcode=0x13]
    93 03 00 00
    # Instruction at 0x0138: addi t3, x0, 0
    # Hex (LE):  13 0E 00 00  →  Word: 0x00000E13
    # Binary: 00000000 00000000 00001110 00010011
    # Fields: [imm[11:0]=0x0] [rs1=0(x0)] [f3=0b000] [rd=28(t3)] [opcode=0x13]
    13 0E 00 00
    # Instruction at 0x013C: addi t4, x0, 0
    # Hex (LE):  93 0E 00 00  →  Word: 0x00000E93
    # Binary: 00000000 00000000 00001110 10010011
    # Fields: [imm[11:0]=0x0] [rs1=0(x0)] [f3=0b000] [rd=29(t4)] [opcode=0x13]
    93 0E 00 00
    # Instruction at 0x0140: addi t5, x0, 0
    # Hex (LE):  13 0F 00 00  →  Word: 0x00000F13
    # Binary: 00000000 00000000 00001111 00010011
    # Fields: [imm[11:0]=0x0] [rs1=0(x0)] [f3=0b000] [rd=30(t5)] [opcode=0x13]
    13 0F 00 00
    # Instruction at 0x0144: addi t6, x0, 0
    # Hex (LE):  93 0F 00 00  →  Word: 0x00000F93
    # Binary: 00000000 00000000 00001111 10010011
    # Fields: [imm[11:0]=0x0] [rs1=0(x0)] [f3=0b000] [rd=31(t6)] [opcode=0x13]
    93 0F 00 00
    # Instruction at 0x0148: addi s0, x0, 0
    # Hex (LE):  13 04 00 00  →  Word: 0x00000413
    # Binary: 00000000 00000000 00000100 00010011
    # Fields: [imm[11:0]=0x0] [rs1=0(x0)] [f3=0b000] [rd=8(s0)] [opcode=0x13]
    13 04 00 00
    # Instruction at 0x014C: addi s1, x0, 0
    # Hex (LE):  93 04 00 00  →  Word: 0x00000493
    # Binary: 00000000 00000000 00000100 10010011
    # Fields: [imm[11:0]=0x0] [rs1=0(x0)] [f3=0b000] [rd=9(s1)] [opcode=0x13]
    93 04 00 00
    # s2 already points to CODE_BASE, keep it
    # Instruction at 0x0150: addi s3, x0, 0
    # Hex (LE):  93 09 00 00  →  Word: 0x00000993
    # Binary: 00000000 00000000 00001001 10010011
    # Fields: [imm[11:0]=0x0] [rs1=0(x0)] [f3=0b000] [rd=19(s3)] [opcode=0x13]
    93 09 00 00
    # Instruction at 0x0154: addi s4, x0, 0
    # Hex (LE):  13 0A 00 00  →  Word: 0x00000A13
    # Binary: 00000000 00000000 00001010 00010011
    # Fields: [imm[11:0]=0x0] [rs1=0(x0)] [f3=0b000] [rd=20(s4)] [opcode=0x13]
    13 0A 00 00
    # Instruction at 0x0158: addi s5, x0, 0
    # Hex (LE):  93 0A 00 00  →  Word: 0x00000A93
    # Binary: 00000000 00000000 00001010 10010011
    # Fields: [imm[11:0]=0x0] [rs1=0(x0)] [f3=0b000] [rd=21(s5)] [opcode=0x13]
    93 0A 00 00
    # Instruction at 0x015C: addi s6, x0, 0
    # Hex (LE):  13 0B 00 00  →  Word: 0x00000B13
    # Binary: 00000000 00000000 00001011 00010011
    # Fields: [imm[11:0]=0x0] [rs1=0(x0)] [f3=0b000] [rd=22(s6)] [opcode=0x13]
    13 0B 00 00
    # Instruction at 0x0160: addi s7, x0, 0
    # Hex (LE):  93 0B 00 00  →  Word: 0x00000B93
    # Binary: 00000000 00000000 00001011 10010011
    # Fields: [imm[11:0]=0x0] [rs1=0(x0)] [f3=0b000] [rd=23(s7)] [opcode=0x13]
    93 0B 00 00
    # Instruction at 0x0164: addi s8, x0, 0
    # Hex (LE):  13 0C 00 00  →  Word: 0x00000C13
    # Binary: 00000000 00000000 00001100 00010011
    # Fields: [imm[11:0]=0x0] [rs1=0(x0)] [f3=0b000] [rd=24(s8)] [opcode=0x13]
    13 0C 00 00
    # Instruction at 0x0168: addi s9, x0, 0
    # Hex (LE):  93 0C 00 00  →  Word: 0x00000C93
    # Binary: 00000000 00000000 00001100 10010011
    # Fields: [imm[11:0]=0x0] [rs1=0(x0)] [f3=0b000] [rd=25(s9)] [opcode=0x13]
    93 0C 00 00
    # Instruction at 0x016C: addi s10, x0, 0
    # Hex (LE):  13 0D 00 00  →  Word: 0x00000D13
    # Binary: 00000000 00000000 00001101 00010011
    # Fields: [imm[11:0]=0x0] [rs1=0(x0)] [f3=0b000] [rd=26(s10)] [opcode=0x13]
    13 0D 00 00
    # Instruction at 0x0170: addi s11, x0, 0
    # Hex (LE):  93 0D 00 00  →  Word: 0x00000D93
    # Binary: 00000000 00000000 00001101 10010011
    # Fields: [imm[11:0]=0x0] [rs1=0(x0)] [f3=0b000] [rd=27(s11)] [opcode=0x13]
    93 0D 00 00
# Jump to CODE_BASE (0x1190) using PC-relative addressing
# auipc captures the current PC (0x174) and adds one 4KB page -> 0x1174
    # Combined intent at 0x0174-0x0178: auipc/addi builds pc-relative t0 = 0x1190 (PC + 0x1000 + 0x1C)
    # Instruction at 0x0174: auipc t0, 0x1
    # Hex (LE):  97 12 00 00  →  Word: 0x00001297
    # Binary: 00000000 00000000 00010010 10010111
    # Fields: [imm[31:12]=0x1] [rd=5(t0)] [opcode=0x17]
    97 12 00 00
# Adds 0x1C to bridge from 0x1174 to CODE_BASE (0x1190)
    # Instruction at 0x0178: addi t0, t0, 0x1C
    # Hex (LE):  93 82 C2 01  →  Word: 0x01C28293
    # Binary: 00000001 11000010 10000010 10010011
    # Fields: [imm[11:0]=0x1C] [rs1=5(t0)] [f3=0b000] [rd=5(t0)] [opcode=0x13]
    93 82 C2 01
# Jump to CODE_BASE, discard return address
    # Instruction at 0x017C: jalr x0, t0, 0
    # Hex (LE):  67 80 02 00  →  Word: 0x00028067
    # Binary: 00000000 00000010 10000000 01100111
    # Fields: [imm[11:0]=0x0] [rs1=5(t0)] [f3=0b000] [rd=0(x0)] [opcode=0x67]
    67 80 02 00
# done: (0x180)
# Infinite loop
    # Instruction at 0x0180: jal x0, 0x0180
    # Hex (LE):  6F 00 00 00  →  Word: 0x0000006F
    # Binary: 00000000 00000000 00000000 01101111
    # Fields: [imm[20]=0b0] [imm[10:1]=0b0000000000] [imm[11]=0b0] [imm[19:12]=0x0] [rd=0(x0)] [opcode=0x6F]
    6F 00 00 00
Filename: hex0_annotated.hex0. Size: 30kb. View raw, , hex, or download this file.

This paste expires on 2026-04-14 08:58:49.254357+00:00. Pasted through web.