1 == code
 2 
 3 # instruction                     effective address                                                   operand     displacement    immediate
 4 # op          subop               mod             rm32          base        index         scale       r32
 5 # 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
 6 
 7 # print msg to stderr if a != b, otherwise print "."
 8 check_ints_equal:  # (a : int, b : int, msg : (address array byte)) -> boolean
 9   # prolog
10   55/push-EBP
11   89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
12   # save registers
13   51/push-ECX
14   53/push-EBX
15   # load args into EAX, EBX and ECX
16   8b/copy                         1/mod/*+disp8   4/rm32/sib    5/base/EBP  4/index/none  .           0/r32/EAX   0x8/disp8       .                 # copy *(EBP+8) to EAX
17   8b/copy                         1/mod/*+disp8   4/rm32/sib    5/base/EBP  4/index/none  .           3/r32/EBX   0xc/disp8       .                 # copy *(EBP+12) to EBX
18   # if EAX == b/EBX
19   39/compare                      3/mod/direct    0/rm32/EAX    .           .             .           3/r32/EBX   .               .                 # compare EAX and EBX
20   75/jump-if-unequal  $check_ints_equal:else/disp8
21     # print('.')
22       # push args
23   68/push  "."/imm32
24       # call
25   e8/call  write_stderr/disp32
26       # discard arg
27   81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
28     # return
29   eb/jump  $check_ints_equal:end/disp8
30   # else:
31 $check_ints_equal:else:
32   # copy msg into ECX
33   8b/copy                         1/mod/*+disp8   4/rm32/sib    5/base/EBP  4/index/none  .           1/r32/ECX   0x10/disp8       .                # copy *(EBP+16) to ECX
34     # print(ECX)
35       # push args
36   51/push-ECX
37       # call
38   e8/call  write_stderr/disp32
39       # discard arg
40   81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
41     # print newline
42       # push args
43   68/push  Newline/imm32
44       # call
45   e8/call  write_stderr/disp32
46       # discard arg
47   81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
48 $check_ints_equal:end:
49   # restore registers
50   5b/pop-to-EBX
51   59/pop-to-ECX
52   # end
53   89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
54   5d/pop-to-EBP
55   c3/return
56 
57 == data
58 
59 Newline:
60   # size
61   01 00 00 00
62   # data
63   0a/newline
64 
65 # vim:ft=subx:nowrap:tw&