15039 - Assembly Runner   

Description

Belle is a professional Proxy, which means she's also very good at hacking computers. Right now, she's trying to hack into a machine, but she has to explore what can the machine's processor do first.

A processor executes machine instructions. Assembly language is a human-readable way to describe those instructions. In this problem, you will help Belle run a small, RISC-V-inspired instruction set.

The program has exactly 10 registers, numbered from $0 to $9, all initially set to 0, and all of them can be modified. The program also has memory, which is separate from the registers and stores values at integer addresses. There is no specified limit on memory, so there can be 1 or 10,000 entries in the memory.

Instructions are numbered from 1 to n, and execution starts at instruction 1. Normally, execution continues with the next instruction. A jump changes which instruction executes next. Execution terminates when there are no more instructions to execute.

In the instruction examples below, register names such as $1 and $2 can be replaced by any register from $0 through $9.

Hint: All n instructions should be read and stored before execution begins, since jumps may refer to instructions that appear later in the input

Instructions

1. Load a value

 

li $1, c

Set $1 to the integer constant c.


2. Add

 
add $1, $2, $3

Add the values in $2 and $3, then store the result in $1: $1 = $2 + $3.


3. Multiply

 
mul $1, $2, $3

Multiply the values in $2 and $3, then store the result in $1: $1 = $2 × $3.


4. Copy a value

 
mv $1, $2

Copy the value in $2 into $1: $1 = $2. The value in $2 does not change.


5. Store in memory

 
sw $1, c($2)

Compute the memory address by adding c to the value stored in $2. Store the value in $1 at that address:

memory[$2 + c] = $1


An existing value at that address is overwritten. The registers do not change.

6. Load from memory

 
lw $1, c($2)

Compute the memory address by adding c to the value stored in $2. Load the value at that address into $1:

$1 = memory[$2 + c]

For both lw and sw, the offset c is an integer from 0 to 9, inclusive. This limit applies to the offset, not to the resulting memory address. For example, if $2 contains 1000, then 4($2) refers to memory address 1004.


7. Jump

 
j c

Continue execution at instruction c. The target c is an absolute instruction number, not an offset from the current instruction. For example, j 1 goes to the first instruction, regardless of where the jump occurs.

After the jump, execution continues from instruction c. It does not automatically return to the instruction after j.


8. Jump if equal

 
beq $1, $2, c

If $1 and $2 contain the same value, continue at instruction c. Otherwise, continue at the next instruction.


9. Jump if not equal

 
bne $1, $2, c

If $1 and $2 contain different values, continue at instruction c. Otherwise, continue at the next instruction.

For j, beq, and bne, c is an absolute, 1-based instruction number.


10. Print a character

 
print $1

Print the ASCII character whose code is the value in $1. For example, if $1 contains 65, print A.


 

Input

The first line contains an integer n, the number of instructions. Each of the next n lines contains one instruction.

All instructions are valid. Every lw reads a memory address that has already been written, and every program eventually terminates.

Output

  • Test cases 1–4 contain only instructions 1–4.
  • Test cases 5–6 contain only instructions 1–6.
  • Test case 7 contains only instructions 1–7.
  • Test case 8 and 9 contains only instructions 1–9.
  • Test case 10 contains all instruction types.

Each print instruction outputs its ASCII character on a separate line.

After the program finishes, print a Python-style list containing the final values of registers $0 through $9, in that order.

Sample Input  Download

Sample Output  Download




Discuss