diff options
author | Thomas Voss <mail@thomasvoss.com> | 2022-03-05 01:59:59 +0100 |
---|---|---|
committer | Thomas Voss <mail@thomasvoss.com> | 2022-03-05 01:59:59 +0100 |
commit | 82628d0be6043823910b84d15d42879344c886a1 (patch) | |
tree | 96304afaccfa67bb4c254282f44175b72861fd10 | |
parent | 8360d6eb0049ed785d4c7c1d8e03842bc93744cf (diff) |
Use normal comment characters
-rw-r--r-- | smallbrain.s | 554 |
1 files changed, 277 insertions, 277 deletions
diff --git a/smallbrain.s b/smallbrain.s index b293978..748fecc 100644 --- a/smallbrain.s +++ b/smallbrain.s @@ -2,7 +2,7 @@ .equ O_RDONLY, 0 .equ EXIT_FAILURE, 1 -# Opcodes +// Opcodes ENUM(OP_ADD) ENUM(OP_SUB) ENUM(OP_RIGHT) @@ -32,114 +32,114 @@ bytecode: .quad 0 program: .quad 0 .text -# ================== -# Description: -# The entry point of the program. -# -# Args: -# %rdi: The number of command line arguments -# %rsi: An array of command line arguments ((%rsi) is the program name) -# -# Return: -# %rax: The programs exit code -# ================== +// ================== +// Description: +// The entry point of the program. +// +// Args: +// %rdi: The number of command line arguments +// %rsi: An array of command line arguments ((%rsi) is the program name) +// +// Return: +// %rax: The programs exit code +// ================== main: - # Make sure that the right number of arguments were passed + // Make sure that the right number of arguments were passed cmpl $2, %edi jne usage - movq 8(%rsi), %rdi # Move the specified script filename into %rdi - call read_file # Read the file - call compile # Compile into bytecode - call execute # Execute the program + movq 8(%rsi), %rdi // Move the specified script filename into %rdi + call read_file // Read the file + call compile // Compile into bytecode + call execute // Execute the program - # Return successfully + // Return successfully xorl %eax, %eax ret -# ================== -# Description: -# Read the specified file into a program buffer which the user must later free themselves. -# -# Args: -# %rdi: The scripts filename -# ================== +// ================== +// Description: +// Read the specified file into a program buffer which the user must later free themselves. +// +// Args: +// %rdi: The scripts filename +// ================== read_file: pushq %rbp movq %rsp, %rbp - # Allocate space for local variables - # 4 bytes for the file descriptor - # 144 bytes for the struct stat (check `extras/sizeof_struct_stat.c` for numbers) - # 12 bytes of padding to align %rsp on a 16 byte boundary + // Allocate space for local variables + // 4 bytes for the file descriptor + // 144 bytes for the struct stat (check `extras/sizeof_struct_stat.c` for numbers) + // 12 bytes of padding to align %rsp on a 16 byte boundary subq $160, %rsp - # Open the file in read-only mode with the open(2) syscall + // Open the file in read-only mode with the open(2) syscall movl $O_RDONLY, %esi call open - cmpl $-1, %eax # Check if open(1) returned -1 (it failed) - je open_die # If so, exit the program - movl %eax, -4(%rbp) # If not store the file descriptor + cmpl $-1, %eax // Check if open(1) returned -1 (it failed) + je open_die // If so, exit the program + movl %eax, -4(%rbp) // If not store the file descriptor - movl %eax, %edi # Set the first argument to the file descriptor - leaq -160(%rbp), %rsi # Set the second argument to the address of the struct stat - call fstat # Call fstat(2) to populate the struct stat + movl %eax, %edi // Set the first argument to the file descriptor + leaq -160(%rbp), %rsi // Set the second argument to the address of the struct stat + call fstat // Call fstat(2) to populate the struct stat - # Error check fstat(2) just like open(2) + // Error check fstat(2) just like open(2) cmpl $-1, %eax je fstat_die - # Allocate a buffer for the programs contents - movq -112(%rbp), %rdi # Put st_size (the filesize) in %rdi - incq %rdi # Make space for the NUL byte - pushq %rdi # Store the value of %rdi for the next 2 malloc calls - call malloc # Allocate the memory - testq %rax, %rax # Check if %rax is NULL - je malloc_die # If it is then malloc failed and we exit - movq %rax, (program) # Store the address of the allocated memory in (program) - addq -112(%rbp), %rax # Point to the last element of the program array - movb $0, (%rax) # NULL terminate the program - - # Allocate a buffer for the bytecode - popq %rdi # Retrieve %rdi from the stack - shlq $4, %rdi # Multiply the size of the buffer by 16 to make space for opcodes - call malloc # Allocate the memory - movq %rax, (bytecode) # Store the address of the allocated memory in (bytecode) - testq %rax, %rax # Check if %rax is NULL - je malloc_die # If it is then malloc failed and we exit - - # Get a FILE* from the file descriptor with fdopen(3) + // Allocate a buffer for the programs contents + movq -112(%rbp), %rdi // Put st_size (the filesize) in %rdi + incq %rdi // Make space for the NUL byte + pushq %rdi // Store the value of %rdi for the next 2 malloc calls + call malloc // Allocate the memory + testq %rax, %rax // Check if %rax is NULL + je malloc_die // If it is then malloc failed and we exit + movq %rax, (program) // Store the address of the allocated memory in (program) + addq -112(%rbp), %rax // Point to the last element of the program array + movb $0, (%rax) // NULL terminate the program + + // Allocate a buffer for the bytecode + popq %rdi // Retrieve %rdi from the stack + shlq $4, %rdi // Multiply the size of the buffer by 16 to make space for opcodes + call malloc // Allocate the memory + movq %rax, (bytecode) // Store the address of the allocated memory in (bytecode) + testq %rax, %rax // Check if %rax is NULL + je malloc_die // If it is then malloc failed and we exit + + // Get a FILE* from the file descriptor with fdopen(3) movl -4(%rbp), %edi movq $read_mode, %rsi call fdopen - pushq %rax # Push the FILE* to the stack for the later call to fclose(3) - movq (program), %r15 # Move the program buffer into %r15 + pushq %rax // Push the FILE* to the stack for the later call to fclose(3) + movq (program), %r15 // Move the program buffer into %r15 -# cmpjeq - Compare Jump Equal Quadword -# ==================================== -# Compare the value of 'val' to %rax and if they match jump to 'jump'. +// cmpjeq - Compare Jump Equal Quadword +// ==================================== +// Compare the value of 'val' to %rax and if they match jump to 'jump'. .macro cmpjeq val, jump cmpq \val, %rax je \jump .endm -# cmpjeb - Compare Jump Equal Byte -# ================================ -# Compare the value of 'val' to %al and if they match jump to 'jump'. +// cmpjeb - Compare Jump Equal Byte +// ================================ +// Compare the value of 'val' to %al and if they match jump to 'jump'. .macro cmpjeb val, jump cmpb \val, %al je \jump .endm read_file_loop: - movq -168(%rbp), %rdi # Move the FILE* into %rdi - call fgetc # Read a character from the file - cmpl $EOF, %eax # Check if we reached EOF - je read_file_eof # If we did then end the loop + movq -168(%rbp), %rdi // Move the FILE* into %rdi + call fgetc // Read a character from the file + cmpl $EOF, %eax // Check if we reached EOF + je read_file_eof // If we did then end the loop - # If we match any non-comment character jump to read_file_not_comment + // If we match any non-comment character jump to read_file_not_comment cmpjeb $'+', read_file_not_comment cmpjeb $'-', read_file_not_comment cmpjeb $'>', read_file_not_comment @@ -148,39 +148,39 @@ read_file_loop: cmpjeb $']', read_file_not_comment cmpjeb $',', read_file_not_comment cmpjeb $'.', read_file_not_comment - # DEFAULT CASE (its a comment we can ignore) + // DEFAULT CASE (its a comment we can ignore) jmp read_file_loop read_file_not_comment: - movb %al, (%r15) # Read the character into the program buffer - incq %r15 # Point to the next empty slot in the buffer - jmp read_file_loop # Loop again + movb %al, (%r15) // Read the character into the program buffer + incq %r15 // Point to the next empty slot in the buffer + jmp read_file_loop // Loop again read_file_eof: - # NUL terminate the buffer + // NUL terminate the buffer movb $0, (%r15) - # Close the file, don't error check this + // Close the file, don't error check this movq -168(%rbp), %rdi call fclose leave ret -# ================== -# Description: -# Compile the program into a bytecode which is an optimized version of the raw program. Each -# opcode is a "struct" where the higher 8 bytes are an opcode and the lower 8 are data for -# the instruction. -# ================== +// ================== +// Description: +// Compile the program into a bytecode which is an optimized version of the raw program. Each +// opcode is a "struct" where the higher 8 bytes are an opcode and the lower 8 are data for +// the instruction. +// ================== compile: - movq (program), %r15 # Store the address of the program pointer into %r15 - movq (bytecode), %r14 # Store the address of the bytecode pointer into %r14 + movq (program), %r15 // Store the address of the program pointer into %r15 + movq (bytecode), %r14 // Store the address of the bytecode pointer into %r14 compile_loop: - # Load the current command into %rax + // Load the current command into %rax movq (%r15), %rax - # Jump to a different label depending on which instruction we hit + // Jump to a different label depending on which instruction we hit cmpjeb $'+', compile_add cmpjeb $'-', compile_sub cmpjeb $'>', compile_right @@ -191,165 +191,165 @@ compile_loop: cmpjeb $'.', compile_write compile_add: - movq $OP_ADD, (%r14) # Specify the ADD opcode - movq $1, 8(%r14) # Write the count of '+'s to the data portion + movq $OP_ADD, (%r14) // Specify the ADD opcode + movq $1, 8(%r14) // Write the count of '+'s to the data portion compile_add_loop: - incq %r15 # Move to the next instruction - cmpb $'+', (%r15) # Check if there is another + - jne compile_out # If not, exit this loop - incq 8(%r14) # Increment the accumulator - jmp compile_add_loop # Loop again + incq %r15 // Move to the next instruction + cmpb $'+', (%r15) // Check if there is another + + jne compile_out // If not, exit this loop + incq 8(%r14) // Increment the accumulator + jmp compile_add_loop // Loop again compile_sub: - movq $OP_SUB, (%r14) # Specify the SUB opcode - movq $1, 8(%r14) # Write the count of '-'s to the data portion + movq $OP_SUB, (%r14) // Specify the SUB opcode + movq $1, 8(%r14) // Write the count of '-'s to the data portion compile_sub_loop: - incq %r15 # Move to the next instruction - cmpb $'-', (%r15) # Check if there is another - - jne compile_out # If not, exit this loop - incq 8(%r14) # Increment the accumulator - jmp compile_sub_loop # Loop again + incq %r15 // Move to the next instruction + cmpb $'-', (%r15) // Check if there is another - + jne compile_out // If not, exit this loop + incq 8(%r14) // Increment the accumulator + jmp compile_sub_loop // Loop again compile_right: - movq $OP_RIGHT, (%r14) # Specify the RIGHT opcode - movq $1, 8(%r14) # Write the count of '>'s to the data portion + movq $OP_RIGHT, (%r14) // Specify the RIGHT opcode + movq $1, 8(%r14) // Write the count of '>'s to the data portion compile_right_loop: - incq %r15 # Move to the next instruction - cmpb $'>', (%r15) # Check if there is another > - jne compile_out # If not, exit this loop - incq 8(%r14) # Increment the accumulator - jmp compile_right_loop # Loop again + incq %r15 // Move to the next instruction + cmpb $'>', (%r15) // Check if there is another > + jne compile_out // If not, exit this loop + incq 8(%r14) // Increment the accumulator + jmp compile_right_loop // Loop again compile_left: - movq $OP_LEFT, (%r14) # Specify the LEFT opcode - movq $1, 8(%r14) # Write the count of '<'s to the data portion + movq $OP_LEFT, (%r14) // Specify the LEFT opcode + movq $1, 8(%r14) // Write the count of '<'s to the data portion compile_left_loop: - incq %r15 # Move to the next instruction - cmpb $'<', (%r15) # Check if there is another < - jne compile_out # If not, exit this loop - incq 8(%r14) # Increment the accumulator - jmp compile_left_loop # Loop again + incq %r15 // Move to the next instruction + cmpb $'<', (%r15) // Check if there is another < + jne compile_out // If not, exit this loop + incq 8(%r14) // Increment the accumulator + jmp compile_left_loop // Loop again compile_loop_start: - # When we reach a '[' the first thing we want to do is check to see if it matches the - # pattern '[-]'. This pattern is one that sets a memory cell to 0, so we can optimize that. - movq %r15, %rdi # Compare the current position in the program string - movq $zero_pattern, %rsi # Compare it against the zero pattern '[-]' - movl $4, %ecx # We want to compare 3 bytes (the instruction requires +1) - repe cmpsb # Keep looping CMPSB while bytes match - jrcxz compile_zero # Jump to compile_zero if the strings matched - - movq %r15, %rdi # Move the current instruction pointer into %rdi - call copy_loop_checker # Call the copy loop checker - testq %rax, %rax # Check to see if we hit a copy loop - jz compile_loop_start_normal # If we didn't, this is a regular loop - movq %rax, %r15 # Otherwise, set %r15 to the new location - incq %r15 # Then point to the next instruction + // When we reach a '[' the first thing we want to do is check to see if it matches the + // pattern '[-]'. This pattern is one that sets a memory cell to 0, so we can optimize that. + movq %r15, %rdi // Compare the current position in the program string + movq $zero_pattern, %rsi // Compare it against the zero pattern '[-]' + movl $4, %ecx // We want to compare 3 bytes (the instruction requires +1) + repe cmpsb // Keep looping CMPSB while bytes match + jrcxz compile_zero // Jump to compile_zero if the strings matched + + movq %r15, %rdi // Move the current instruction pointer into %rdi + call copy_loop_checker // Call the copy loop checker + testq %rax, %rax // Check to see if we hit a copy loop + jz compile_loop_start_normal // If we didn't, this is a regular loop + movq %rax, %r15 // Otherwise, set %r15 to the new location + incq %r15 // Then point to the next instruction jmp compile_out compile_loop_start_normal: - # Push the address of the loop start to the stack for the next ']' + // Push the address of the loop start to the stack for the next ']' pushq %r14 - movq $OP_LOOP_START, (%r14) # Specify the LOOP_START opcode - movq $0, 8(%r14) # Zero the data section - incq %r15 # Increment the instruction pointer + movq $OP_LOOP_START, (%r14) // Specify the LOOP_START opcode + movq $0, 8(%r14) // Zero the data section + incq %r15 // Increment the instruction pointer jmp compile_out compile_loop_end: - popq 8(%r14) # Pop the address of the previous loop start to the data section - movq $OP_LOOP_END, (%r14) # Push the address of the loop end to the stack - incq %r15 # Increment the instruction pointer + popq 8(%r14) // Pop the address of the previous loop start to the data section + movq $OP_LOOP_END, (%r14) // Push the address of the loop end to the stack + incq %r15 // Increment the instruction pointer jmp compile_out compile_read: - movq $OP_READ, (%r14) # Specify the READ opcode - movq $0, 8(%r14) # Zero the data section - incq %r15 # Increment the instruction pointer + movq $OP_READ, (%r14) // Specify the READ opcode + movq $0, 8(%r14) // Zero the data section + incq %r15 // Increment the instruction pointer jmp compile_out compile_write: - movq $OP_WRITE, (%r14) # Specify the WRITE opcode - movq $0, 8(%r14) # Zero the data section - incq %r15 # Increment the instruction pointer + movq $OP_WRITE, (%r14) // Specify the WRITE opcode + movq $0, 8(%r14) // Zero the data section + incq %r15 // Increment the instruction pointer jmp compile_out compile_zero: - movq $OP_ZERO, (%r14) # Specify the ZERO opcode - movq $0, 8(%r14) # Zero the data section - addq $3, %r15 # '[-]' is a 3 byte instruction - # FALLTHROUGH + movq $OP_ZERO, (%r14) // Specify the ZERO opcode + movq $0, 8(%r14) // Zero the data section + addq $3, %r15 // '[-]' is a 3 byte instruction + // FALLTHROUGH compile_out: - addq $16, %r14 # Move to the next opcode - movb (%r15), %al # Move the current instruction into %al - testb %al, %al # Check if we have reached the NUL byte - jne compile_loop # If we haven't, loop - movq $0, (%r14) # Otherwise, NUL terminate the bytecode - - # Now that we have traversed the entire program, we do a 2nd pass backwards so that we can - # set the jump addresses for the '[' commands now that the ']' commands have the addresses - # set. + addq $16, %r14 // Move to the next opcode + movb (%r15), %al // Move the current instruction into %al + testb %al, %al // Check if we have reached the NUL byte + jne compile_loop // If we haven't, loop + movq $0, (%r14) // Otherwise, NUL terminate the bytecode + + // Now that we have traversed the entire program, we do a 2nd pass backwards so that we can + // set the jump addresses for the '[' commands now that the ']' commands have the addresses + // set. compile_backwards: - # We are at the NUL terminator, so move backwards + // We are at the NUL terminator, so move backwards subq $16, %r14 - cmpq $OP_LOOP_END, (%r14) # Check if we hit a ']' - jne compile_backwards_next # If we didn't move to the next check - pushq %r14 # Otherwise push the address of the opcode to the stack + cmpq $OP_LOOP_END, (%r14) // Check if we hit a ']' + jne compile_backwards_next // If we didn't move to the next check + pushq %r14 // Otherwise push the address of the opcode to the stack jmp compile_backwards_out compile_backwards_next: - cmpq $OP_LOOP_START, (%r14) # Check if we hit a '[' - jne compile_backwards_out # If we didn't just keep looping - popq 8(%r14) # If we did then pop the corresponding ']' address + cmpq $OP_LOOP_START, (%r14) // Check if we hit a '[' + jne compile_backwards_out // If we didn't just keep looping + popq 8(%r14) // If we did then pop the corresponding ']' address compile_backwards_out: - cmpq %r14, (bytecode) # Check if we've seen every opcode - jne compile_backwards # If not keep looping - movq (program), %rdi # Otherwise, move the program buffer to %rdi - call free # Free it - ret # And return - -# ================== -# Description: -# Try to figure out if we are at a copy loop and optimize it. A copy loop follows the pattern -# of a loop ([]) beginning with a '-' followed by N occurances of '>' followed by a '+' and N -# occurances of '<'. This sequence copies the current cell to the cell at offset N and clears -# the current cell afterwards. -# -# Args: -# %rdi: A pointer to the first '[' of the potential copy loop -# -# Return: -# 0 if not a copy loop, otherwise the new position of the instruction pointer. -# ================== + cmpq %r14, (bytecode) // Check if we've seen every opcode + jne compile_backwards // If not keep looping + movq (program), %rdi // Otherwise, move the program buffer to %rdi + call free // Free it + ret // And return + +// ================== +// Description: +// Try to figure out if we are at a copy loop and optimize it. A copy loop follows the pattern +// of a loop ([]) beginning with a '-' followed by N occurances of '>' followed by a '+' and N +// occurances of '<'. This sequence copies the current cell to the cell at offset N and clears +// the current cell afterwards. +// +// Args: +// %rdi: A pointer to the first '[' of the potential copy loop +// +// Return: +// 0 if not a copy loop, otherwise the new position of the instruction pointer. +// ================== copy_loop_checker: - # Skip '[' + // Skip '[' incq %rdi - # All copy loops must begin with a '-' + // All copy loops must begin with a '-' cmpb $'-', (%rdi) jne copy_loop_fail incq %rdi - # Zero %rax so we can use it to count the copy offset + // Zero %rax so we can use it to count the copy offset xorl %eax, %eax copy_loop_count_offset: - cmpb $'>', (%rdi) # Check for '>' - jne copy_loop_next # If we don't match anymore then move to the next step - incq %rax # Increment the offset counter - incq %rdi # Increment the instruction pointer - jmp copy_loop_count_offset # Loop again + cmpb $'>', (%rdi) // Check for '>' + jne copy_loop_next // If we don't match anymore then move to the next step + incq %rax // Increment the offset counter + incq %rdi // Increment the instruction pointer + jmp copy_loop_count_offset // Loop again copy_loop_next: - cmpb $'+', (%rdi) # Check if we see the mandatory '+' - jne copy_loop_fail # If we don't then fail - incq %rdi # Otherwise move to the next instruction + cmpb $'+', (%rdi) // Check if we see the mandatory '+' + jne copy_loop_fail // If we don't then fail + incq %rdi // Otherwise move to the next instruction - # The following code is the exact same as what we just did to count the offset but we are - # now using %rcx and decrementing for each '<'. This is so we can make sure that the copy - # loop is a working one. + // The following code is the exact same as what we just did to count the offset but we are + // now using %rcx and decrementing for each '<'. This is so we can make sure that the copy + // loop is a working one. cmpb $'<', (%rdi) jne copy_loop_fail movq %rax, %rcx @@ -360,36 +360,36 @@ copy_loop_verify_offset: incq %rdi copy_loop_next_2: - cmpb $']', (%rdi) # Ensure this is the end of the loop - jne copy_loop_fail # If its not then fail - testq %rcx, %rcx # Otherwise make sure that our offsets line up - jnz copy_loop_fail # If they don't then fail - - movq $OP_COPY, (%r14) # Create an OP_COPY opcode - movq %rax, 8(%r14) # Set the offset to copy to - movq $OP_ZERO, 16(%r14) # Create an OP_ZERO opcode - movq $0, 24(%r14) # Set an empty data section - addq $16, %r14 # Increment the opcode pointer - - # Return the address of the instruction pointer + cmpb $']', (%rdi) // Ensure this is the end of the loop + jne copy_loop_fail // If its not then fail + testq %rcx, %rcx // Otherwise make sure that our offsets line up + jnz copy_loop_fail // If they don't then fail + + movq $OP_COPY, (%r14) // Create an OP_COPY opcode + movq %rax, 8(%r14) // Set the offset to copy to + movq $OP_ZERO, 16(%r14) // Create an OP_ZERO opcode + movq $0, 24(%r14) // Set an empty data section + addq $16, %r14 // Increment the opcode pointer + + // Return the address of the instruction pointer movq %rdi, %rax ret copy_loop_fail: xorl %eax, %eax ret -# ================== -# Description: -# Execute the brainfuck bytecode. -# ================== +// ================== +// Description: +// Execute the brainfuck bytecode. +// ================== execute: - movq (bytecode), %r15 # Store the address of the program pointer into %r15 - movq $memory, %r14 # Store the address of the first memory cell into %r14 # TODO make sure this handles overflows normally + movq (bytecode), %r15 // Store the address of the program pointer into %r15 + movq $memory, %r14 // Store the address of the first memory cell into %r14 # TODO make sure this handles overflows normally execute_loop: - # Load the current command into %rax + // Load the current command into %rax movq (%r15), %rax - # Jump to a different label depending on which instruction we hit + // Jump to a different label depending on which instruction we hit cmpjeq $OP_ADD, execute_add cmpjeq $OP_SUB, execute_sub cmpjeq $OP_RIGHT, execute_right @@ -399,87 +399,87 @@ execute_loop: cmpjeq $OP_READ, execute_read cmpjeq $OP_WRITE, execute_write cmpjeq $OP_ZERO, execute_zero - # OP_COPY + // OP_COPY jmp execute_copy execute_add: - # Increment the current memory cell + // Increment the current memory cell movq 8(%r15), %rax addb %al, (%r14) jmp execute_out execute_sub: - # Decrement the current memory cell + // Decrement the current memory cell movq 8(%r15), %rax subb %al, (%r14) jmp execute_out execute_right: - # Move the memory pointer right + // Move the memory pointer right addq 8(%r15), %r14 jmp execute_out execute_left: - # Move the memory pointer left + // Move the memory pointer left subq 8(%r15), %r14 jmp execute_out execute_loop_start: - # If the current memory cell is 0 move to the next ']' + // If the current memory cell is 0 move to the next ']' cmpb $0, (%r14) cmovzq 8(%r15), %r15 jmp execute_out execute_loop_end: - # If the current memory cell is not 0 move to the last '[' + // If the current memory cell is not 0 move to the last '[' cmpb $0, (%r14) cmovnzq 8(%r15), %r15 jmp execute_out execute_read: - # Set the current cell to the character read from stdin - call getchar # Read a character with getchar(3) - cmpb $EOF, %al # Check if the EOF was read - je execute_read_eof # If EOF was read, jump to a special handler for that - movb %al, (%r14) # Otherwise move the read character into the current memory cell + // Set the current cell to the character read from stdin + call getchar // Read a character with getchar(3) + cmpb $EOF, %al // Check if the EOF was read + je execute_read_eof // If EOF was read, jump to a special handler for that + movb %al, (%r14) // Otherwise move the read character into the current memory cell jmp execute_out execute_read_eof: - # If EOF was read, set the current cell to 0 + // If EOF was read, set the current cell to 0 movb $0, (%r14) jmp execute_out execute_write: - # Print the character at the current memory cell - movl (%r14), %edi # Move the current memory cell into %edi - call putchar # Print it with putchar(3) + // Print the character at the current memory cell + movl (%r14), %edi // Move the current memory cell into %edi + call putchar // Print it with putchar(3) jmp execute_out execute_zero: - # Zero the current cell + // Zero the current cell movb $0, (%r14) jmp execute_out execute_copy: - # Copy the current memory cells contents elsewhere + // Copy the current memory cells contents elsewhere movq 8(%r15), %rax movb (%r14), %cl movb %cl, (%rax, %r14, 1) - # FALLTHROUGH + // FALLTHROUGH execute_out: - addq $16 , %r15 # Increment the instruction pointer - movq (%r15), %rax # Move the current instruction into %rax - testq %rax, %rax # Check if we have reached the NUL byte - jne execute_loop # If we haven't, loop - ret # Otherwise, return - -# ================== -# Description: -# The following die functions all work the same. They simply take the name of the -# corresponding function and store it in %rdi. Then the die function is called to print a -# message to stderr and terminate the program. -# ================== + addq $16 , %r15 // Increment the instruction pointer + movq (%r15), %rax // Move the current instruction into %rax + testq %rax, %rax // Check if we have reached the NUL byte + jne execute_loop // If we haven't, loop + ret // Otherwise, return + +// ================== +// Description: +// The following die functions all work the same. They simply take the name of the +// corresponding function and store it in %rdi. Then the die function is called to print a +// message to stderr and terminate the program. +// ================== .macro fdie s movq \s, %rdi @@ -492,46 +492,46 @@ read_die: fdie $func_read malloc_die: fdie $func_malloc -# ================== -# Description: -# Print out an error message in the format "<func name>: <err msg>" then exit via `_exit` -# -# Args: -# %rdi: The function name -# ================== +// ================== +// Description: +// Print out an error message in the format "<func name>: <err msg>" then exit via `_exit` +// +// Args: +// %rdi: The function name +// ================== die: - # Store the function name temporarily in %r15 + // Store the function name temporarily in %r15 movq %rdi, %r15 - call __errno_location # Call __errno_location to get a pointer to errno - movq (%rax), %rdi # Move errno into %rdi - call strerror # Get the error string with strerror(3) + call __errno_location // Call __errno_location to get a pointer to errno + movq (%rax), %rdi // Move errno into %rdi + call strerror // Get the error string with strerror(3) - movq %rax, %rcx # Set the error string - xorl %eax, %eax # Zero %rax - movq %r15, %rdx # Set the function name - movq $die_fmt, %rsi # Set the format string - movq stderr, %rdi # Get stderr - call fprintf # Print the message to stderr + movq %rax, %rcx // Set the error string + xorl %eax, %eax // Zero %rax + movq %r15, %rdx // Set the function name + movq $die_fmt, %rsi // Set the format string + movq stderr, %rdi // Get stderr + call fprintf // Print the message to stderr jmp _exit -# ================== -# Description: -# Print a usage message to standard error and exit the program via `_exit` -# ================== +// ================== +// Description: +// Print a usage message to standard error and exit the program via `_exit` +// ================== usage: - xorl %eax, %eax # Set rax to 0 - movq (%rsi), %rdx # Get argv[0] - movq $usage_fmt, %rsi # Set the format string - movq stderr, %rdi # Get stderr - call fprintf # Print the error - # FALLTHROUGH - -# ================== -# Description: -# Exit the program with the return code EXIT_FAILURE -# ================== + xorl %eax, %eax // Set rax to 0 + movq (%rsi), %rdx // Get argv[0] + movq $usage_fmt, %rsi // Set the format string + movq stderr, %rdi // Get stderr + call fprintf // Print the error + // FALLTHROUGH + +// ================== +// Description: +// Exit the program with the return code EXIT_FAILURE +// ================== _exit: movl $EXIT_FAILURE, %eax call exit |