about summary refs log tree commit diff stats
path: root/subx
diff options
context:
space:
mode:
Diffstat (limited to 'subx')
-rw-r--r--subx/apps/crenshaw2-1bin1217 -> 1245 bytes
-rw-r--r--subx/apps/crenshaw2-1.subx112
-rwxr-xr-xsubx/apps/factorialbin1215 -> 1243 bytes
-rw-r--r--subx/apps/factorial.subx49
-rw-r--r--subx/examples/ex11bin1034 -> 1062 bytes
-rw-r--r--subx/examples/ex11.subx50
6 files changed, 158 insertions, 53 deletions
diff --git a/subx/apps/crenshaw2-1 b/subx/apps/crenshaw2-1
index f5d28502..cb0429f3 100644
--- a/subx/apps/crenshaw2-1
+++ b/subx/apps/crenshaw2-1
Binary files differdiff --git a/subx/apps/crenshaw2-1.subx b/subx/apps/crenshaw2-1.subx
index 00481453..b1df5889 100644
--- a/subx/apps/crenshaw2-1.subx
+++ b/subx/apps/crenshaw2-1.subx
@@ -85,9 +85,15 @@ error:  # s : (address array byte) -> <void>
 
 # print msg to stderr if a != b, otherwise print "."
 check_ints_equal:  # (a : int, b : int, msg : (address array byte)) -> boolean
+  # prolog
+  55/push-EBP
+  89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+  # save registers
+  51/push-ECX
+  53/push-EBX
   # load args into EAX, EBX and ECX
-  8b/copy                         1/mod/*+disp8   4/rm32/sib    4/base/ESP  4/index/none  .           0/r32/EAX   0xc/disp8       .                 # copy *(ESP+12) to EAX
-  8b/copy                         1/mod/*+disp8   4/rm32/sib    4/base/ESP  4/index/none  .           3/r32/EBX   0x8/disp8       .                 # copy *(ESP+8) to EBX
+  8b/copy                         1/mod/*+disp8   4/rm32/sib    5/base/EBP  4/index/none  .           0/r32/EAX   0x8/disp8       .                 # copy *(EBP+8) to EAX
+  8b/copy                         1/mod/*+disp8   4/rm32/sib    5/base/EBP  4/index/none  .           3/r32/EBX   0xc/disp8       .                 # copy *(EBP+12) to EBX
   # if EAX == b/EBX
   39/compare                      3/mod/direct    0/rm32/EAX    .           .             .           3/r32/EBX   .               .                 # compare EAX and EBX
   75/jump-if-unequal  $check_ints_equal:else/disp8
@@ -99,11 +105,11 @@ check_ints_equal:  # (a : int, b : int, msg : (address array byte)) -> boolean
       # discard arg
   81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add 4 to ESP
     # return
-  c3/return
+  eb/jump  $check_ints_equal:end/disp8
   # else:
 $check_ints_equal:else:
   # copy msg into ECX
-  8b/copy                         1/mod/*+disp8   4/rm32/sib    4/base/ESP  4/index/none  .           1/r32/ECX   4/disp8         .                 # copy *(ESP+4) to ECX
+  8b/copy                         1/mod/*+disp8   4/rm32/sib    5/base/EBP  4/index/none  .           1/r32/ECX   0x10/disp8       .                # copy *(EBP+16) to ECX
     # print(ECX)
       # push args
   51/push-ECX
@@ -118,13 +124,28 @@ $check_ints_equal:else:
   e8/call  write_stderr/disp32
       # discard arg
   81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add 4 to ESP
+$check_ints_equal:end:
+  # restore registers
+  5b/pop-to-EBX
+  59/pop-to-ECX
   # end
+  89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
+  5d/pop-to-EBP
   c3/return
 
 # compare a null-terminated ascii string with a more idiomatic length-prefixed byte array
 # reason for the name: the only place we should have null-terminated ascii strings is from commandline args
 argv_equal:  # s : null-terminated ascii string, benchmark : length-prefixed ascii string -> EAX : boolean
-# {{{
+  # prolog
+  55/push-EBP
+  89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+  # save registers
+  51/push-ECX
+  52/push-EDX
+  53/push-EBX
+  56/push-ESI
+  57/push-EDI
+
   # pseudocode:
   #   initialize n = b.length
   #   initialize s1 = s
@@ -138,13 +159,14 @@ argv_equal:  # s : null-terminated ascii string, benchmark : length-prefixed asc
   #     if c1 != c2
   #       return false
   #   return *s1 == 0
+# {{{
   # initialize s into EDI
-  8b/copy                         1/mod/*+disp8   4/rm32/sib    4/base/ESP  4/index/none  .           7/r32/EDI   8/disp8         .                 # copy *(ESP+8) to EDI
+  8b/copy                         1/mod/*+disp8   4/rm32/sib    5/base/EBP  4/index/none  .           7/r32/EDI   8/disp8         .                 # copy *(EBP+8) to EDI
   # initialize benchmark length n into EDX
-  8b/copy                         1/mod/*+disp8   4/rm32/sib    4/base/ESP  4/index/none  .           2/r32/EDX   4/disp8         .                 # copy *(ESP+4) to EDX
+  8b/copy                         1/mod/*+disp8   4/rm32/sib    5/base/EBP  4/index/none  .           2/r32/EDX   0xc/disp8       .                 # copy *(EBP+12) to EDX
   8b/copy                         0/mod/indirect  2/rm32/EDX    .           .             .           2/r32/EDX   .               .                 # copy *EDX to EDX
   # initialize benchmark data into ESI
-  8b/copy                         1/mod/*+disp8   4/rm32/sib    4/base/ESP  4/index/none  .           6/r32/ESI   4/disp8         .                 # copy *(ESP+4) to ESI
+  8b/copy                         1/mod/*+disp8   4/rm32/sib    5/base/EBP  4/index/none  .           6/r32/ESI   0xc/disp8       .                 # copy *(EBP+12) to ESI
   81          0/subop/add         3/mod/direct    6/rm32/ESI    .           .             .           .           .               4/imm32           # add 4 to ESI
   # initialize loop counter i into ECX
   b9/copy                         .               .             .           .             .           .           .               0/imm32/exit      # copy 1 to ECX
@@ -176,26 +198,38 @@ $argv_break:
   81          7/subop/compare     3/mod/direct    0/rm32/EAX    .           .             .           .           .               0/imm32           # compare EAX with 0
   75/jump-if-not-equal  $argv_fail/disp8
   b8/copy                         .               .             .           .             .           .           .               1/imm32           # copy 1 to EAX
-  c3/return
+  eb/jump  $argv_end/disp8
   # return false
 $argv_fail:
   b8/copy                         .               .             .           .             .           .           .               0/imm32           # copy 0 to EAX
+
+$argv_end:
+  # restore registers
+  5f/pop-to-EDI
+  5e/pop-to-ESI
+  5b/pop-to-EBX
+  5a/pop-to-EDX
+  59/pop-to-ECX
+  # end
+  89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
+  5d/pop-to-EBP
   c3/return
 # }}}
 # tests for argv_equal {{{
 test_compare_null_argv_with_empty_array:
   # EAX = argv_equal(Null_argv, "")
     # push args
-  68/push  Null_argv/imm32
   68/push  ""/imm32
+  68/push  Null_argv/imm32
     # call
   e8/call  argv_equal/disp32
     # discard args
   81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add 8 to ESP
-  # call check_ints_equal(EAX, 1)
-  50/push-EAX
-  68/push  1/imm32/true
+  # call check_ints_equal(EAX, 1, msg)
+    # push args
   68/push  "F - test_compare_null_argv_with_empty_array"/imm32
+  68/push  1/imm32/true
+  50/push-EAX
     # call
   e8/call  check_ints_equal/disp32
     # discard args
@@ -205,16 +239,17 @@ test_compare_null_argv_with_empty_array:
 test_compare_null_argv_with_non_empty_array:
   # EAX = argv_equal(Null_argv, "Abc")
     # push args
-  68/push  Null_argv/imm32
   68/push  "Abc"/imm32
+  68/push  Null_argv/imm32
     # call
   e8/call  argv_equal/disp32
     # discard args
   81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add 8 to ESP
-  # call check_ints_equal(EAX, 0)
-  50/push-EAX
-  68/push  0/imm32/false
+  # call check_ints_equal(EAX, 0, msg)
+    # push args
   68/push  "F - test_compare_null_argv_with_non_empty_array"/imm32
+  68/push  0/imm32/false
+  50/push-EAX
     # call
   e8/call  check_ints_equal/disp32
     # discard args
@@ -224,16 +259,17 @@ test_compare_null_argv_with_non_empty_array:
 test_compare_argv_with_equal_array:
   # EAX = argv_equal(Abc_argv, "Abc")
     # push args
-  68/push  Abc_argv/imm32
   68/push  "Abc"/imm32
+  68/push  Abc_argv/imm32
     # call
   e8/call  argv_equal/disp32
     # discard args
   81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add 8 to ESP
-  # call check_ints_equal(EAX, 1)
-  50/push-EAX
-  68/push  1/imm32/true
+  # call check_ints_equal(EAX, 1, msg)
+    # push args
   68/push  "F - test_compare_argv_with_equal_array"/imm32
+  68/push  1/imm32/true
+  50/push-EAX
     # call
   e8/call  check_ints_equal/disp32
     # discard args
@@ -243,16 +279,17 @@ test_compare_argv_with_equal_array:
 test_compare_argv_with_inequal_array:
   # EAX = argv_equal(Abc_argv, "Adc")
     # push args
-  68/push  Abc_argv/imm32
   68/push  "Adc"/imm32
+  68/push  Abc_argv/imm32
     # call
   e8/call  argv_equal/disp32
     # discard args
   81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add 8 to ESP
-  # call check_ints_equal(EAX, 0)
-  50/push-EAX
-  68/push  0/imm32/false
+  # call check_ints_equal(EAX, 0, msg)
+    # push args
   68/push  "F - test_compare_argv_with_equal_array"/imm32
+  68/push  0/imm32/false
+  50/push-EAX
     # call
   e8/call  check_ints_equal/disp32
     # discard args
@@ -262,16 +299,17 @@ test_compare_argv_with_inequal_array:
 test_compare_argv_with_empty_array:
   # EAX = argv_equal(Abc_argv, "")
     # push args
-  68/push  Abc_argv/imm32
   68/push  ""/imm32
+  68/push  Abc_argv/imm32
     # call
   e8/call  argv_equal/disp32
     # discard args
   81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add 8 to ESP
   # call check_ints_equal(EAX, 0)
-  50/push-EAX
-  68/push  0/imm32/false
+    # push args
   68/push  "F - test_compare_argv_with_equal_array"/imm32
+  68/push  0/imm32/false
+  50/push-EAX
     # call
   e8/call  check_ints_equal/disp32
     # discard args
@@ -281,16 +319,17 @@ test_compare_argv_with_empty_array:
 test_compare_argv_with_shorter_array:
   # EAX = argv_equal(Abc_argv, "Ab")
     # push args
-  68/push  Abc_argv/imm32
   68/push  "Ab"/imm32
+  68/push  Abc_argv/imm32
     # call
   e8/call  argv_equal/disp32
     # discard args
   81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add 8 to ESP
   # call check_ints_equal(EAX, 0)
-  50/push-EAX
-  68/push  0/imm32/false
+    # push args
   68/push  "F - test_compare_argv_with_shorter_array"/imm32
+  68/push  0/imm32/false
+  50/push-EAX
     # call
   e8/call  check_ints_equal/disp32
     # discard args
@@ -300,16 +339,17 @@ test_compare_argv_with_shorter_array:
 test_compare_argv_with_longer_array:
   # EAX = argv_equal(Abc_argv, "Abcd")
     # push args
-  68/push  Abc_argv/imm32
   68/push  "Abcd"/imm32
+  68/push  Abc_argv/imm32
     # call
   e8/call  argv_equal/disp32
     # discard args
   81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add 8 to ESP
   # call check_ints_equal(EAX, 0)
-  50/push-EAX
-  68/push  0/imm32/false
+    # push args
   68/push  "F - test_compare_argv_with_longer_array"/imm32
+  68/push  0/imm32/false
+  50/push-EAX
     # call
   e8/call  check_ints_equal/disp32
     # discard args
@@ -361,10 +401,10 @@ write_stdout:  # s : (address array byte) -> <void>
     # fd = 1 (stdout)
   bb/copy                         .               .             .           .             .           .           .               1/imm32           # copy 1 to EBX
     # x = s+4
-  8b/copy                         1/mod/*+disp8   4/rm32/SIB    4/base/ESP  4/index/none  .           1/r32/ECX   8/disp8         .                 # copy *(ESP+8) to ECX
+  8b/copy                         1/mod/*+disp8   4/rm32/SIB    5/base/EBP  4/index/none  .           1/r32/ECX   8/disp8         .                 # copy *(EBP+8) to ECX
   81          0/subop/add         3/mod/direct    1/rm32/ECX    .           .             .           .           .               4/imm32           # add 4 to ECX
     # size = *s
-  8b/copy                         1/mod/*+disp8   4/rm32/SIB    4/base/ESP  4/index/none  .           2/r32/EDX   8/disp8         .                 # copy *(ESP+8) to EDX
+  8b/copy                         1/mod/*+disp8   4/rm32/SIB    5/base/EBP  4/index/none  .           2/r32/EDX   8/disp8         .                 # copy *(EBP+8) to EDX
   8b/copy                         0/mod/indirect  2/rm32/EDX    .           .             .           2/r32/EDX   .               .                 # copy *EDX to EDX
     # call write()
   b8/copy                         .               .             .           .             .           .           .               4/imm32/write     # copy 1 to EAX
diff --git a/subx/apps/factorial b/subx/apps/factorial
index f0505cba..3d052619 100755
--- a/subx/apps/factorial
+++ b/subx/apps/factorial
Binary files differdiff --git a/subx/apps/factorial.subx b/subx/apps/factorial.subx
index b6d904ba..b4f8867e 100644
--- a/subx/apps/factorial.subx
+++ b/subx/apps/factorial.subx
@@ -106,9 +106,15 @@ test_factorial:
 
 # print msg to stderr if a != b, otherwise print "."
 check_ints_equal:  # (a : int, b : int, msg : (address array byte)) -> boolean
+  # prolog
+  55/push-EBP
+  89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+  # save registers
+  51/push-ECX
+  53/push-EBX
   # load args into EAX, EBX and ECX
-  8b/copy                         1/mod/*+disp8   4/rm32/sib    4/base/ESP  4/index/none  .           0/r32/EAX   0x4/disp8       .                 # copy *(ESP+4) to EAX
-  8b/copy                         1/mod/*+disp8   4/rm32/sib    4/base/ESP  4/index/none  .           3/r32/EBX   0x8/disp8       .                 # copy *(ESP+8) to EBX
+  8b/copy                         1/mod/*+disp8   4/rm32/sib    5/base/EBP  4/index/none  .           0/r32/EAX   0x8/disp8       .                 # copy *(EBP+8) to EAX
+  8b/copy                         1/mod/*+disp8   4/rm32/sib    5/base/EBP  4/index/none  .           3/r32/EBX   0xc/disp8       .                 # copy *(EBP+12) to EBX
   # if EAX == b/EBX
   39/compare                      3/mod/direct    0/rm32/EAX    .           .             .           3/r32/EBX   .               .                 # compare EAX and EBX
   75/jump-if-unequal  $check_ints_equal:else/disp8
@@ -120,11 +126,11 @@ check_ints_equal:  # (a : int, b : int, msg : (address array byte)) -> boolean
       # discard arg
   81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add 4 to ESP
     # return
-  c3/return
+  eb/jump  $check_ints_equal:end/disp8
   # else:
 $check_ints_equal:else:
   # copy msg into ECX
-  8b/copy                         1/mod/*+disp8   4/rm32/sib    4/base/ESP  4/index/none  .           1/r32/ECX   0xc/disp8       .                 # copy *(ESP+12) to ECX
+  8b/copy                         1/mod/*+disp8   4/rm32/sib    5/base/EBP  4/index/none  .           1/r32/ECX   0x10/disp8       .                # copy *(EBP+16) to ECX
     # print(ECX)
       # push args
   51/push-ECX
@@ -139,12 +145,28 @@ $check_ints_equal:else:
   e8/call  write_stderr/disp32
       # discard arg
   81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add 4 to ESP
+$check_ints_equal:end:
+  # restore registers
+  5b/pop-to-EBX
+  59/pop-to-ECX
   # end
+  89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
+  5d/pop-to-EBP
   c3/return
 
 # compare a null-terminated ascii string with a more idiomatic length-prefixed byte array
 # reason for the name: the only place we should have null-terminated ascii strings is from commandline args
 argv_equal:  # s : null-terminated ascii string, benchmark : length-prefixed ascii string -> EAX : boolean
+  # prolog
+  55/push-EBP
+  89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+  # save registers
+  51/push-ECX
+  52/push-EDX
+  53/push-EBX
+  56/push-ESI
+  57/push-EDI
+
   # pseudocode:
   #   initialize n = b.length
   #   initialize s1 = s
@@ -160,12 +182,12 @@ argv_equal:  # s : null-terminated ascii string, benchmark : length-prefixed asc
   #   return *s1 == 0
 # {{{
   # initialize s into EDI
-  8b/copy                         1/mod/*+disp8   4/rm32/sib    4/base/ESP  4/index/none  .           7/r32/EDI   4/disp8         .                 # copy *(ESP+4) to EDI
+  8b/copy                         1/mod/*+disp8   4/rm32/sib    5/base/EBP  4/index/none  .           7/r32/EDI   8/disp8         .                 # copy *(EBP+8) to EDI
   # initialize benchmark length n into EDX
-  8b/copy                         1/mod/*+disp8   4/rm32/sib    4/base/ESP  4/index/none  .           2/r32/EDX   8/disp8         .                 # copy *(ESP+8) to EDX
+  8b/copy                         1/mod/*+disp8   4/rm32/sib    5/base/EBP  4/index/none  .           2/r32/EDX   0xc/disp8       .                 # copy *(EBP+12) to EDX
   8b/copy                         0/mod/indirect  2/rm32/EDX    .           .             .           2/r32/EDX   .               .                 # copy *EDX to EDX
   # initialize benchmark data into ESI
-  8b/copy                         1/mod/*+disp8   4/rm32/sib    4/base/ESP  4/index/none  .           6/r32/ESI   8/disp8         .                 # copy *(ESP+8) to ESI
+  8b/copy                         1/mod/*+disp8   4/rm32/sib    5/base/EBP  4/index/none  .           6/r32/ESI   0xc/disp8       .                 # copy *(EBP+12) to ESI
   81          0/subop/add         3/mod/direct    6/rm32/ESI    .           .             .           .           .               4/imm32           # add 4 to ESI
   # initialize loop counter i into ECX
   b9/copy                         .               .             .           .             .           .           .               0/imm32/exit      # copy 1 to ECX
@@ -197,10 +219,21 @@ $argv_break:
   81          7/subop/compare     3/mod/direct    0/rm32/EAX    .           .             .           .           .               0/imm32           # compare EAX with 0
   75/jump-if-not-equal  $argv_fail/disp8
   b8/copy                         .               .             .           .             .           .           .               1/imm32           # copy 1 to EAX
-  c3/return
+  eb/jump  $argv_end/disp8
   # return false
 $argv_fail:
   b8/copy                         .               .             .           .             .           .           .               0/imm32           # copy 0 to EAX
+
+$argv_end:
+  # restore registers
+  5f/pop-to-EDI
+  5e/pop-to-ESI
+  5b/pop-to-EBX
+  5a/pop-to-EDX
+  59/pop-to-ECX
+  # end
+  89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
+  5d/pop-to-EBP
   c3/return
 # }}}
 # tests for argv_equal {{{
diff --git a/subx/examples/ex11 b/subx/examples/ex11
index 646c2eb7..d68fd5ad 100644
--- a/subx/examples/ex11
+++ b/subx/examples/ex11
Binary files differdiff --git a/subx/examples/ex11.subx b/subx/examples/ex11.subx
index 86b7e8b4..8c2c9625 100644
--- a/subx/examples/ex11.subx
+++ b/subx/examples/ex11.subx
@@ -29,6 +29,16 @@
 # compare a null-terminated ascii string with a more idiomatic length-prefixed byte array
 # reason for the name: the only place we should have null-terminated ascii strings is from commandline args
 argv_equal:  # s : null-terminated ascii string, benchmark : length-prefixed ascii string -> EAX : boolean
+  # prolog
+  55/push-EBP
+  89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+  # save registers
+  51/push-ECX
+  52/push-EDX
+  53/push-EBX
+  56/push-ESI
+  57/push-EDI
+
   # pseudocode:
   #   initialize n = b.length
   #   initialize s1 = s
@@ -42,14 +52,13 @@ argv_equal:  # s : null-terminated ascii string, benchmark : length-prefixed asc
   #     if c1 != c2
   #       return false
   #   return *s1 == 0
-
   # initialize s into EDI
-  8b/copy                         1/mod/*+disp8   4/rm32/sib    4/base/ESP  4/index/none  .           7/r32/EDI   4/disp8         .                 # copy *(ESP+4) to EDI
+  8b/copy                         1/mod/*+disp8   4/rm32/sib    5/base/EBP  4/index/none  .           7/r32/EDI   8/disp8         .                 # copy *(EBP+8) to EDI
   # initialize benchmark length n into EDX
-  8b/copy                         1/mod/*+disp8   4/rm32/sib    4/base/ESP  4/index/none  .           2/r32/EDX   8/disp8         .                 # copy *(ESP+8) to EDX
+  8b/copy                         1/mod/*+disp8   4/rm32/sib    5/base/EBP  4/index/none  .           2/r32/EDX   0xc/disp8       .                 # copy *(EBP+12) to EDX
   8b/copy                         0/mod/indirect  2/rm32/EDX    .           .             .           2/r32/EDX   .               .                 # copy *EDX to EDX
   # initialize benchmark data into ESI
-  8b/copy                         1/mod/*+disp8   4/rm32/sib    4/base/ESP  4/index/none  .           6/r32/ESI   8/disp8         .                 # copy *(ESP+8) to ESI
+  8b/copy                         1/mod/*+disp8   4/rm32/sib    5/base/EBP  4/index/none  .           6/r32/ESI   0xc/disp8       .                 # copy *(EBP+12) to ESI
   81          0/subop/add         3/mod/direct    6/rm32/ESI    .           .             .           .           .               4/imm32           # add 4 to ESI
   # initialize loop counter i into ECX
   b9/copy                         .               .             .           .             .           .           .               0/imm32/exit      # copy 1 to ECX
@@ -81,10 +90,21 @@ $argv_break:
   81          7/subop/compare     3/mod/direct    0/rm32/EAX    .           .             .           .           .               0/imm32           # compare EAX with 0
   75/jump-if-not-equal  $argv_fail/disp8
   b8/copy                         .               .             .           .             .           .           .               1/imm32           # copy 1 to EAX
-  c3/return
+  eb/jump  $argv_end/disp8
   # return false
 $argv_fail:
   b8/copy                         .               .             .           .             .           .           .               0/imm32           # copy 0 to EAX
+
+$argv_end:
+  # restore registers
+  5f/pop-to-EDI
+  5e/pop-to-ESI
+  5b/pop-to-EBX
+  5a/pop-to-EDX
+  59/pop-to-ECX
+  # end
+  89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
+  5d/pop-to-EBP
   c3/return
 
 ## tests
@@ -233,9 +253,15 @@ test_compare_argv_with_longer_array:
 
 # print msg to stderr if a != b, otherwise print "."
 check_ints_equal:  # (a : int, b : int, msg : (address array byte)) -> boolean
+  # prolog
+  55/push-EBP
+  89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+  # save registers
+  51/push-ECX
+  53/push-EBX
   # load args into EAX, EBX and ECX
-  8b/copy                         1/mod/*+disp8   4/rm32/sib    4/base/ESP  4/index/none  .           0/r32/EAX   0x4/disp8       .                 # copy *(ESP+4) to EAX
-  8b/copy                         1/mod/*+disp8   4/rm32/sib    4/base/ESP  4/index/none  .           3/r32/EBX   0x8/disp8       .                 # copy *(ESP+8) to EBX
+  8b/copy                         1/mod/*+disp8   4/rm32/sib    5/base/EBP  4/index/none  .           0/r32/EAX   0x8/disp8       .                 # copy *(EBP+8) to EAX
+  8b/copy                         1/mod/*+disp8   4/rm32/sib    5/base/EBP  4/index/none  .           3/r32/EBX   0xc/disp8       .                 # copy *(EBP+12) to EBX
   # if EAX == b/EBX
   39/compare                      3/mod/direct    0/rm32/EAX    .           .             .           3/r32/EBX   .               .                 # compare EAX and EBX
   75/jump-if-unequal  $check_ints_equal:else/disp8
@@ -247,11 +273,11 @@ check_ints_equal:  # (a : int, b : int, msg : (address array byte)) -> boolean
       # discard arg
   81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add 4 to ESP
     # return
-  c3/return
+  eb/jump  $check_ints_equal:end/disp8
   # else:
 $check_ints_equal:else:
   # copy msg into ECX
-  8b/copy                         1/mod/*+disp8   4/rm32/sib    4/base/ESP  4/index/none  .           1/r32/ECX   0xc/disp8       .                 # copy *(ESP+12) to ECX
+  8b/copy                         1/mod/*+disp8   4/rm32/sib    5/base/EBP  4/index/none  .           1/r32/ECX   0x10/disp8       .                # copy *(EBP+16) to ECX
     # print(ECX)
       # push args
   51/push-ECX
@@ -266,7 +292,13 @@ $check_ints_equal:else:
   e8/call  write_stderr/disp32
       # discard arg
   81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add 4 to ESP
+$check_ints_equal:end:
+  # restore registers
+  5b/pop-to-EBX
+  59/pop-to-ECX
   # end
+  89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
+  5d/pop-to-EBP
   c3/return
 
 write_stderr:  # s : (address array byte) -> <void>