You are launched into the debugger either by an ebreak/sbreak
instruction, or when an exception occurs while running executing instructions.
Consider the example program examples/fibs.asm
:
.data
fibs: .space 56
.text
main:
addi s1, zero, 0 ; storage index
addi s2, zero, 56 ; last storage index
addi t0, zero, 1 ; t0 = F_{i}
addi t1, zero, 1 ; t1 = F_{i+1}
ebreak ; launch debugger
loop:
sw t0, fibs(s1) ; save
add t2, t1, t0 ; t2 = F_{i+2}
addi t0, t1, 0 ; t0 = t1
addi t1, t2, 0 ; t1 = t2
addi s1, s1, 4 ; increment storage pointer
blt s1, s2, loop ; loop as long as we did not reach array length
ebreak ; launch debugger
; exit gracefully
addi a0, zero, 0
addi a7, zero, 93
scall ; exit with code 0
This calculates the fibonacci sequence and stores it in memory at fibs
. before and after it calculated all fibonacci numbers, it
uses the ebreak
instruction to open the debugger. Let's run it and see what happens:
> python -m riscemu examples/fibs.asm
[MMU] Successfully loaded: LoadedExecutable[examples/fibs.asm](base=0x00000100, size=72bytes, sections=data text, run_ptr=0x00000138)
[CPU] Started running from 0x00000138 (examples/fibs.asm)
Debug instruction encountered at 0x0000013C
>>>
In this interactive session, you have access to the cpu, registers, memory and syscall interface. You can look into everything, and most common tasks should have helper methods for them.
Available objects are:
mem
: (akammu
ormemory
)dump(address, fmt='hex', max_rows=10, group=4, bytes_per_row=16, all=False
: Dumps the memory ataddress
, in at mostmax_rows
rows, each containingbytes_per_row
bytes grouped into groups ofgroup
bytes. They can be printed as:hex
: hexadecimal, unsignedint
: converted to integersuint
: converted to unsigned integers
symbol(name)
: Lookup all symbols namedname
reg
: (akaregs
orregisters
)dump(full=False)
dumps all integer registers (unlessall
is true, then all registers are printed)get(name)
get register contentset(name, val)
set register content
cpu
:- The CPU has the
pc
attribute andcycle
attribute. Others won't be useful in this context.
- The CPU has the
Available helpers are:
dump(regs | addr)
dumps either registers or memory addresscont(verbose=False)
continue execution (verbose prints each executed instruction)step()
run the next instructionins()
get current instruction (this reference is mutable, if you want to edit your code on the fly)run_ins(name, *args)
Run an instruction in the current context. Symbols, jumping, etc are supported!
Example: