Share
Embed
Transcript
125 slides
-
Simulating a CPU with Ruby Denis Defreyne / RUG::B /
April 2, 2015 1 -
3 1. Write an assembler 2. Design an assembly language
3. Design a CPU instruction format 4. Design a CPU instruction set 5. Write an emulator -
3 1. Write an assembler 2. Design an assembly language
3. Design a CPU instruction format 4. Design a CPU instruction set 5. Write an emulator -
3 1. Write an assembler 2. Design an assembly language
3. Design a CPU instruction format 4. Design a CPU instruction set 5. Write an emulator -
3 1. Write an assembler 2. Design an assembly language
3. Design a CPU instruction format 4. Design a CPU instruction set 5. Write an emulator -
3 1. Write an assembler 2. Design an assembly language
3. Design a CPU instruction format 4. Design a CPU instruction set 5. Write an emulator -
3 1. Write an assembler 2. Design an assembly language
3. Design a CPU instruction format 4. Design a CPU instruction set 5. Write an emulator -
loop do grab case apple_color when :red move_to(:right) when :green
move_to(:left) 5 -
loop do grab case apple_color when :red move_to(:right) when :green
move_to(:left) end 5 -
loop do grab case apple_color when :red move_to(:right) when :green
move_to(:left) end release 5 -
loop do grab case apple_color when :red move_to(:right) when :green
move_to(:left) end release move_to(:middle) 5 -
loop do grab case apple_color when :red move_to(:right) when :green
move_to(:left) end release move_to(:middle) end 5 -
7 loop do grab case apple_color when :red move_to(:right) when
:green move_to(:left) end release move_to(:bucket) end -
7 loop do grab case apple_color when :red move_to(:right) when
:green move_to(:left) end release move_to(:bucket) end -
grab # grab apple 7 loop do grab case apple_color
when :red move_to(:right) when :green move_to(:left) end release move_to(:bucket) end -
grab # grab apple getcolor r0 # r0 now contains
apple color 7 loop do grab case apple_color when :red move_to(:right) when :green move_to(:left) end release move_to(:bucket) end -
grab # grab apple getcolor r0 # r0 now contains
apple color cmp r0, 0 # 0 means red 7 loop do grab case apple_color when :red move_to(:right) when :green move_to(:left) end release move_to(:bucket) end -
grab # grab apple getcolor r0 # r0 now contains
apple color cmp r0, 0 # 0 means red je @red # jump if equal (i.e. red) 7 loop do grab case apple_color when :red move_to(:right) when :green move_to(:left) end release move_to(:bucket) end -
grab # grab apple getcolor r0 # r0 now contains
apple color cmp r0, 0 # 0 means red je @red # jump if equal (i.e. red) jmp @green # jump 7 loop do grab case apple_color when :red move_to(:right) when :green move_to(:left) end release move_to(:bucket) end -
grab # grab apple getcolor r0 # r0 now contains
apple color cmp r0, 0 # 0 means red je @red # jump if equal (i.e. red) jmp @green # jump green: 7 loop do grab case apple_color when :red move_to(:right) when :green move_to(:left) end release move_to(:bucket) end -
grab # grab apple getcolor r0 # r0 now contains
apple color cmp r0, 0 # 0 means red je @red # jump if equal (i.e. red) jmp @green # jump green: mvarm 1 # move arm (1 means left) 7 loop do grab case apple_color when :red move_to(:right) when :green move_to(:left) end release move_to(:bucket) end -
grab # grab apple getcolor r0 # r0 now contains
apple color cmp r0, 0 # 0 means red je @red # jump if equal (i.e. red) jmp @green # jump green: mvarm 1 # move arm (1 means left) jmp @done # jump 7 loop do grab case apple_color when :red move_to(:right) when :green move_to(:left) end release move_to(:bucket) end -
grab # grab apple getcolor r0 # r0 now contains
apple color cmp r0, 0 # 0 means red je @red # jump if equal (i.e. red) jmp @green # jump green: mvarm 1 # move arm (1 means left) jmp @done # jump red: 7 loop do grab case apple_color when :red move_to(:right) when :green move_to(:left) end release move_to(:bucket) end -
grab # grab apple getcolor r0 # r0 now contains
apple color cmp r0, 0 # 0 means red je @red # jump if equal (i.e. red) jmp @green # jump green: mvarm 1 # move arm (1 means left) jmp @done # jump red: mvarm 2 # move arm (2 means right) 7 loop do grab case apple_color when :red move_to(:right) when :green move_to(:left) end release move_to(:bucket) end -
grab # grab apple getcolor r0 # r0 now contains
apple color cmp r0, 0 # 0 means red je @red # jump if equal (i.e. red) jmp @green # jump green: mvarm 1 # move arm (1 means left) jmp @done # jump red: mvarm 2 # move arm (2 means right) jmp @done # jump 7 loop do grab case apple_color when :red move_to(:right) when :green move_to(:left) end release move_to(:bucket) end -
grab # grab apple getcolor r0 # r0 now contains
apple color cmp r0, 0 # 0 means red je @red # jump if equal (i.e. red) jmp @green # jump green: mvarm 1 # move arm (1 means left) jmp @done # jump red: mvarm 2 # move arm (2 means right) jmp @done # jump done: 7 loop do grab case apple_color when :red move_to(:right) when :green move_to(:left) end release move_to(:bucket) end -
grab # grab apple getcolor r0 # r0 now contains
apple color cmp r0, 0 # 0 means red je @red # jump if equal (i.e. red) jmp @green # jump green: mvarm 1 # move arm (1 means left) jmp @done # jump red: mvarm 2 # move arm (2 means right) jmp @done # jump done: release # release apple (falls in target pile) 7 loop do grab case apple_color when :red move_to(:right) when :green move_to(:left) end release move_to(:bucket) end -
grab # grab apple getcolor r0 # r0 now contains
apple color cmp r0, 0 # 0 means red je @red # jump if equal (i.e. red) jmp @green # jump green: mvarm 1 # move arm (1 means left) jmp @done # jump red: mvarm 2 # move arm (2 means right) jmp @done # jump done: release # release apple (falls in target pile) mvarm 0 # move arm (0 means middle) 7 loop do grab case apple_color when :red move_to(:right) when :green move_to(:left) end release move_to(:bucket) end -
grab # grab apple getcolor r0 # r0 now contains
apple color cmp r0, 0 # 0 means red je @red # jump if equal (i.e. red) jmp @green # jump green: mvarm 1 # move arm (1 means left) jmp @done # jump red: mvarm 2 # move arm (2 means right) jmp @done # jump done: release # release apple (falls in target pile) mvarm 0 # move arm (0 means middle) jmp @start # jump 7 loop do grab case apple_color when :red move_to(:right) when :green move_to(:left) end release move_to(:bucket) end -
start: grab # grab apple getcolor r0 # r0 now
contains apple color cmp r0, 0 # 0 means red je @red # jump if equal (i.e. red) jmp @green # jump green: mvarm 1 # move arm (1 means left) jmp @done # jump red: mvarm 2 # move arm (2 means right) jmp @done # jump done: release # release apple (falls in target pile) mvarm 0 # move arm (0 means middle) jmp @start # jump 7 loop do grab case apple_color when :red move_to(:right) when :green move_to(:left) end release move_to(:bucket) end -
start: grab # grab apple getcolor r0 # r0 now
contains apple color cmp r0, 0 # 0 means red je @red # jump if equal (i.e. red) jmp @green # jump green: mvarm 1 # move arm (1 means left) jmp @done # jump red: mvarm 2 # move arm (2 means right) jmp @done # jump done: release # release apple (falls in target pile) mvarm 0 # move arm (0 means middle) jmp @start # jump 7 loop do grab case apple_color when :red move_to(:right) when :green move_to(:left) end release move_to(:bucket) end -
start: grab # grab apple getcolor r0 # r0 now
contains apple color cmp r0, 0 # 0 means red je @red # jump if equal (i.e. red) jmp @green # jump green: mvarm 1 # move arm (1 means left) jmp @done # jump red: mvarm 2 # move arm (2 means right) jmp @done # jump done: release # release apple (falls in target pile) mvarm 0 # move arm (0 means middle) jmp @start # jump 7 loop do grab case apple_color when :red move_to(:right) when :green move_to(:left) end release move_to(:bucket) end -
lv r0, 100 lv r1, 200 add r2, r0, r1
prn r2 11 -
lv r0, 100 lv r1, 200 add r2, r0, r1
prn r2 halt 11 -
def gcd(a, b) while b != 0 t = b
b = a % b a = t end a end 12 -
13 def gcd(r0, r1) while r1 != 0 r2 =
r1 r1 = r0 % r1 r0 = r2 end r0 end -
lv r0, 819000 # r0 = 819000 13 def gcd(r0,
r1) while r1 != 0 r2 = r1 r1 = r0 % r1 r0 = r2 end r0 end -
lv r0, 819000 # r0 = 819000 lv r1, 254163
# r1 = 254163 13 def gcd(r0, r1) while r1 != 0 r2 = r1 r1 = r0 % r1 r0 = r2 end r0 end -
lv r0, 819000 # r0 = 819000 lv r1, 254163
# r1 = 254163 cmp r1, 0 # compare r1 with 0 13 def gcd(r0, r1) while r1 != 0 r2 = r1 r1 = r0 % r1 r0 = r2 end r0 end -
lv r0, 819000 # r0 = 819000 lv r1, 254163
# r1 = 254163 cmp r1, 0 # compare r1 with 0 je @end # jump to @end if = 13 def gcd(r0, r1) while r1 != 0 r2 = r1 r1 = r0 % r1 r0 = r2 end r0 end -
lv r0, 819000 # r0 = 819000 lv r1, 254163
# r1 = 254163 cmp r1, 0 # compare r1 with 0 je @end # jump to @end if = mov r2, r1 # r2 <— r1 13 def gcd(r0, r1) while r1 != 0 r2 = r1 r1 = r0 % r1 r0 = r2 end r0 end -
lv r0, 819000 # r0 = 819000 lv r1, 254163
# r1 = 254163 cmp r1, 0 # compare r1 with 0 je @end # jump to @end if = mov r2, r1 # r2 <— r1 mod r1, r0, r1 # r1 <— r0 % r1 13 def gcd(r0, r1) while r1 != 0 r2 = r1 r1 = r0 % r1 r0 = r2 end r0 end -
lv r0, 819000 # r0 = 819000 lv r1, 254163
# r1 = 254163 cmp r1, 0 # compare r1 with 0 je @end # jump to @end if = mov r2, r1 # r2 <— r1 mod r1, r0, r1 # r1 <— r0 % r1 mov r0, r2 # r0 <— r2 13 def gcd(r0, r1) while r1 != 0 r2 = r1 r1 = r0 % r1 r0 = r2 end r0 end -
lv r0, 819000 # r0 = 819000 lv r1, 254163
# r1 = 254163 cmp r1, 0 # compare r1 with 0 je @end # jump to @end if = mov r2, r1 # r2 <— r1 mod r1, r0, r1 # r1 <— r0 % r1 mov r0, r2 # r0 <— r2 jmp @start # jump to @start 13 def gcd(r0, r1) while r1 != 0 r2 = r1 r1 = r0 % r1 r0 = r2 end r0 end -
lv r0, 819000 # r0 = 819000 lv r1, 254163
# r1 = 254163 cmp r1, 0 # compare r1 with 0 je @end # jump to @end if = mov r2, r1 # r2 <— r1 mod r1, r0, r1 # r1 <— r0 % r1 mov r0, r2 # r0 <— r2 jmp @start # jump to @start 13 def gcd(r0, r1) while r1 != 0 r2 = r1 r1 = r0 % r1 r0 = r2 end r0 end start: -
end: lv r0, 819000 # r0 = 819000 lv r1, 254163 # r1 = 254163 cmp r1, 0 # compare r1 with 0 je @end # jump to @end if = mov r2, r1 # r2 <— r1 mod r1, r0, r1 # r1 <— r0 % r1 mov r0, r2 # r0 <— r2 jmp @start # jump to @start 13 def gcd(r0, r1) while r1 != 0 r2 = r1 r1 = r0 % r1 r0 = r2 end r0 end start: -
end: prn r0 # print r0 (our gcd!) lv r0, 819000 # r0 = 819000 lv r1, 254163 # r1 = 254163 cmp r1, 0 # compare r1 with 0 je @end # jump to @end if = mov r2, r1 # r2 <— r1 mod r1, r0, r1 # r1 <— r0 % r1 mov r0, r2 # r0 <— r2 jmp @start # jump to @start 13 def gcd(r0, r1) while r1 != 0 r2 = r1 r1 = r0 % r1 r0 = r2 end r0 end start: -
end: prn r0 # print r0 (our gcd!) halt # shut down lv r0, 819000 # r0 = 819000 lv r1, 254163 # r1 = 254163 cmp r1, 0 # compare r1 with 0 je @end # jump to @end if = mov r2, r1 # r2 <— r1 mod r1, r0, r1 # r1 <— r0 % r1 mov r0, r2 # r0 <— r2 jmp @start # jump to @start 13 def gcd(r0, r1) while r1 != 0 r2 = r1 r1 = r0 % r1 r0 = r2 end r0 end start: -
1000 000c 7f38 1001 0003 e0d3 1201 0000 0000 0720
0f02 0113 0100 010f 0002 060c 0e00 ff 14 -
1000 000c 7f38 1001 0003 e0d3 1201 0000 0000 0720
0f02 01 1301 0001 0f00 02 060c 0e00 ff 15 -
1000 000c 7f38 1001 0003 e0d3 1201 0000 0000 0720
0f02 01 1301 0001 0f00 02 060c 0e00 ff 1000 000c 7f38 lv r0, 819000 15 -
1000 000c 7f38 1001 0003 e0d3 1201 0000 0000 0720
0f02 01 1301 0001 0f00 02 060c 0e00 ff 1000 000c 7f38 lv r0, 819000 1001 0003 e0d3 lv r1, 254163 15 -
1000 000c 7f38 1001 0003 e0d3 1201 0000 0000 0720
0f02 01 1301 0001 0f00 02 060c 0e00 ff 1000 000c 7f38 lv r0, 819000 1001 0003 e0d3 lv r1, 254163 1201 0000 0000 cmp r1, 0 15 -
1000 000c 7f38 1001 0003 e0d3 1201 0000 0000 0720
0f02 01 1301 0001 0f00 02 060c 0e00 ff 1000 000c 7f38 lv r0, 819000 1001 0003 e0d3 lv r1, 254163 1201 0000 0000 cmp r1, 0 0720 je @end 15 -
1000 000c 7f38 1001 0003 e0d3 1201 0000 0000 0720
0f02 01 1301 0001 0f00 02 060c 0e00 ff 1000 000c 7f38 lv r0, 819000 1001 0003 e0d3 lv r1, 254163 1201 0000 0000 cmp r1, 0 0720 je @end 0f02 01 mov r2, r1 15 -
1000 000c 7f38 1001 0003 e0d3 1201 0000 0000 0720
0f02 01 1301 0001 0f00 02 060c 0e00 ff 1000 000c 7f38 lv r0, 819000 1001 0003 e0d3 lv r1, 254163 1201 0000 0000 cmp r1, 0 0720 je @end 0f02 01 mov r2, r1 1301 0001 mod r1, r0, r1 15 -
1000 000c 7f38 1001 0003 e0d3 1201 0000 0000 0720
0f02 01 1301 0001 0f00 02 060c 0e00 ff 1000 000c 7f38 lv r0, 819000 1001 0003 e0d3 lv r1, 254163 1201 0000 0000 cmp r1, 0 0720 je @end 0f02 01 mov r2, r1 1301 0001 mod r1, r0, r1 0f00 02 mov r0, r2 15 -
1000 000c 7f38 1001 0003 e0d3 1201 0000 0000 0720
0f02 01 1301 0001 0f00 02 060c 0e00 ff 1000 000c 7f38 lv r0, 819000 1001 0003 e0d3 lv r1, 254163 1201 0000 0000 cmp r1, 0 0720 je @end 0f02 01 mov r2, r1 1301 0001 mod r1, r0, r1 0f00 02 mov r0, r2 060c jmp @start 15 -
1000 000c 7f38 1001 0003 e0d3 1201 0000 0000 0720
0f02 01 1301 0001 0f00 02 060c 0e00 ff 1000 000c 7f38 lv r0, 819000 1001 0003 e0d3 lv r1, 254163 1201 0000 0000 cmp r1, 0 0720 je @end 0f02 01 mov r2, r1 1301 0001 mod r1, r0, r1 0f00 02 mov r0, r2 060c jmp @start 0e00 prn r0 15 -
1000 000c 7f38 1001 0003 e0d3 1201 0000 0000 0720
0f02 01 1301 0001 0f00 02 060c 0e00 ff 1000 000c 7f38 lv r0, 819000 1001 0003 e0d3 lv r1, 254163 1201 0000 0000 cmp r1, 0 0720 je @end 0f02 01 mov r2, r1 1301 0001 mod r1, r0, r1 0f00 02 mov r0, r2 060c jmp @start 0e00 prn r0 ff halt 15 -
Machine code is executed by actual, physical CPUs. Bytecode is
executed by virtual machines. 16 -
0000000000001f76 <_rb_ary_freeze>: 1f76: 55 push %rbp 1f77: 48 89 e5
mov %rsp,%rbp 1f7a: 5d pop %rbp 1f7b: e9 32 b6 07 00 jmpq 7d5b2 <_rb_obj_freeze> 0000000000002483 <_rb_ary_free>: 2483: 55 push %rbp 2484: 48 89 e5 mov %rsp,%rbp 2487: 40 f6 c7 07 test $0x7,%dil 248b: 75 23 jne 24b0 <_rb_ary_free+0x2d> 248d: 48 89 f8 mov %rdi,%rax 2490: 48 83 e0 f7 and $0xfffffffffffffff7,%rax 2494: 74 1a je 24b0 <_rb_ary_free+0x2d> 2496: 48 8b 07 mov (%rdi),%rax 2499: 48 89 c1 mov %rax,%rcx 249c: 48 83 e1 1f and $0x1f,%rcx 24a0: 48 83 f9 1c cmp $0x1c,%rcx 24a4: 74 0a je 24b0 <_rb_ary_free+0x2d> 24a6: 48 25 00 60 00 00 and $0x6000,%rax 24ac: 74 02 je 24b0 <_rb_ary_free+0x2d> 24ae: 5d pop %rbp 24af: c3 retq 24b0: 48 8b 7f 20 mov 0x20(%rdi),%rdi 24b4: 5d pop %rbp 24b5: e9 23 39 04 00 jmpq 45ddd <_ruby_xfree> 19 X86 -
0010c00 <main.init.1>: 10c00: e59a1008 ldr r1, [sl, #8] 10c04: e15d0001
cmp sp, r1 10c08: 91a0300e movls r3, lr 10c0c: 9b01a46b blls 79dc0 <runtime.morestack_noctxt> 10c10: 9afffffa bls 10c00 <main.init.1> 10c14: e52de044 str lr, [sp, #-68]! ; 0xffffffbc 10c18: e59fb19c ldr fp, [pc, #412] ; 10dbc <main.init.1+0x1bc> 10c1c: e5db0000 ldrb r0, [fp] 10c20: e3500000 cmp r0, #0 10c24: 0a000062 beq 10db4 <main.init.1+0x1b4> 10c28: e59f1190 ldr r1, [pc, #400] ; 10dc0 <main.init.1+0x1c0> 10c2c: e28d0004 add r0, sp, #4 10c30: e4912004 ldr r2, [r1], #4 10c34: e4802004 str r2, [r0], #4 10c38: e4912004 ldr r2, [r1], #4 10c3c: e4802004 str r2, [r0], #4 10c40: eb021a3a bl 97530 <os.Getenv> 10c44: e28d000c add r0, sp, #12 10c48: e5901000 ldr r1, [r0] 10c4c: e5901004 ldr r1, [r0, #4] 10c50: e58d1034 str r1, [sp, #52] ; 0x34 10c54: e59d0034 ldr r0, [sp, #52] ; 0x34 10c58: e3500000 cmp r0, #0 10c5c: 0a000054 beq 10db4 <main.init.1+0x1b4> 10c60: e59f115c ldr r1, [pc, #348] ; 10dc4 <main.init.1+0x1c4> 10c64: e28d0004 add r0, sp, #4 10c68: e4912004 ldr r2, [r1], #4 10c6c: e4802004 str r2, [r0], #4 10c70: e4912004 ldr r2, [r1], #4 10c74: e4802004 str r2, [r0], #4 20 ARM -
22 1. Fetch instruction 2. Execute instruction 3. Move to
next instruction -
1000 000c 7f38 1001 0003 e0d3 1201 0000 0000 0720
0f02 01 1301 0001 0f00 02 060c 0e00 ff 24 RPC 0 -
1000 000c 7f38 1001 0003 e0d3 1201 0000 0000 0720
0f02 01 1301 0001 0f00 02 060c 0e00 ff 24 RPC 6 -
1000 000c 7f38 1001 0003 e0d3 1201 0000 0000 0720
0f02 01 1301 0001 0f00 02 060c 0e00 ff 24 RPC 12 -
1000 000c 7f38 1001 0003 e0d3 1201 0000 0000 0720
0f02 01 1301 0001 0f00 02 060c 0e00 ff 24 RPC 18 -
1000 000c 7f38 1001 0003 e0d3 1201 0000 0000 0720
0f02 01 1301 0001 0f00 02 060c 0e00 ff 24 RPC 20 -
27 j je jne jg jge jl jle cmp mod
add sub mul div xor or and shl shr not lw lh lb sw sh sb STACK FUNC SPECIAL call ret push pop prn halt BRANCHING ARITHMETIC mov li MEMORY REG -
31 This talk would not have been the same without
some great assets that I could use for free. The fonts in this presentation are Clear Sans by Intel (01.org/clear-sans) and Ubuntu Mono by Canonical Ltd (font.ubuntu.com). The apple sprite is by http://chrisdesign.wordpress.com/. -
33 25 15 RPC + 5 old RBP old R0
old R1 old R2 CALLER CALLEE -
lv r0, 100 cmpi r0, 100 # rflags is now
0x01 (equal) 34 -
lv r0, 100 cmpi r0, 100 # rflags is now
0x01 (equal) cmpi r0, 99 # rflags is now 0x02 (greater than) 34