From 6e1eeeebfb453fa7c871869c19375ce60fbd7413 Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Sat, 27 Jul 2019 16:01:55 -0700 Subject: 5485 - promote SubX to top-level --- html/054string-equal.subx.html | 296 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 296 insertions(+) create mode 100644 html/054string-equal.subx.html (limited to 'html/054string-equal.subx.html') diff --git a/html/054string-equal.subx.html b/html/054string-equal.subx.html new file mode 100644 index 00000000..2d315db5 --- /dev/null +++ b/html/054string-equal.subx.html @@ -0,0 +1,296 @@ + + + + +Mu - subx/054string-equal.subx + + + + + + + + + + +https://github.com/akkartik/mu/blob/master/subx/054string-equal.subx +
+  1 # Comparing 'regular' length-prefixed strings.
+  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:  # run all tests
+  9 #?     e8/call test-compare-equal-strings/disp32
+ 10     e8/call  run-tests/disp32  # 'run-tests' is a function created automatically by SubX. It calls all functions that start with 'test-'.
+ 11     # syscall(exit, Num-test-failures)
+ 12     8b/copy                         0/mod/indirect  5/rm32/.disp32            .             .           3/r32/EBX   Num-test-failures/disp32          # copy *Num-test-failures to EBX
+ 13     b8/copy-to-EAX  1/imm32/exit
+ 14     cd/syscall  0x80/imm8
+ 15 
+ 16 string-equal?:  # s : (address string), benchmark : (address string) -> EAX : boolean
+ 17     # pseudocode:
+ 18     #   if (s->length != benchmark->length) return false
+ 19     #   currs = s->data
+ 20     #   currb = benchmark->data
+ 21     #   maxs = s->data + s->length
+ 22     #   while currs < maxs
+ 23     #     c1 = *currs
+ 24     #     c2 = *currb
+ 25     #     if (c1 != c2) return false
+ 26     #     ++currs, ++currb
+ 27     #   return true
+ 28     #
+ 29     # registers:
+ 30     #   currs: ESI
+ 31     #   maxs: ECX
+ 32     #   currb: EDI
+ 33     #   c1: EAX
+ 34     #   c2: EBX
+ 35     #
+ 36     # . prolog
+ 37     55/push-EBP
+ 38     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+ 39     # . save registers
+ 40     51/push-ECX
+ 41     52/push-EDX
+ 42     56/push-ESI
+ 43     57/push-EDI
+ 44     # ESI = s
+ 45     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           6/r32/ESI   8/disp8         .                 # copy *(EBP+8) to ESI
+ 46     # EDI = benchmark
+ 47     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           7/r32/EDI   0xc/disp8       .                 # copy *(EBP+12) to EDI
+ 48     # ECX = s->length
+ 49     8b/copy                         0/mod/indirect  6/rm32/ESI    .           .             .           1/r32/ECX   .               .                 # copy *ESI to ECX
+ 50 $string-equal?:lengths:
+ 51     # if (ECX != benchmark->length) return false
+ 52     39/compare                      0/mod/indirect  7/rm32/EDI    .           .             .           1/r32/ECX   .               .                 # compare *EDI and ECX
+ 53     75/jump-if-not-equal  $string-equal?:false/disp8
+ 54     # currs/ESI = s->data
+ 55     81          0/subop/add         3/mod/direct    6/rm32/ESI    .           .             .           .           .               4/imm32           # add to ESI
+ 56     # maxs/ECX = s->data + s->length
+ 57     01/add                          3/mod/direct    1/rm32/ECX    .           .             .           6/r32/ESI   .               .                 # add ESI to ECX
+ 58     # currb/EDI = benchmark->data
+ 59     81          0/subop/add         3/mod/direct    7/rm32/EDI    .           .             .           .           .               4/imm32           # add to EDI
+ 60     # c1/EAX = c2/EDX = 0
+ 61     31/xor                          3/mod/direct    0/rm32/EAX    .           .             .           0/r32/EAX   .               .                 # clear EAX
+ 62     31/xor                          3/mod/direct    2/rm32/EDX    .           .             .           2/r32/EDX   .               .                 # clear EDX
+ 63 $string-equal?:loop:
+ 64     # if (currs >= maxs) return true
+ 65     39/compare                      3/mod/direct    6/rm32/ESI    .           .             .           1/r32/ECX   .               .                 # compare ESI with ECX
+ 66     73/jump-if-greater-or-equal-unsigned  $string-equal?:true/disp8
+ 67     # c1 = *currs
+ 68     8a/copy-byte                    0/mod/indirect  6/rm32/ESI    .           .             .           0/r32/AL    .               .                 # copy byte at *ESI to AL
+ 69     # c2 = *currb
+ 70     8a/copy-byte                    0/mod/indirect  7/rm32/EDI    .           .             .           2/r32/DL    .               .                 # copy byte at *EDI to DL
+ 71     # if (c1 != c2) return false
+ 72     39/compare                      3/mod/direct    0/rm32/EAX    .           .             .           2/r32/EDX   .               .                 # compare EAX and EDX
+ 73     75/jump-if-not-equal  $string-equal?:false/disp8
+ 74     # ++currs
+ 75     46/increment-ESI
+ 76     # ++currb
+ 77     47/increment-EDI
+ 78     eb/jump  $string-equal?:loop/disp8
+ 79 $string-equal?:true:
+ 80     b8/copy-to-EAX  1/imm32
+ 81     eb/jump  $string-equal?:end/disp8
+ 82 $string-equal?:false:
+ 83     b8/copy-to-EAX  0/imm32
+ 84 $string-equal?:end:
+ 85     # . restore registers
+ 86     5f/pop-to-EDI
+ 87     5e/pop-to-ESI
+ 88     5a/pop-to-EDX
+ 89     59/pop-to-ECX
+ 90     # . epilog
+ 91     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
+ 92     5d/pop-to-EBP
+ 93     c3/return
+ 94 
+ 95 # - tests
+ 96 
+ 97 test-compare-empty-with-empty-string:
+ 98     # EAX = string-equal?("", "")
+ 99     # . . push args
+100     68/push  ""/imm32
+101     68/push  ""/imm32
+102     # . . call
+103     e8/call  string-equal?/disp32
+104     # . . discard args
+105     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+106     # check-ints-equal(EAX, 1, msg)
+107     # . . push args
+108     68/push  "F - test-compare-empty-with-empty-string"/imm32
+109     68/push  1/imm32/true
+110     50/push-EAX
+111     # . . call
+112     e8/call  check-ints-equal/disp32
+113     # . . discard args
+114     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+115     c3/return
+116 
+117 test-compare-empty-with-non-empty-string:  # also checks length-mismatch code path
+118     # EAX = string-equal?("", "Abc")
+119     # . . push args
+120     68/push  "Abc"/imm32
+121     68/push  ""/imm32
+122     # . . call
+123     e8/call  string-equal?/disp32
+124     # . . discard args
+125     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+126     # check-ints-equal(EAX, 0, msg)
+127     # . . push args
+128     68/push  "F - test-compare-empty-with-non-empty-string"/imm32
+129     68/push  0/imm32/false
+130     50/push-EAX
+131     # . . call
+132     e8/call  check-ints-equal/disp32
+133     # . . discard args
+134     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+135     c3/return
+136 
+137 test-compare-equal-strings:
+138     # EAX = string-equal?("Abc", "Abc")
+139     # . . push args
+140     68/push  "Abc"/imm32
+141     68/push  "Abc"/imm32
+142     # . . call
+143     e8/call  string-equal?/disp32
+144     # . . discard args
+145     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+146     # check-ints-equal(EAX, 1, msg)
+147     # . . push args
+148     68/push  "F - test-compare-equal-strings"/imm32
+149     68/push  1/imm32/true
+150     50/push-EAX
+151     # . . call
+152     e8/call  check-ints-equal/disp32
+153     # . . discard args
+154     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+155     c3/return
+156 
+157 test-compare-inequal-strings-equal-lengths:
+158     # EAX = string-equal?("Abc", "Adc")
+159     # . . push args
+160     68/push  "Adc"/imm32
+161     68/push  "Abc"/imm32
+162     # . . call
+163     e8/call  string-equal?/disp32
+164     # . . discard args
+165     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+166     # check-ints-equal(EAX, 0, msg)
+167     # . . push args
+168     68/push  "F - test-compare-inequal-strings-equal-lengths"/imm32
+169     68/push  0/imm32/false
+170     50/push-EAX
+171     # . . call
+172     e8/call  check-ints-equal/disp32
+173     # . . discard args
+174     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+175     c3/return
+176 
+177 # helper for later tests
+178 check-string-equal:  # s : (address string), expected : (address string), msg : (address string)
+179     # . prolog
+180     55/push-EBP
+181     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+182     # . save registers
+183     50/push-EAX
+184     # EAX = string-equal?(s, expected)
+185     # . . push args
+186     ff          6/subop/push        1/mod/*+disp8   5/rm32/EBP    .           .             .           .           0xc/disp8       .                 # push *(EBP+12)
+187     ff          6/subop/push        1/mod/*+disp8   5/rm32/EBP    .           .             .           .           8/disp8         .                 # push *(EBP+8)
+188     # . . call
+189     e8/call  string-equal?/disp32
+190     # . . discard args
+191     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+192     # check-ints-equal(EAX, 1, msg)
+193     # . . push args
+194     ff          6/subop/push        1/mod/*+disp8   5/rm32/EBP    .           .             .           .           0x10/disp8      .                 # push *(EBP+16)
+195     68/push  1/imm32
+196     50/push-EAX
+197     # . . call
+198     e8/call  check-ints-equal/disp32
+199     # . . discard args
+200     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+201 $check-string-equal:end:
+202     # . restore registers
+203     58/pop-to-EAX
+204     # . epilog
+205     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
+206     5d/pop-to-EBP
+207     c3/return
+208 
+209 # test the helper
+210 test-check-string-equal:
+211     # check-string-equal?("Abc", "Abc")
+212     # . . push args
+213     68/push  "Abc"/imm32
+214     68/push  "Abc"/imm32
+215     # . . call
+216     e8/call  check-string-equal/disp32
+217     # . . discard args
+218     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+219     # check-ints-equal(EAX, 1, msg)
+220     # . . push args
+221     68/push  "F - test-check-string-equal"/imm32
+222     68/push  0/imm32/false
+223     50/push-EAX
+224     # . . call
+225     e8/call  check-ints-equal/disp32
+226     # . . discard args
+227     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+228     c3/return
+229 
+230 # . . vim:nowrap:textwidth=0
+
+ + + -- cgit 1.4.1-2-gfad0