From 8fa32599bb288f9e51ebcf6f7c00339692c2a5b5 Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Tue, 14 Jan 2020 01:24:54 -0800 Subject: 5889 --- html/100array-equal.subx.html | 663 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 663 insertions(+) create mode 100644 html/100array-equal.subx.html (limited to 'html/100array-equal.subx.html') diff --git a/html/100array-equal.subx.html b/html/100array-equal.subx.html new file mode 100644 index 00000000..89c48e6b --- /dev/null +++ b/html/100array-equal.subx.html @@ -0,0 +1,663 @@ + + + + +Mu - 100array-equal.subx + + + + + + + + + + +https://github.com/akkartik/mu/blob/master/100array-equal.subx +
+  1 # Comparing arrays of numbers.
+  2 
+  3 == code
+  4 
+  5 array-equal?:  # a : (addr array int), b : (addr array int) -> eax : boolean
+  6     # pseudocode:
+  7     #   lena = a->length
+  8     #   if (lena != b->length) return false
+  9     #   i = 0
+ 10     #   curra = a->data
+ 11     #   currb = b->data
+ 12     #   while i < lena
+ 13     #     i1 = *curra
+ 14     #     i2 = *currb
+ 15     #     if (c1 != c2) return false
+ 16     #     i+=4, curra+=4, currb+=4
+ 17     #   return true
+ 18     #
+ 19     # registers:
+ 20     #   i: ecx
+ 21     #   lena: edx
+ 22     #   curra: esi
+ 23     #   currb: edi
+ 24     #   i1: eax
+ 25     #   i2: ebx
+ 26     #
+ 27     # . prologue
+ 28     55/push-ebp
+ 29     89/<- %ebp 4/r32/esp
+ 30     # . save registers
+ 31     51/push-ecx
+ 32     52/push-edx
+ 33     53/push-ebx
+ 34     56/push-esi
+ 35     57/push-edi
+ 36     # esi = a
+ 37     8b/-> *(ebp+8) 6/r32/esi
+ 38     # edi = b
+ 39     8b/-> *(ebp+0xc) 7/r32/edi
+ 40     # var lena/edx : int = a->length
+ 41     8b/-> *esi 2/r32/edx
+ 42 $array-equal?:lengths:
+ 43     # if (lena != b->length) return false
+ 44     39/compare *edi 2/r32/edx
+ 45     75/jump-if-not-equal $array-equal?:false/disp8
+ 46     # var curra/esi : (addr byte) = a->data
+ 47     81 0/subop/add %esi 4/imm32
+ 48     # var currb/edi : (addr byte) = b->data
+ 49     81 0/subop/add %edi 4/imm32
+ 50     # var i/ecx : int = 0
+ 51     31/xor %ecx 1/r32/ecx
+ 52     # var vala/eax : int
+ 53     # var valb/ebx : int
+ 54 $array-equal?:loop:
+ 55     # if (i >= lena) return true
+ 56     39/compare %ecx 2/r32/edx
+ 57     7d/jump-if-greater-or-equal $array-equal?:true/disp8
+ 58     # var vala/eax : int = *curra
+ 59     8b/-> *esi 0/r32/eax
+ 60     # var valb/ebx : int = *currb
+ 61     8b/-> *edi 3/r32/ebx
+ 62     # if (vala != valb) return false
+ 63     39/compare %eax 3/r32/ebx
+ 64     75/jump-if-not-equal $array-equal?:false/disp8
+ 65     # i += 4
+ 66     81 0/subop/add %ecx 4/imm32
+ 67     # currs += 4
+ 68     81 0/subop/add %esi 4/imm32
+ 69     # currb += 4
+ 70     81 0/subop/add %edi 4/imm32
+ 71     eb/jump $array-equal?:loop/disp8
+ 72 $array-equal?:true:
+ 73     b8/copy-to-eax 1/imm32
+ 74     eb/jump $array-equal?:end/disp8
+ 75 $array-equal?:false:
+ 76     b8/copy-to-eax 0/imm32
+ 77 $array-equal?:end:
+ 78     # . restore registers
+ 79     5f/pop-to-edi
+ 80     5e/pop-to-esi
+ 81     5b/pop-to-ebx
+ 82     5a/pop-to-edx
+ 83     59/pop-to-ecx
+ 84     # . epilogue
+ 85     89/<- %esp 5/r32/ebp
+ 86     5d/pop-to-ebp
+ 87     c3/return
+ 88 
+ 89 test-compare-empty-with-empty-array:
+ 90     # . prologue
+ 91     55/push-ebp
+ 92     89/<- %ebp 4/r32/esp
+ 93     # var ecx : (array _) = []
+ 94     68/push 0/imm32/size
+ 95     89/<- %ecx 4/r32/esp
+ 96     # var edx : (array _) = []
+ 97     68/push 0/imm32/size
+ 98     89/<- %edx 4/r32/esp
+ 99     # eax = array-equal?(ecx, edx)
+100     # . . push args
+101     52/push-edx
+102     51/push-ecx
+103     # . . call
+104     e8/call array-equal?/disp32
+105     # . . discard args
+106     81 0/subop/add %esp 8/imm32
+107     # check-ints-equal(eax, 1, msg)
+108     # . . push args
+109     68/push "F - test-compare-empty-with-empty-array"/imm32
+110     68/push 1/imm32/true
+111     50/push-eax
+112     # . . call
+113     e8/call check-ints-equal/disp32
+114     # . . discard args
+115     81 0/subop/add %esp 0xc/imm32
+116     # . epilogue
+117     89/<- %esp 5/r32/ebp
+118     5d/pop-to-ebp
+119     c3/return
+120 
+121 test-compare-empty-with-non-empty-array:  # also checks length-mismatch code path
+122     # . prologue
+123     55/push-ebp
+124     89/<- %ebp 4/r32/esp
+125     # var ecx : (array int) = [1]
+126     68/push 1/imm32
+127     68/push 4/imm32/size
+128     89/<- %ecx 4/r32/esp
+129     # var edx : (array int) = []
+130     68/push 0/imm32/size
+131     89/<- %edx 4/r32/esp
+132     # eax = array-equal?(ecx, edx)
+133     # . . push args
+134     52/push-edx
+135     51/push-ecx
+136     # . . call
+137     e8/call array-equal?/disp32
+138     # . . discard args
+139     81 0/subop/add %esp 8/imm32
+140     # check-ints-equal(eax, 0, msg)
+141     # . . push args
+142     68/push "F - test-compare-empty-with-non-empty-array"/imm32
+143     68/push 0/imm32/false
+144     50/push-eax
+145     # . . call
+146     e8/call check-ints-equal/disp32
+147     # . . discard args
+148     81 0/subop/add %esp 0xc/imm32
+149     # . epilogue
+150     89/<- %esp 5/r32/ebp
+151     5d/pop-to-ebp
+152     c3/return
+153 
+154 test-compare-equal-arrays:
+155     # . prologue
+156     55/push-ebp
+157     89/<- %ebp 4/r32/esp
+158     # var ecx : (array int) = [1, 2, 3]
+159     68/push 3/imm32
+160     68/push 2/imm32
+161     68/push 1/imm32
+162     68/push 0xc/imm32/size
+163     89/<- %ecx 4/r32/esp
+164     # var edx : (array int) = [1, 2, 3]
+165     68/push 3/imm32
+166     68/push 2/imm32
+167     68/push 1/imm32
+168     68/push 0xc/imm32/size
+169     89/<- %edx 4/r32/esp
+170     # eax = array-equal?(ecx, edx)
+171     # . . push args
+172     52/push-edx
+173     51/push-ecx
+174     # . . call
+175     e8/call array-equal?/disp32
+176     # . . discard args
+177     81 0/subop/add %esp 8/imm32
+178     # check-ints-equal(eax, 1, msg)
+179     # . . push args
+180     68/push "F - test-compare-equal-arrays"/imm32
+181     68/push 1/imm32/true
+182     50/push-eax
+183     # . . call
+184     e8/call check-ints-equal/disp32
+185     # . . discard args
+186     81 0/subop/add %esp 0xc/imm32
+187     # . epilogue
+188     89/<- %esp 5/r32/ebp
+189     5d/pop-to-ebp
+190     c3/return
+191 
+192 test-compare-inequal-arrays-equal-lengths:
+193     # . prologue
+194     55/push-ebp
+195     89/<- %ebp 4/r32/esp
+196     # var ecx : (array int) = [1, 4, 3]
+197     68/push 3/imm32
+198     68/push 4/imm32
+199     68/push 1/imm32
+200     68/push 0xc/imm32/size
+201     89/<- %ecx 4/r32/esp
+202     # var edx : (array int) = [1, 2, 3]
+203     68/push 3/imm32
+204     68/push 2/imm32
+205     68/push 1/imm32
+206     68/push 0xc/imm32/size
+207     89/<- %edx 4/r32/esp
+208     # eax = array-equal?(ecx, edx)
+209     # . . push args
+210     52/push-edx
+211     51/push-ecx
+212     # . . call
+213     e8/call array-equal?/disp32
+214     # . . discard args
+215     81 0/subop/add %esp 8/imm32
+216     # check-ints-equal(eax, 0, msg)
+217     # . . push args
+218     68/push "F - test-compare-inequal-arrays-equal-lengths"/imm32
+219     68/push 0/imm32/false
+220     50/push-eax
+221     # . . call
+222     e8/call check-ints-equal/disp32
+223     # . . discard args
+224     81 0/subop/add %esp 0xc/imm32
+225     # . epilogue
+226     89/<- %esp 5/r32/ebp
+227     5d/pop-to-ebp
+228     c3/return
+229 
+230 parse-array-of-ints:  # ad : (addr allocation-descriptor), s : (addr string) -> result/eax : (handle array int)
+231     # pseudocode
+232     #   end = &s->data[s->length]
+233     #   curr = s->data
+234     #   size = 0
+235     #   while true
+236     #     if (curr >= end) break
+237     #     curr = skip-chars-matching-in-slice(curr, end, ' ')
+238     #     if (curr >= end) break
+239     #     curr = skip-chars-not-matching-in-slice(curr, end, ' ')
+240     #     ++size
+241     #   result = allocate(ad, (size+1)*4)
+242     #   result->size = (size+1)*4
+243     #   var slice : slice = {s->data, 0}
+244     #   out = result->data
+245     #   while true
+246     #     if (slice->start >= end) break
+247     #     slice->start = skip-chars-matching-in-slice(slice->start, end, ' ')
+248     #     if (slice->start >= end) break
+249     #     slice->end = skip-chars-not-matching-in-slice(slice->start, end, ' ')
+250     #     *out = parse-hex-int(slice)
+251     #     out += 4
+252     #     slice->start = slice->end
+253     #   return result
+254     #
+255     # . prologue
+256     55/push-ebp
+257     89/<- %ebp 4/r32/esp
+258     # . save registers
+259     51/push-ecx
+260     52/push-edx
+261     53/push-ebx
+262     56/push-esi
+263     57/push-edi
+264     # esi = s
+265     8b/-> *(ebp+0xc) 6/r32/esi
+266     # var curr/ecx : (addr byte) = s->data
+267     8d/copy-address *(esi+4) 1/r32/ecx
+268     # var end/edx : (addr byte) = &s->data[s->length]
+269     # . edx = s->length
+270     8b/-> *esi 2/r32/edx
+271     # . edx += curr
+272     01/add %edx 1/r32/ecx
+273     # var size/ebx : int = 0
+274     31/xor %ebx 3/r32/ebx
+275 $parse-array-of-ints:loop1:
+276     # if (curr >= end) break
+277     39/compare %ecx 2/r32/edx
+278     73/jump-if-greater-or-equal-unsigned $parse-array-of-ints:break1/disp8
+279     # curr = skip-chars-matching-in-slice(curr, end, ' ')
+280     # . eax = skip-chars-matching-in-slice(curr, end, ' ')
+281     # . . push args
+282     68/push 0x20/imm32/space
+283     52/push-edx
+284     51/push-ecx
+285     # . . call
+286     e8/call skip-chars-matching-in-slice/disp32
+287     # . . discard args
+288     81 0/subop/add %esp 0xc/imm32
+289     # . ecx = eax
+290     89/<- %ecx 0/r32/eax
+291     # if (curr >= end) break
+292     39/compare %ecx 2/r32/edx
+293     73/jump-if-greater-or-equal-unsigned $parse-array-of-ints:break1/disp8
+294     # curr = skip-chars-not-matching-in-slice(curr, end, ' ')
+295     # . eax = skip-chars-not-matching-in-slice(curr, end, ' ')
+296     # . . push args
+297     68/push 0x20/imm32/space
+298     52/push-edx
+299     51/push-ecx
+300     # . . call
+301     e8/call skip-chars-not-matching-in-slice/disp32
+302     # . . discard args
+303     81 0/subop/add %esp 0xc/imm32
+304     # . ecx = eax
+305     89/<- %ecx 0/r32/eax
+306     # size += 4
+307     81 0/subop/add %ebx 4/imm32
+308     eb/jump $parse-array-of-ints:loop1/disp8
+309 $parse-array-of-ints:break1:
+310     # var result/edi : (handle array int) = allocate(ad, size+4)
+311     # . eax = allocate(ad, size+4)
+312     # . . push args
+313     89/<- %eax 3/r32/ebx
+314     05/add-to-eax 4/imm32
+315     50/push-eax
+316     ff 6/subop/push *(ebp+8)
+317     # . . call
+318     e8/call allocate/disp32
+319     # . . discard args
+320     81 0/subop/add %esp 8/imm32
+321     # . edi = eax
+322     89/<- %edi 0/r32/eax
+323     # result->size = size
+324     89/<- *eax 3/r32/ebx
+325 $parse-array-of-ints:pass2:
+326     # var slice/ecx : slice = {s->data, 0}
+327     68/push 0/imm32/end
+328     8d/copy-address *(esi+4) 1/r32/ecx
+329     51/push-ecx
+330     89/<- %ecx 4/r32/esp
+331     # var out/ebx : (addr byte) = result->data
+332     8d/copy-address *(eax+4) 3/r32/ebx
+333 $parse-array-of-ints:loop2:
+334     # if (slice->start >= end) break
+335     39/compare *ecx 2/r32/edx
+336     73/jump-if-greater-or-equal-unsigned $parse-array-of-ints:end/disp8
+337     # slice->start = skip-chars-matching-in-slice(slice->start, end, ' ')
+338     # . eax = skip-chars-matching-in-slice(slice->start, end, ' ')
+339     # . . push args
+340     68/push 0x20/imm32/space
+341     52/push-edx
+342     ff 6/subop/push *ecx
+343     # . . call
+344     e8/call skip-chars-matching-in-slice/disp32
+345     # . . discard args
+346     81 0/subop/add %esp 0xc/imm32
+347     # . slice->start = eax
+348     89/<- *ecx 0/r32/eax
+349     # if (slice->start >= end) break
+350     39/compare *ecx 2/r32/edx
+351     73/jump-if-greater-or-equal-unsigned $parse-array-of-ints:end/disp8
+352     # slice->end = skip-chars-not-matching-in-slice(slice->start, end, ' ')
+353     # . eax = skip-chars-not-matching-in-slice(curr, end, ' ')
+354     # . . push args
+355     68/push 0x20/imm32/space
+356     52/push-edx
+357     50/push-eax
+358     # . . call
+359     e8/call skip-chars-not-matching-in-slice/disp32
+360     # . . discard args
+361     81 0/subop/add %esp 0xc/imm32
+362     # . slice->end = eax
+363     89/<- *(ecx+4) 0/r32/eax
+364     # *out = parse-hex-int(slice)
+365     # . eax = parse-hex-int(slice)
+366     # . . push args
+367     51/push-ecx
+368     # . . call
+369     e8/call parse-hex-int/disp32
+370     # . . discard args
+371     81 0/subop/add %esp 4/imm32
+372     # . *out = eax
+373     89/<- *ebx 0/r32/eax
+374     # out += 4
+375     81 0/subop/add %ebx 4/imm32
+376     # slice->start = slice->end
+377     8b/-> *(ecx+4) 0/r32/eax
+378     89/<- *ecx 0/r32/eax
+379     81 0/subop/add %ecx 4/imm32
+380     eb/jump $parse-array-of-ints:loop2/disp8
+381 $parse-array-of-ints:end:
+382     # return edi
+383     89/<- %eax 7/r32/edi
+384     # . reclaim locals
+385     81 0/subop/add %esp 8/imm32
+386     # . restore registers
+387     5f/pop-to-edi
+388     5e/pop-to-esi
+389     5b/pop-to-ebx
+390     5a/pop-to-edx
+391     59/pop-to-ecx
+392     # . epilogue
+393     89/<- %esp 5/r32/ebp
+394     5d/pop-to-ebp
+395     c3/return
+396 
+397 test-parse-array-of-ints:
+398     # . prologue
+399     55/push-ebp
+400     89/<- %ebp 4/r32/esp
+401     # var ecx : (array int) = [1, 2, 3]
+402     68/push 3/imm32
+403     68/push 2/imm32
+404     68/push 1/imm32
+405     68/push 0xc/imm32/size
+406     89/<- %ecx 4/r32/esp
+407     # eax = parse-array-of-ints(Heap, "1 2 3")
+408     # . . push args
+409     68/push "1 2 3"/imm32
+410     68/push Heap/imm32
+411     # . . call
+412     e8/call parse-array-of-ints/disp32
+413     # . . discard args
+414     81 0/subop/add %esp 8/imm32
+415     # eax = array-equal?(ecx, eax)
+416     # . . push args
+417     50/push-eax
+418     51/push-ecx
+419     # . . call
+420     e8/call array-equal?/disp32
+421     # . . discard args
+422     81 0/subop/add %esp 8/imm32
+423     # check-ints-equal(eax, 1, msg)
+424     # . . push args
+425     68/push "F - test-parse-array-of-ints"/imm32
+426     68/push 1/imm32/true
+427     50/push-eax
+428     # . . call
+429     e8/call check-ints-equal/disp32
+430     # . . discard args
+431     81 0/subop/add %esp 0xc/imm32
+432     # . epilogue
+433     89/<- %esp 5/r32/ebp
+434     5d/pop-to-ebp
+435     c3/return
+436 
+437 test-parse-array-of-ints-empty:
+438     # - empty string = empty array
+439     # . prologue
+440     55/push-ebp
+441     89/<- %ebp 4/r32/esp
+442     # eax = parse-array-of-ints(Heap, "")
+443     # . . push args
+444     68/push ""/imm32
+445     68/push Heap/imm32
+446     # . . call
+447     e8/call parse-array-of-ints/disp32
+448     # . . discard args
+449     81 0/subop/add %esp 8/imm32
+450     # check-ints-equal(*eax, 0, msg)
+451     # . . push args
+452     68/push "F - test-parse-array-of-ints-empty"/imm32
+453     68/push 0/imm32/size
+454     ff 6/subop/push *eax
+455     # . . call
+456     e8/call check-ints-equal/disp32
+457     # . . discard args
+458     81 0/subop/add %esp 0xc/imm32
+459     # . epilogue
+460     89/<- %esp 5/r32/ebp
+461     5d/pop-to-ebp
+462     c3/return
+463 
+464 test-parse-array-of-ints-just-whitespace:
+465     # - just whitespace = empty array
+466     # . prologue
+467     55/push-ebp
+468     89/<- %ebp 4/r32/esp
+469     # eax = parse-array-of-ints(Heap, " ")
+470     # . . push args
+471     68/push Space/imm32
+472     68/push Heap/imm32
+473     # . . call
+474     e8/call parse-array-of-ints/disp32
+475     # . . discard args
+476     81 0/subop/add %esp 8/imm32
+477     # check-ints-equal(*eax, 0, msg)
+478     # . . push args
+479     68/push "F - test-parse-array-of-ints-empty"/imm32
+480     68/push 0/imm32/size
+481     ff 6/subop/push *eax
+482     # . . call
+483     e8/call check-ints-equal/disp32
+484     # . . discard args
+485     81 0/subop/add %esp 0xc/imm32
+486     # . epilogue
+487     89/<- %esp 5/r32/ebp
+488     5d/pop-to-ebp
+489     c3/return
+490 
+491 test-parse-array-of-ints-extra-whitespace:
+492     # . prologue
+493     55/push-ebp
+494     89/<- %ebp 4/r32/esp
+495     # var ecx : (array int) = [1, 2, 3]
+496     68/push 3/imm32
+497     68/push 2/imm32
+498     68/push 1/imm32
+499     68/push 0xc/imm32/size
+500     89/<- %ecx 4/r32/esp
+501     # eax = parse-array-of-ints(Heap, " 1 2  3  ")
+502     # . . push args
+503     68/push " 1 2  3  "/imm32
+504     68/push Heap/imm32
+505     # . . call
+506     e8/call parse-array-of-ints/disp32
+507     # . . discard args
+508     81 0/subop/add %esp 8/imm32
+509     # eax = array-equal?(ecx, eax)
+510     # . . push args
+511     50/push-eax
+512     51/push-ecx
+513     # . . call
+514     e8/call array-equal?/disp32
+515     # . . discard args
+516     81 0/subop/add %esp 8/imm32
+517     # check-ints-equal(eax, 1, msg)
+518     # . . push args
+519     68/push "F - test-parse-array-of-ints-extra-whitespace"/imm32
+520     68/push 1/imm32/true
+521     50/push-eax
+522     # . . call
+523     e8/call check-ints-equal/disp32
+524     # . . discard args
+525     81 0/subop/add %esp 0xc/imm32
+526     # . epilogue
+527     89/<- %esp 5/r32/ebp
+528     5d/pop-to-ebp
+529     c3/return
+530 
+531 # helper for later tests
+532 # compare an array with a string representation of an array literal
+533 check-array-equal:  # a : (addr array int), expected : (addr string), msg : (addr string)
+534     # . prologue
+535     55/push-ebp
+536     89/<- %ebp 4/r32/esp
+537     # . save registers
+538     50/push-eax
+539     # var b/ecx : (handle array int) = parse-array-of-ints(Heap, expected)
+540     # . eax = parse-array-of-ints(Heap, expected)
+541     # . . push args
+542     ff 6/subop/push *(ebp+0xc)
+543     68/push Heap/imm32
+544     # . . call
+545     e8/call parse-array-of-ints/disp32
+546     # . . discard args
+547     81 0/subop/add %esp 8/imm32
+548     # . b = eax
+549     89/<- %ecx 0/r32/eax
+550     # eax = array-equal?(a, b)
+551     # . . push args
+552     51/push-ecx
+553     ff 6/subop/push *(ebp+8)
+554     # . . call
+555     e8/call array-equal?/disp32
+556     # . . discard args
+557     81 0/subop/add %esp 8/imm32
+558     # check-ints-equal(eax, 1, msg)
+559     # . . push args
+560     ff 6/subop/push *(ebp+0x10)
+561     68/push 1/imm32
+562     50/push-eax
+563     # . . call
+564     e8/call check-ints-equal/disp32
+565     # . . discard args
+566     81 0/subop/add %esp 0xc/imm32
+567 $check-array-equal:end:
+568     # . restore registers
+569     58/pop-to-eax
+570     # . epilogue
+571     89/<- %esp 5/r32/ebp
+572     5d/pop-to-ebp
+573     c3/return
+574 
+575 test-check-array-equal:
+576     # . prologue
+577     55/push-ebp
+578     89/<- %ebp 4/r32/esp
+579     # var ecx : (array int) = [1, 2, 3]
+580     68/push 3/imm32
+581     68/push 2/imm32
+582     68/push 1/imm32
+583     68/push 0xc/imm32/size
+584     89/<- %ecx 4/r32/esp
+585     # check-array-equal(ecx, "1 2 3", "msg")
+586     # . . push args
+587     68/push "F - test-check-array-equal"/imm32
+588     68/push "1 2 3"/imm32
+589     51/push-ecx
+590     # . . call
+591     e8/call check-array-equal/disp32
+592     # . . discard args
+593     81 0/subop/add %esp 8/imm32
+594     # . epilogue
+595     89/<- %esp 5/r32/ebp
+596     5d/pop-to-ebp
+597     c3/return
+598 
+599 # . . vim:nowrap:textwidth=0
+
+ + + -- cgit 1.4.1-2-gfad0