From 3350c34a74844e21ea69077e01efff3bae64bdcd Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Tue, 23 Mar 2021 17:31:08 -0700 Subject: . --- html/linux/105string-equal.subx.html | 329 +++++++++++++++++++++++++++++++++++ 1 file changed, 329 insertions(+) create mode 100644 html/linux/105string-equal.subx.html (limited to 'html/linux/105string-equal.subx.html') diff --git a/html/linux/105string-equal.subx.html b/html/linux/105string-equal.subx.html new file mode 100644 index 00000000..1a41c469 --- /dev/null +++ b/html/linux/105string-equal.subx.html @@ -0,0 +1,329 @@ + + + + +Mu - linux/105string-equal.subx + + + + + + + + + + +https://github.com/akkartik/mu/blob/main/linux/105string-equal.subx +
+  1 # Comparing 'regular' size-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     e8/call  syscall_exit/disp32
+ 14 
+ 15 string-equal?:  # s: (addr array byte), benchmark: (addr array byte) -> result/eax: boolean
+ 16     # pseudocode:
+ 17     #   if (s->size != benchmark->size) return false
+ 18     #   return string-starts-with?(s, benchmark)
+ 19     #
+ 20     # . prologue
+ 21     55/push-ebp
+ 22     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
+ 23     # . save registers
+ 24     51/push-ecx
+ 25     56/push-esi
+ 26     57/push-edi
+ 27     # esi = s
+ 28     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           6/r32/esi   8/disp8         .                 # copy *(ebp+8) to esi
+ 29     # edi = benchmark
+ 30     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           7/r32/edi   0xc/disp8       .                 # copy *(ebp+12) to edi
+ 31     # ecx = s->size
+ 32     8b/copy                         0/mod/indirect  6/rm32/esi    .           .             .           1/r32/ecx   .               .                 # copy *esi to ecx
+ 33 $string-equal?:sizes:
+ 34     # if (ecx != benchmark->size) return false
+ 35     39/compare                      0/mod/indirect  7/rm32/edi    .           .             .           1/r32/ecx   .               .                 # compare *edi and ecx
+ 36     b8/copy-to-eax  0/imm32/false
+ 37     75/jump-if-!=  $string-equal?:end/disp8
+ 38 $string-equal?:contents:
+ 39     # string-starts-with?(s, benchmark)
+ 40     # . . push args
+ 41     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0xc/disp8       .                 # push *(ebp+12)
+ 42     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           8/disp8         .                 # push *(ebp+8)
+ 43     # . . call
+ 44     e8/call  string-starts-with?/disp32
+ 45     # . . discard args
+ 46     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+ 47 $string-equal?:end:
+ 48     # . restore registers
+ 49     5f/pop-to-edi
+ 50     5e/pop-to-esi
+ 51     59/pop-to-ecx
+ 52     # . epilogue
+ 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 string-starts-with?:  # s: (addr array byte), benchmark: (addr array byte) -> result/eax: boolean
+ 58     # pseudocode:
+ 59     #   if (s->size < benchmark->size) return false
+ 60     #   currs = s->data
+ 61     #   currb = benchmark->data
+ 62     #   maxb = &benchmark->data[benchmark->size]
+ 63     #   while currb < maxb
+ 64     #     c1 = *currs
+ 65     #     c2 = *currb
+ 66     #     if (c1 != c2) return false
+ 67     #     ++currs, ++currb
+ 68     #   return true
+ 69     #
+ 70     # registers:
+ 71     #   currs: esi
+ 72     #   maxs: ecx
+ 73     #   currb: edi
+ 74     #   c1: eax
+ 75     #   c2: ebx
+ 76     #
+ 77     # . prologue
+ 78     55/push-ebp
+ 79     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
+ 80     # . save registers
+ 81     51/push-ecx
+ 82     52/push-edx
+ 83     56/push-esi
+ 84     57/push-edi
+ 85     # esi = s
+ 86     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           6/r32/esi   8/disp8         .                 # copy *(ebp+8) to esi
+ 87     # edi = benchmark
+ 88     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           7/r32/edi   0xc/disp8       .                 # copy *(ebp+12) to edi
+ 89     # var bsize/ecx: int = benchmark->size
+ 90     8b/copy                         0/mod/indirect  7/rm32/edi    .           .             .           1/r32/ecx   .               .                 # copy *edi to ecx
+ 91 $string-starts-with?:sizes:
+ 92     # if (s->size < bsize) return false
+ 93     39/compare                      0/mod/indirect  6/rm32/esi    .           .             .           1/r32/ecx   .               .                 # compare *esi with ecx
+ 94     7c/jump-if-<  $string-starts-with?:false/disp8
+ 95     # var currs/esi: (addr byte) = s->data
+ 96     81          0/subop/add         3/mod/direct    6/rm32/esi    .           .             .           .           .               4/imm32           # add to esi
+ 97     # var currb/edi: (addr byte) = benchmark->data
+ 98     81          0/subop/add         3/mod/direct    7/rm32/edi    .           .             .           .           .               4/imm32           # add to edi
+ 99     # var maxb/ecx: (addr byte) = &benchmark->data[benchmark->size]
+100     01/add                          3/mod/direct    1/rm32/ecx    .           .             .           7/r32/edi   .               .                 # add edi to ecx
+101     # var c1/eax: byte = 0
+102     31/xor                          3/mod/direct    0/rm32/eax    .           .             .           0/r32/eax   .               .                 # clear eax
+103     # var c2/edx: byte = 0
+104     31/xor                          3/mod/direct    2/rm32/edx    .           .             .           2/r32/edx   .               .                 # clear edx
+105 $string-starts-with?:loop:
+106     # if (currs >= maxs) return true
+107     39/compare                      3/mod/direct    7/rm32/edi    .           .             .           1/r32/ecx   .               .                 # compare edi with ecx
+108     73/jump-if-addr>=  $string-starts-with?:true/disp8
+109     # c1 = *currs
+110     8a/copy-byte                    0/mod/indirect  6/rm32/esi    .           .             .           0/r32/AL    .               .                 # copy byte at *esi to AL
+111     # c2 = *currb
+112     8a/copy-byte                    0/mod/indirect  7/rm32/edi    .           .             .           2/r32/DL    .               .                 # copy byte at *edi to DL
+113     # if (c1 != c2) return false
+114     39/compare                      3/mod/direct    0/rm32/eax    .           .             .           2/r32/edx   .               .                 # compare eax and edx
+115     75/jump-if-!=  $string-starts-with?:false/disp8
+116     # ++currs
+117     46/increment-esi
+118     # ++currb
+119     47/increment-edi
+120     eb/jump  $string-starts-with?:loop/disp8
+121 $string-starts-with?:true:
+122     b8/copy-to-eax  1/imm32
+123     eb/jump  $string-starts-with?:end/disp8
+124 $string-starts-with?:false:
+125     b8/copy-to-eax  0/imm32
+126 $string-starts-with?:end:
+127     # . restore registers
+128     5f/pop-to-edi
+129     5e/pop-to-esi
+130     5a/pop-to-edx
+131     59/pop-to-ecx
+132     # . epilogue
+133     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
+134     5d/pop-to-ebp
+135     c3/return
+136 
+137 # - tests
+138 
+139 test-compare-empty-with-empty-string:
+140     # eax = string-equal?("", "")
+141     # . . push args
+142     68/push  ""/imm32
+143     68/push  ""/imm32
+144     # . . call
+145     e8/call  string-equal?/disp32
+146     # . . discard args
+147     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+148     # check-ints-equal(eax, 1, msg)
+149     # . . push args
+150     68/push  "F - test-compare-empty-with-empty-string"/imm32
+151     68/push  1/imm32/true
+152     50/push-eax
+153     # . . call
+154     e8/call  check-ints-equal/disp32
+155     # . . discard args
+156     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
+157     c3/return
+158 
+159 test-compare-empty-with-non-empty-string:  # also checks size-mismatch code path
+160     # eax = string-equal?("", "Abc")
+161     # . . push args
+162     68/push  "Abc"/imm32
+163     68/push  ""/imm32
+164     # . . call
+165     e8/call  string-equal?/disp32
+166     # . . discard args
+167     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+168     # check-ints-equal(eax, 0, msg)
+169     # . . push args
+170     68/push  "F - test-compare-empty-with-non-empty-string"/imm32
+171     68/push  0/imm32/false
+172     50/push-eax
+173     # . . call
+174     e8/call  check-ints-equal/disp32
+175     # . . discard args
+176     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
+177     c3/return
+178 
+179 test-compare-equal-strings:
+180     # eax = string-equal?("Abc", "Abc")
+181     # . . push args
+182     68/push  "Abc"/imm32
+183     68/push  "Abc"/imm32
+184     # . . call
+185     e8/call  string-equal?/disp32
+186     # . . discard args
+187     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+188     # check-ints-equal(eax, 1, msg)
+189     # . . push args
+190     68/push  "F - test-compare-equal-strings"/imm32
+191     68/push  1/imm32/true
+192     50/push-eax
+193     # . . call
+194     e8/call  check-ints-equal/disp32
+195     # . . discard args
+196     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
+197     c3/return
+198 
+199 test-compare-inequal-strings-equal-sizes:
+200     # eax = string-equal?("Abc", "Adc")
+201     # . . push args
+202     68/push  "Adc"/imm32
+203     68/push  "Abc"/imm32
+204     # . . call
+205     e8/call  string-equal?/disp32
+206     # . . discard args
+207     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+208     # check-ints-equal(eax, 0, msg)
+209     # . . push args
+210     68/push  "F - test-compare-inequal-strings-equal-sizes"/imm32
+211     68/push  0/imm32/false
+212     50/push-eax
+213     # . . call
+214     e8/call  check-ints-equal/disp32
+215     # . . discard args
+216     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
+217     c3/return
+218 
+219 # helper for later tests
+220 check-strings-equal:  # s: (addr array byte), expected: (addr array byte), msg: (addr array byte)
+221     # . prologue
+222     55/push-ebp
+223     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
+224     # . save registers
+225     50/push-eax
+226     # var eax: boolean = string-equal?(s, expected)
+227     # . . push args
+228     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0xc/disp8       .                 # push *(ebp+12)
+229     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           8/disp8         .                 # push *(ebp+8)
+230     # . . call
+231     e8/call  string-equal?/disp32
+232     # . . discard args
+233     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+234     # check-ints-equal(eax, 1, msg)
+235     # . . push args
+236     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0x10/disp8      .                 # push *(ebp+16)
+237     68/push  1/imm32
+238     50/push-eax
+239     # . . call
+240     e8/call  check-ints-equal/disp32
+241     # . . discard args
+242     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
+243 $check-strings-equal:end:
+244     # . restore registers
+245     58/pop-to-eax
+246     # . epilogue
+247     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
+248     5d/pop-to-ebp
+249     c3/return
+250 
+251 # test the helper
+252 test-check-strings-equal:
+253     # check-strings-equal("Abc", "Abc")
+254     # . . push args
+255     68/push  "Abc"/imm32
+256     68/push  "Abc"/imm32
+257     # . . call
+258     e8/call  check-strings-equal/disp32
+259     # . . discard args
+260     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+261     c3/return
+262 
+263 # . . vim:nowrap:textwidth=0
+
+ + + -- cgit 1.4.1-2-gfad0