1 # Rudimentary test harness 2 3 == code 4 # instruction effective address register displacement immediate 5 # . op subop mod rm32 base index scale r32 6 # . 1-3 bytes 3 bits 2 bits 3 bits 3 bits 3 bits 2 bits 2 bits 0/1/2/4 bytes 0/1/2/4 bytes 7 8 #? Entry: # manual test 9 #? # check-ints-equal(34, 34) 10 #? # . . push args 11 #? 68/push "error in check-ints-equal"/imm32 12 #? 68/push 34/imm32 13 #? 68/push 34/imm32 14 #? # . . call 15 #? e8/call check-ints-equal/disp32 16 #? # . . discard args 17 #? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 18 #? # syscall_exit(0) 19 #? bb/copy-to-ebx 0/imm32 20 #? e8/call syscall_exit/disp32 21 22 # print msg to stderr if a != b, otherwise print "." 23 check-ints-equal: # a: int, b: int, msg: (addr array byte) 24 # . prologue 25 55/push-ebp 26 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 27 # . save registers 28 50/push-eax 29 51/push-ecx 30 53/push-ebx 31 # load first 2 args into eax and ebx 32 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 0/r32/eax 8/disp8 . # copy *(ebp+8) to eax 33 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 3/r32/ebx 0xc/disp8 . # copy *(ebp+12) to ebx 34 # if (eax == ebx) success 35 39/compare 3/mod/direct 0/rm32/eax . . . 3/r32/ebx . . # compare eax and ebx 36 75/jump-if-unequal $check-ints-equal:else/disp8 37 # . _write(2/stderr, '.') 38 # . . push args 39 68/push "."/imm32 40 68/push 2/imm32/stderr 41 # . . call 42 e8/call _write/disp32 43 # . . discard args 44 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 45 # . return 46 eb/jump $check-ints-equal:end/disp8 47 # otherwise print error message 48 $check-ints-equal:else: 49 # . _write(2/stderr, msg) 50 # . . push args 51 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 1/r32/ecx 0x10/disp8 . # copy *(ebp+16) to ecx 52 51/push-ecx 53 68/push 2/imm32/stderr 54 # . . call 55 e8/call _write/disp32 56 # . . discard args 57 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 58 # . _write(2/stderr, Newline) 59 # . . push args 60 68/push Newline/imm32 61 68/push 2/imm32/stderr 62 # . . call 63 e8/call _write/disp32 64 # . . discard args 65 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 66 # increment Num-test-failures 67 ff 0/subop/increment 0/mod/indirect 5/rm32/.disp32 . . . Num-test-failures/disp32 # increment *Num-test-failures 68 $check-ints-equal:end: 69 # . restore registers 70 5b/pop-to-ebx 71 59/pop-to-ecx 72 58/pop-to-eax 73 # . epilogue 74 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 75 5d/pop-to-ebp 76 c3/return 77 78 == data 79 80 # length-prefixed string containing just a single newline 81 # convenient to have when printing messages and so on 82 Newline: # (array byte) 83 # size: int 84 1/imm32 85 # data 86 0a/newline 87 88 # every test failure increments this counter 89 Num-test-failures: # int 90 0/imm32 91 92 # length-prefixed string containing just a single space 93 Space: # (array byte) 94 # size: int 95 1/imm32 96 # data 97 20/space 98 99 # length-prefixed string containing just a single slash 100 Slash: # (array byte) 101 # size: int 102 1/imm32 103 # data 104 2f/slash 105 106 # . . vim:nowrap:textwidth=0