import os,sys,inspect sys.path.insert(1, os.path.join(sys.path[0], '..')) import infernal fib_prog = """ fib: push %rbp # push previous base pointer movq %rsp,%rbp # setup new base pointer if: cmpq $1, %rdi # if (a-1) > 0: goto long jg long quick: movq %rdi, %rax jmp return long: pushq %rdi # Push a onto the stack subq $1, %rdi call fib # Call fib(a-1) pushq %rax # Push fib(a-1) onto the stack subq $1, %rdi call fib # Call fib(a-2) popq %rdi # pop fib(a-1) into rdi addq %rdi, %rax # rax = fib(a-1)+fib(a-2) popq %rdi # Garentee that a lies in rdi. return: leave # Clean up (stack pointers?) ret # return m (rax) """ fib_iter_prog = """ fib: push %rbp # push previous base pointer movq %rsp,%rbp # setup new base pointer if: cmpq $1, %rdi # if (a-1) > 0: goto loops jg loops quick: movq %rdi, %rax jmp return loops: movq %rdi, %r8 # i (r8) = a movq $1, %rdi # minus_one (rdi) = 1 movq $0, %rax # minus_two (rax) = 0 loopb: movq %rdi, %9 # r = minus_one addq %rax, %rdi # minus_one += minus_two movq %9, %rax # minus_two = r subq $1, %r8 # i-- cmpq $0, %r8 # if a > 0 jg loopb return: leave # Clean up ret # return m (rax) """ OPTIONS = """register_node/.style={rectangle, draw=black!30, fill=black!5, very thick, minimum size=0.5, minimum width=20mm}, text_node/.style={}""" def printf (str, *args): print(str.format(*args)) if __name__ == "__main__": a = 3 printf("Running for fib({})", a) # Setup registers = ["%rip","%rbp","%rsp","","%rax","%rdi","%r8","%r9"] emu = infernal.Emulator(fib_prog) painter = infernal.TikzPainter(registers) emu.setStack("junk...", "calling eip") emu.setRegs( rip = 0, rbp = 'old bp', rdi = a ) painter.drawState(emu) for line_nr in emu: painter.drawState(emu, line_nr) painter.drawNames(emu) printf("fib({}) = {}", a, emu.registers["%rax"]) with open("tikz.tex","w") as f: f.write("\\documentclass{standalone}\n\n\usepackage{tikz}\\begin{document}\n") f.write("\\begin{tikzpicture}["+OPTIONS+"]\n") f.write(str(painter)) f.write("\\end{tikzpicture}\n\\end{document}")