2015-12-15 23:43:30 +00:00
|
|
|
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
|
2015-12-16 23:06:26 +00:00
|
|
|
registers = ["%rip","%rbp","%rsp","","%rax","%rdi","%r8","%r9"]
|
2015-12-16 23:11:18 +00:00
|
|
|
emu = infernal.Emulator(fib_prog)
|
|
|
|
painter = infernal.TikzPainter(registers)
|
2015-12-16 01:09:04 +00:00
|
|
|
emu.setStack("junk...", "calling eip")
|
|
|
|
emu.setRegs( rip = 0, rbp = 'old bp', rdi = a )
|
2015-12-15 23:43:30 +00:00
|
|
|
|
2015-12-16 00:36:23 +00:00
|
|
|
painter.drawState(emu)
|
|
|
|
for line_nr in emu:
|
|
|
|
painter.drawState(emu, line_nr)
|
|
|
|
painter.drawNames(emu)
|
2015-12-15 23:43:30 +00:00
|
|
|
|
|
|
|
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")
|
2015-12-16 00:36:23 +00:00
|
|
|
f.write(str(painter))
|
2015-12-15 23:43:30 +00:00
|
|
|
f.write("\\end{tikzpicture}\n\\end{document}")
|