From 44e030822e03b28b53db0f73a9d5d1a3913cee4a Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Thu, 10 Jan 2019 17:19:00 -0800 Subject: 4919 --- html/subx/052kernel-string-equal.subx.html | 23 +- html/subx/059read-byte.subx.html | 2 +- html/subx/060write-stream.subx.html | 2 +- html/subx/062write-byte.subx.html | 262 ++- html/subx/063print-byte.subx.html | 2 +- html/subx/064write-buffered.subx.html | 6 +- html/subx/065error-byte.subx.html | 2 +- html/subx/068read-line.subx.html | 2 +- html/subx/069next-token.subx.html | 514 ----- html/subx/069slice.subx.html | 452 ++++ html/subx/070next-token.subx.html | 512 +++++ html/subx/apps/hex.subx.html | 3330 ++++++++++++++-------------- 12 files changed, 2813 insertions(+), 2296 deletions(-) delete mode 100644 html/subx/069next-token.subx.html create mode 100644 html/subx/069slice.subx.html create mode 100644 html/subx/070next-token.subx.html diff --git a/html/subx/052kernel-string-equal.subx.html b/html/subx/052kernel-string-equal.subx.html index 83df21de..86926d78 100644 --- a/html/subx/052kernel-string-equal.subx.html +++ b/html/subx/052kernel-string-equal.subx.html @@ -21,6 +21,7 @@ a { color:inherit; } .SpecialChar { color: #d70000; } .subxFunction { color: #af5f00; text-decoration: underline; } .subxTest { color: #5f8700; } +.subxMinorFunction { color: #875f5f; } .Normal { color: #000000; background-color: #c6c6c6; padding-bottom: 1px; } .subxS2Comment { color: #8a8a8a; } .subxH1Comment { color: #005faf; text-decoration: underline; } @@ -211,10 +212,10 @@ if ('onhashchange' in window) { 150 c3/return 151 152 test-compare-kernel-string-with-equal-array: -153 # EAX = kernel-string-equal(Abc-kernel-string, "Abc") +153 # EAX = kernel-string-equal(_test-Abc-kernel-string, "Abc") 154 # . . push args 155 68/push "Abc"/imm32 -156 68/push Abc-kernel-string/imm32 +156 68/push _test-Abc-kernel-string/imm32 157 # . . call 158 e8/call kernel-string-equal/disp32 159 # . . discard args @@ -231,10 +232,10 @@ if ('onhashchange' in window) { 170 c3/return 171 172 test-compare-kernel-string-with-inequal-array: -173 # EAX = kernel-string-equal(Abc-kernel-string, "Adc") +173 # EAX = kernel-string-equal(_test-Abc-kernel-string, "Adc") 174 # . . push args 175 68/push "Adc"/imm32 -176 68/push Abc-kernel-string/imm32 +176 68/push _test-Abc-kernel-string/imm32 177 # . . call 178 e8/call kernel-string-equal/disp32 179 # . . discard args @@ -251,10 +252,10 @@ if ('onhashchange' in window) { 190 c3/return 191 192 test-compare-kernel-string-with-empty-array: -193 # EAX = kernel-string-equal(Abc-kernel-string, "") +193 # EAX = kernel-string-equal(_test-Abc-kernel-string, "") 194 # . . push args 195 68/push ""/imm32 -196 68/push Abc-kernel-string/imm32 +196 68/push _test-Abc-kernel-string/imm32 197 # . . call 198 e8/call kernel-string-equal/disp32 199 # . . discard args @@ -271,10 +272,10 @@ if ('onhashchange' in window) { 210 c3/return 211 212 test-compare-kernel-string-with-shorter-array: -213 # EAX = kernel-string-equal(Abc-kernel-string, "Ab") +213 # EAX = kernel-string-equal(_test-Abc-kernel-string, "Ab") 214 # . . push args 215 68/push "Ab"/imm32 -216 68/push Abc-kernel-string/imm32 +216 68/push _test-Abc-kernel-string/imm32 217 # . . call 218 e8/call kernel-string-equal/disp32 219 # . . discard args @@ -291,10 +292,10 @@ if ('onhashchange' in window) { 230 c3/return 231 232 test-compare-kernel-string-with-longer-array: -233 # EAX = kernel-string-equal(Abc-kernel-string, "Abcd") +233 # EAX = kernel-string-equal(_test-Abc-kernel-string, "Abcd") 234 # . . push args 235 68/push "Abcd"/imm32 -236 68/push Abc-kernel-string/imm32 +236 68/push _test-Abc-kernel-string/imm32 237 # . . call 238 e8/call kernel-string-equal/disp32 239 # . . discard args @@ -314,7 +315,7 @@ if ('onhashchange' in window) { 253 254 Null-kernel-string: 255 00/null -256 Abc-kernel-string: +256 _test-Abc-kernel-string: 257 41/A 62/b 63/c 00/null 258 259 # . . vim:nowrap:textwidth=0 diff --git a/html/subx/059read-byte.subx.html b/html/subx/059read-byte.subx.html index 7eb39292..9d8cff7c 100644 --- a/html/subx/059read-byte.subx.html +++ b/html/subx/059read-byte.subx.html @@ -127,7 +127,7 @@ if ('onhashchange' in window) { 64 e8/call clear-stream/disp32 65 # . . discard args 66 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 67 # . f->read must now be 0; update ECX + 67 # . f->read must now be 0; update its cache at ECX 68 31/xor 3/mod/direct 1/rm32/ECX . . . 1/r32/ECX . . # clear ECX 69 # . EAX = read(f->fd, stream = f+4) 70 # . . push args diff --git a/html/subx/060write-stream.subx.html b/html/subx/060write-stream.subx.html index 027deb60..ffda2352 100644 --- a/html/subx/060write-stream.subx.html +++ b/html/subx/060write-stream.subx.html @@ -158,7 +158,7 @@ if ('onhashchange' in window) { 96 8b/copy 1/mod/*+disp8 6/rm32/ESI . . . 7/r32/EDI 4/disp8 . # copy *(ESI+4) to EDI 97 # EDX = s->write 98 8b/copy 0/mod/indirect 6/rm32/ESI . . . 2/r32/EDX . . # copy *ESI to EDX - 99 # syscall(write, fd, &s->data[s->read], s->write-s->read) + 99 # syscall(write, fd, &s->data[s->read], s->write - s->read) 100 # . . fd : EBX 101 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 3/r32/EBX 8/disp8 . # copy *(EBP+8) to EBX 102 # . . data : ECX = &s->data[s->read] diff --git a/html/subx/062write-byte.subx.html b/html/subx/062write-byte.subx.html index f53db7ba..3032ba85 100644 --- a/html/subx/062write-byte.subx.html +++ b/html/subx/062write-byte.subx.html @@ -114,7 +114,7 @@ if ('onhashchange' in window) { 53 # . . push args 54 57/push-EDI 55 # . . call - 56 e8/call flush/disp32 + 56 e8/call flush/disp32 57 # . . discard args 58 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 59 # . clear-stream(stream = f+4) @@ -125,101 +125,173 @@ if ('onhashchange' in window) { 64 e8/call clear-stream/disp32 65 # . . discard args 66 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 67 $write-byte:to-stream: - 68 # write to stream - 69 # f->data[f->write] = LSB(n) - 70 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX - 71 8a/copy-byte 1/mod/*+disp8 5/rm32/EBP . . . 0/r32/AL 0xc/disp8 . # copy byte at *(EBP+12) to AL - 72 88/copy-byte 1/mod/*+disp8 4/rm32/sib 7/base/EDI 1/index/ECX . 0/r32/AL 0x10/disp8 . # copy AL to *(EDI+ECX+16) - 73 # ++f->write - 74 ff 0/subop/increment 1/mod/*+disp8 7/rm32/EDI . . . . 4/disp8 . # increment *(EDI+4) - 75 $write-byte:end: - 76 # . restore registers - 77 5f/pop-to-EDI - 78 59/pop-to-ECX - 79 # . epilog - 80 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP - 81 5d/pop-to-EBP - 82 c3/return - 83 - 84 flush: # f : (address buffered-file) -> <void> - 85 # . prolog - 86 55/push-EBP - 87 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP - 88 # . save registers - 89 50/push-EAX - 90 51/push-ECX - 91 # EAX = f - 92 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 0/r32/EAX 8/disp8 . # copy *(EBP+8) to EAX - 93 # write-stream(f->fd, data = f+4) - 94 # . . push args - 95 8d/copy-address 1/mod/*+disp8 0/rm32/EAX . . . 1/r32/ECX 4/disp8 . # copy EAX+4 to ECX - 96 51/push-ECX - 97 ff 6/subop/push 0/mod/indirect 0/rm32/EAX . . . . . . # push *EAX - 98 # . . call - 99 e8/call write-stream/disp32 -100 # . . discard args -101 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -102 $flush:end: -103 # . restore registers -104 59/pop-to-ECX -105 58/pop-to-EAX -106 # . epilog -107 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -108 5d/pop-to-EBP -109 c3/return -110 -111 # - tests + 67 # . f->write must now be 0; update its cache at ECX + 68 31/xor 3/mod/direct 1/rm32/ECX . . . 1/r32/ECX . . # clear ECX + 69 $write-byte:to-stream: + 70 # write to stream + 71 # f->data[f->write] = LSB(n) + 72 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX + 73 8a/copy-byte 1/mod/*+disp8 5/rm32/EBP . . . 0/r32/AL 0xc/disp8 . # copy byte at *(EBP+12) to AL + 74 88/copy-byte 1/mod/*+disp8 4/rm32/sib 7/base/EDI 1/index/ECX . 0/r32/AL 0x10/disp8 . # copy AL to *(EDI+ECX+16) + 75 # ++f->write + 76 ff 0/subop/increment 1/mod/*+disp8 7/rm32/EDI . . . . 4/disp8 . # increment *(EDI+4) + 77 $write-byte:end: + 78 # . restore registers + 79 5f/pop-to-EDI + 80 59/pop-to-ECX + 81 # . epilog + 82 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP + 83 5d/pop-to-EBP + 84 c3/return + 85 + 86 flush: # f : (address buffered-file) -> <void> + 87 # . prolog + 88 55/push-EBP + 89 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + 90 # . save registers + 91 50/push-EAX + 92 51/push-ECX + 93 # EAX = f + 94 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 0/r32/EAX 8/disp8 . # copy *(EBP+8) to EAX + 95 # write-stream(f->fd, data = f+4) + 96 # . . push args + 97 8d/copy-address 1/mod/*+disp8 0/rm32/EAX . . . 1/r32/ECX 4/disp8 . # copy EAX+4 to ECX + 98 51/push-ECX + 99 ff 6/subop/push 0/mod/indirect 0/rm32/EAX . . . . . . # push *EAX +100 # . . call +101 e8/call write-stream/disp32 +102 # . . discard args +103 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +104 $flush:end: +105 # . restore registers +106 59/pop-to-ECX +107 58/pop-to-EAX +108 # . epilog +109 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +110 5d/pop-to-EBP +111 c3/return 112 -113 test-write-byte-single: -114 # - check that read-byte returns first byte of 'file' -115 # setup -116 # . clear-stream(_test-stream) -117 # . . push args -118 68/push _test-stream/imm32 -119 # . . call -120 e8/call clear-stream/disp32 -121 # . . discard args -122 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -123 # . clear-stream(_test-buffered-file+4) -124 # . . push args -125 b8/copy-to-EAX _test-buffered-file/imm32 -126 05/add-to-EAX 4/imm32 -127 50/push-EAX -128 # . . call -129 e8/call clear-stream/disp32 -130 # . . discard args -131 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -132 # write-byte(_test-buffered-file, 'A') -133 # . . push args -134 68/push 0x41/imm32 -135 68/push _test-buffered-file/imm32 -136 # . . call -137 e8/call write-byte/disp32 -138 # . . discard args -139 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -140 # flush(_test-buffered-file) -141 # . . push args -142 68/push _test-buffered-file/imm32 -143 # . . call -144 e8/call flush/disp32 -145 # . . discard args -146 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -147 # check-ints-equal(*_test-stream->data, 'A', msg) -148 # . . push args -149 68/push "F - test-write-byte-single"/imm32 -150 68/push 0x41/imm32 -151 # . . push *_test-stream->data -152 b8/copy-to-EAX _test-stream/imm32 -153 ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0xc/disp8 . # push *(EAX+12) -154 # . . call -155 e8/call check-ints-equal/disp32 -156 # . . discard args -157 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -158 # . end -159 c3/return -160 -161 # . . vim:nowrap:textwidth=0 +113 # - tests +114 +115 test-write-byte-single: +116 # - check that write-byte writes to first byte of 'file' +117 # setup +118 # . clear-stream(_test-stream) +119 # . . push args +120 68/push _test-stream/imm32 +121 # . . call +122 e8/call clear-stream/disp32 +123 # . . discard args +124 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +125 # . clear-stream(_test-buffered-file+4) +126 # . . push args +127 b8/copy-to-EAX _test-buffered-file/imm32 +128 05/add-to-EAX 4/imm32 +129 50/push-EAX +130 # . . call +131 e8/call clear-stream/disp32 +132 # . . discard args +133 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +134 # write-byte(_test-buffered-file, 'A') +135 # . . push args +136 68/push 0x41/imm32 +137 68/push _test-buffered-file/imm32 +138 # . . call +139 e8/call write-byte/disp32 +140 # . . discard args +141 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +142 # flush(_test-buffered-file) +143 # . . push args +144 68/push _test-buffered-file/imm32 +145 # . . call +146 e8/call flush/disp32 +147 # . . discard args +148 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +149 # check-ints-equal(*_test-stream->data, 'A', msg) +150 # . . push args +151 68/push "F - test-write-byte-single"/imm32 +152 68/push 0x41/imm32 +153 # . . push *_test-stream->data +154 b8/copy-to-EAX _test-stream/imm32 +155 ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0xc/disp8 . # push *(EAX+12) +156 # . . call +157 e8/call check-ints-equal/disp32 +158 # . . discard args +159 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +160 # . end +161 c3/return +162 +163 test-write-byte-multiple-flushes: +164 # - check that write-byte correctly flushes buffered data +165 # setup +166 # . clear-stream(_test-stream) +167 # . . push args +168 68/push _test-stream/imm32 +169 # . . call +170 e8/call clear-stream/disp32 +171 # . . discard args +172 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +173 # . clear-stream(_test-buffered-file+4) +174 # . . push args +175 b8/copy-to-EAX _test-buffered-file/imm32 +176 05/add-to-EAX 4/imm32 +177 50/push-EAX +178 # . . call +179 e8/call clear-stream/disp32 +180 # . . discard args +181 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +182 # fill up the buffer for _test-buffered-file +183 # . write(_test-buffered-file+4, 'abcdef') +184 # . . push args +185 68/push "abcdef"/imm32 +186 b8/copy-to-EAX _test-buffered-file/imm32 +187 05/add-to-EAX 4/imm32 +188 50/push-EAX +189 # . . call +190 e8/call write/disp32 +191 # . . discard args +192 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +193 # write-byte(_test-buffered-file, 'g') +194 # . . push args +195 68/push 0x67/imm32 +196 68/push _test-buffered-file/imm32 +197 # . . call +198 e8/call write-byte/disp32 +199 # . . discard args +200 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +201 # flush(_test-buffered-file) +202 # . . push args +203 68/push _test-buffered-file/imm32 +204 # . . call +205 e8/call flush/disp32 +206 # . . discard args +207 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +208 # check-ints-equal(_test-stream->data[0..3], 'abcd', msg) +209 # . . push args +210 68/push "F - test-write-byte-multiple-flushes: 1"/imm32 +211 68/push 0x64636261/imm32 +212 # . . push *_test-stream->data +213 b8/copy-to-EAX _test-stream/imm32 +214 ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0xc/disp8 . # push *(EAX+12) +215 # . . call +216 e8/call check-ints-equal/disp32 +217 # . . discard args +218 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +219 # check-ints-equal(_test-stream->data[4..8], 'efg', msg) +220 # . . push args +221 68/push "F - test-write-byte-multiple-flushes"/imm32 +222 68/push 0x00676665/imm32 +223 # . . push *_test-stream->data +224 b8/copy-to-EAX _test-stream/imm32 +225 ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0x10/disp8 . # push *(EAX+16) +226 # . . call +227 e8/call check-ints-equal/disp32 +228 # . . discard args +229 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +230 # . end +231 c3/return +232 +233 # . . vim:nowrap:textwidth=0 diff --git a/html/subx/063print-byte.subx.html b/html/subx/063print-byte.subx.html index 4a21bc33..6462dade 100644 --- a/html/subx/063print-byte.subx.html +++ b/html/subx/063print-byte.subx.html @@ -183,7 +183,7 @@ if ('onhashchange' in window) { 122 # . . push args 123 68/push _test-buffered-file/imm32 124 # . . call -125 e8/call flush/disp32 +125 e8/call flush/disp32 126 # . . discard args 127 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 128 # check-ints-equal(*_test-stream->data, '0a', msg) diff --git a/html/subx/064write-buffered.subx.html b/html/subx/064write-buffered.subx.html index 5327f9c6..41e9ee6c 100644 --- a/html/subx/064write-buffered.subx.html +++ b/html/subx/064write-buffered.subx.html @@ -132,7 +132,7 @@ if ('onhashchange' in window) { 70 # . . push args 71 57/push-EDI 72 # . . call - 73 e8/call flush/disp32 + 73 e8/call flush/disp32 74 # . . discard args 75 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 76 # . clear-stream(stream = f+4) @@ -143,7 +143,7 @@ if ('onhashchange' in window) { 81 e8/call clear-stream/disp32 82 # . . discard args 83 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 84 # . clear EBX (cached f->write) + 84 # . f->write must now be 0; update its cache at EBX 85 31/xor 3/mod/direct 3/rm32/EBX . . . 3/r32/EBX . . # clear EBX 86 $write-buffered:to-stream: 87 # write to stream @@ -205,7 +205,7 @@ if ('onhashchange' in window) { 143 # . . push args 144 68/push _test-buffered-file/imm32 145 # . . call -146 e8/call flush/disp32 +146 e8/call flush/disp32 147 # . . discard args 148 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 149 # check-ints-equal(*_test-stream->data, "Abc", msg) diff --git a/html/subx/065error-byte.subx.html b/html/subx/065error-byte.subx.html index 31783f53..6632f448 100644 --- a/html/subx/065error-byte.subx.html +++ b/html/subx/065error-byte.subx.html @@ -135,7 +135,7 @@ if ('onhashchange' in window) { 75 # . . push args 76 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) 77 # . . call - 78 e8/call flush/disp32 + 78 e8/call flush/disp32 79 # . . discard args 80 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 81 # stop(ed, 1) diff --git a/html/subx/068read-line.subx.html b/html/subx/068read-line.subx.html index 3c42df5c..e65883fb 100644 --- a/html/subx/068read-line.subx.html +++ b/html/subx/068read-line.subx.html @@ -116,7 +116,7 @@ if ('onhashchange' in window) { 55 e8/call clear-stream/disp32 56 # . . discard args 57 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 58 # . f->read must now be 0; update ECX + 58 # . f->read must now be 0; update its cache at ECX 59 31/xor 3/mod/direct 1/rm32/ECX . . . 1/r32/ECX . . # clear ECX 60 # . EAX = read(f->fd, stream = f+4) 61 # . . push args diff --git a/html/subx/069next-token.subx.html b/html/subx/069next-token.subx.html deleted file mode 100644 index 9a8395a1..00000000 --- a/html/subx/069next-token.subx.html +++ /dev/null @@ -1,514 +0,0 @@ - - - - -Mu - subx/069next-token.subx - - - - - - - - - - -https://github.com/akkartik/mu/blob/master/subx/069next-token.subx -
-  1 == code
-  2 #   instruction                     effective address                                                   register    displacement    immediate
-  3 # . op          subop               mod             rm32          base        index         scale       r32
-  4 # . 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
-  5 
-  6 # main:
-  7     e8/call  run-tests/disp32  # 'run-tests' is a function created automatically by SubX. It calls all functions that start with 'test-'.
-  8     # syscall(exit, Num-test-failures)
-  9     8b/copy                         0/mod/indirect  5/rm32/.disp32            .             .           3/r32/EBX   Num-test-failures/disp32          # copy *Num-test-failures to EBX
- 10     b8/copy-to-EAX  1/imm32/exit
- 11     cd/syscall  0x80/imm8
- 12 
- 13 # new data structure: a slice is an open interval of addresses [start, end) that includes 'start' but not 'end'
- 14 
- 15 # extract the next run of characters that are different from a given 'delimiter'
- 16 # on eof return an empty interval
- 17 next-token:  # in : (address stream), delimiter : byte, out : (address slice)
- 18     # . prolog
- 19     55/push-EBP
- 20     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
- 21     # . save registers
- 22     50/push-EAX
- 23     51/push-ECX
- 24     56/push-ESI
- 25     57/push-EDI
- 26     # ESI = in
- 27     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           6/r32/ESI   8/disp8         .                 # copy *(EBP+8) to ESI
- 28     # EDI = out
- 29     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           7/r32/EDI   0x10/disp8      .                 # copy *(EBP+16) to EDI
- 30     # skip-chars-matching(in, delimiter)
- 31     # . . push args
- 32     ff          6/subop/push        1/mod/*+disp8   5/rm32/EBP    .           .             .           .           0xc/disp8       .                 # push *(EBP+12)
- 33     ff          6/subop/push        1/mod/*+disp8   5/rm32/EBP    .           .             .           .           8/disp8         .                 # push *(EBP+8)
- 34     # . . call
- 35     e8/call  skip-chars-matching/disp32
- 36     # . . discard args
- 37     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
- 38     # out->start = &in->data[in->read]
- 39     8b/copy                         1/mod/*+disp8   6/rm32/ESI    .           .             .           1/r32/ECX   4/disp8         .                 # copy *(ESI+4) to ECX
- 40     8d/copy-address                 1/mod/*+disp8   4/rm32/sib    6/base/ESI  1/index/ECX   .           0/r32/EAX   0xc/disp8       .                 # copy ESI+ECX+12 to EAX
- 41     89/copy                         0/mod/indirect  7/rm32/EDI    .           .             .           0/r32/EAX   .               .                 # copy EAX to *EDI
- 42     # skip-chars-not-matching(in, delimiter)
- 43     # . . push args
- 44     ff          6/subop/push        1/mod/*+disp8   5/rm32/EBP    .           .             .           .           0xc/disp8       .                 # push *(EBP+12)
- 45     ff          6/subop/push        1/mod/*+disp8   5/rm32/EBP    .           .             .           .           8/disp8         .                 # push *(EBP+8)
- 46     # . . call
- 47     e8/call  skip-chars-not-matching/disp32
- 48     # . . discard args
- 49     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
- 50     # out->end = &in->data[in->read]
- 51     8b/copy                         1/mod/*+disp8   6/rm32/ESI    .           .             .           1/r32/ECX   4/disp8         .                 # copy *(ESI+4) to ECX
- 52     8d/copy-address                 1/mod/*+disp8   4/rm32/sib    6/base/ESI  1/index/ECX   .           0/r32/EAX   0xc/disp8       .                 # copy ESI+ECX+12 to EAX
- 53     89/copy                         1/mod/*+disp8   7/rm32/EDI    .           .             .           0/r32/EAX   4/disp8         .                 # copy EAX to *(EDI+4)
- 54     # . restore registers
- 55     5f/pop-to-EDI
- 56     5e/pop-to-ESI
- 57     59/pop-to-ECX
- 58     58/pop-to-EAX
- 59     # . epilog
- 60     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
- 61     5d/pop-to-EBP
- 62     c3/return
- 63 
- 64 test-next-token:
- 65     # . prolog
- 66     55/push-EBP
- 67     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
- 68     # setup
- 69     # . clear-stream(_test-stream)
- 70     # . . push args
- 71     68/push  _test-stream/imm32
- 72     # . . call
- 73     e8/call  clear-stream/disp32
- 74     # . . discard args
- 75     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
- 76     # var slice/ECX = {0, 0}
- 77     68/push  0/imm32/end
- 78     68/push  0/imm32/start
- 79     89/copy                         3/mod/direct    1/rm32/ECX    .           .             .           4/r32/ESP   .               .                 # copy ESP to ECX
- 80     # write(_test-stream, "  ab")
- 81     # . . push args
- 82     68/push  "  ab"/imm32
- 83     68/push  _test-stream/imm32
- 84     # . . call
- 85     e8/call  write/disp32
- 86     # . . discard args
- 87     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
- 88     # next-token(_test-stream, 0x20/space, slice)
- 89     # . . push args
- 90     51/push-ECX
- 91     68/push  0x20/imm32
- 92     68/push  _test-stream/imm32
- 93     # . . call
- 94     e8/call  next-token/disp32
- 95     # . . discard args
- 96     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
- 97     # check-ints-equal(slice->start - _test-stream->data, 2, msg)
- 98     # . check-ints-equal(slice->start - _test-stream, 14, msg)
- 99     # . . push args
-100     68/push  "F - test-next-token: start"/imm32
-101     68/push  0xe/imm32
-102     # . . push slice->start - _test-stream
-103     8b/copy                         0/mod/indirect  1/rm32/ECX    .           .             .           0/r32/EAX   .               .                 # copy *ECX to EAX
-104     81          5/subop/subtract    3/mod/direct    0/rm32/EAX    .           .             .           .           .               _test-stream/imm32 # subtract from EAX
-105     50/push-EAX
-106     # . . call
-107     e8/call  check-ints-equal/disp32
-108     # . . discard args
-109     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
-110     # check-ints-equal(slice->end - _test-stream->data, 4, msg)
-111     # . check-ints-equal(slice->end - _test-stream, 16, msg)
-112     # . . push args
-113     68/push  "F - test-next-token: end"/imm32
-114     68/push  0x10/imm32
-115     # . . push slice->end - _test-stream
-116     8b/copy                         1/mod/*+disp8   1/rm32/ECX    .           .             .           0/r32/EAX   4/disp8         .                 # copy *(ECX+4) to EAX
-117     81          5/subop/subtract    3/mod/direct    0/rm32/EAX    .           .             .           .           .               _test-stream/imm32 # subtract from EAX
-118     50/push-EAX
-119     # . . call
-120     e8/call  check-ints-equal/disp32
-121     # . . discard args
-122     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
-123     # . epilog
-124     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
-125     5d/pop-to-EBP
-126     c3/return
-127 
-128 test-next-token-eof:
-129     # . prolog
-130     55/push-EBP
-131     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
-132     # setup
-133     # . clear-stream(_test-stream)
-134     # . . push args
-135     68/push  _test-stream/imm32
-136     # . . call
-137     e8/call  clear-stream/disp32
-138     # . . discard args
-139     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
-140     # var slice/ECX = {0, 0}
-141     68/push  0/imm32/end
-142     68/push  0/imm32/start
-143     89/copy                         3/mod/direct    1/rm32/ECX    .           .             .           4/r32/ESP   .               .                 # copy ESP to ECX
-144     # write nothing to _test-stream
-145     # next-token(_test-stream, 0x20/space, slice)
-146     # . . push args
-147     51/push-ECX
-148     68/push  0x20/imm32
-149     68/push  _test-stream/imm32
-150     # . . call
-151     e8/call  next-token/disp32
-152     # . . discard args
-153     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
-154     # check-ints-equal(slice->end, slice->start, msg)
-155     # . . push args
-156     68/push  "F - test-next-token-eof"/imm32
-157     ff          6/subop/push        1/mod/*+disp8   1/rm32/ECX    .           .             .           .           4/disp8         .                 # push *(ECX+4)
-158     ff          6/subop/push        0/mod/indirect  1/rm32/ECX    .           .             .           .           .               .                 # push *ECX
-159     # . . call
-160     e8/call  check-ints-equal/disp32
-161     # . . discard args
-162     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
-163     # . epilog
-164     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
-165     5d/pop-to-EBP
-166     c3/return
-167 
-168 skip-chars-matching:  # in : (address stream), delimiter : byte
-169     # . prolog
-170     55/push-EBP
-171     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
-172     # . save registers
-173     50/push-EAX
-174     51/push-ECX
-175     52/push-EDX
-176     56/push-ESI
-177     # ESI = in
-178     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           6/r32/ESI   8/disp8         .                 # copy *(EBP+8) to ESI
-179     # ECX = in->read
-180     8b/copy                         1/mod/*+disp8   6/rm32/ESI    .           .             .           1/r32/ECX   4/disp8         .                 # copy *(ESI+4) to ECX
-181     # EBX = in->write
-182     8b/copy                         0/mod/indirect  6/rm32/ESI    .           .             .           3/r32/EBX   .               .                 # copy *ESI to EBX
-183     # EDX = delimiter
-184     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           2/r32/EDX   0xc/disp8       .                 # copy *(EBP+12) to EDX
-185 $skip-chars-matching:loop:
-186     # if (in->read >= in->write) break
-187     3b/compare                      3/mod/direct    3/rm32/EBX    .           .             .           1/r32/ECX   .               .                 # compare ECX with *EBX
-188     7d/jump-if-greater-or-equal  $skip-chars-matching:end/disp8
-189     # EAX = in->data[in->read]
-190     31/xor                          3/mod/direct    0/rm32/EAX    .           .             .           0/r32/EAX   .               .                 # clear EAX
-191     8a/copy-byte                    1/mod/*+disp8   4/rm32/sib    6/base/ESI  1/index/ECX   .           0/r32/AL    0xc/disp8       .                 # copy byte at *(ESI+ECX+12) to AL
-192     # if (EAX != delimiter) break
-193     39/compare                      3/mod/direct    0/rm32/EAX    .           .             .           2/r32/EDX   .               .                 # compare EAX and EDX
-194     75/jump-if-not-equal  $skip-chars-matching:end/disp8
-195     # ++in->read
-196     41/inc-ECX
-197     eb/jump  $skip-chars-matching:loop/disp8
-198 $skip-chars-matching:end:
-199     # persist in->read
-200     89/copy                         1/mod/*+disp8   6/rm32/ESI    .           .             .           1/r32/ECX   4/disp8         .                 # copy ECX to *(ESI+4)
-201     # . restore registers
-202     5e/pop-to-ESI
-203     5a/pop-to-EDX
-204     59/pop-to-ECX
-205     58/pop-to-EAX
-206     # . epilog
-207     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
-208     5d/pop-to-EBP
-209     c3/return
-210 
-211 test-skip-chars-matching:
-212     # setup
-213     # . clear-stream(_test-stream)
-214     # . . push args
-215     68/push  _test-stream/imm32
-216     # . . call
-217     e8/call  clear-stream/disp32
-218     # . . discard args
-219     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
-220     # write(_test-stream, "  ab")
-221     # . . push args
-222     68/push  "  ab"/imm32
-223     68/push  _test-stream/imm32
-224     # . . call
-225     e8/call  write/disp32
-226     # . . discard args
-227     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
-228     # skip-chars-matching(_test-stream, 0x20/space)
-229     # . . push args
-230     68/push  0x20/imm32
-231     68/push  _test-stream/imm32
-232     # . . call
-233     e8/call  skip-chars-matching/disp32
-234     # . . discard args
-235     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
-236     # check-ints-equal(_test-stream->read, 2, msg)
-237     # . . push args
-238     68/push  "F - test-skip-chars-matching"/imm32
-239     68/push  2/imm32
-240     # . . push *_test-stream->read
-241     b8/copy-to-EAX  _test-stream/imm32
-242     ff          6/subop/push        1/mod/*+disp8   0/rm32/EAX    .           .             .           .           4/disp8         .                 # push *(EAX+4)
-243     # . . call
-244     e8/call  check-ints-equal/disp32
-245     # . . discard args
-246     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
-247     # end
-248     c3/return
-249 
-250 test-skip-chars-matching-none:
-251     # setup
-252     # . clear-stream(_test-stream)
-253     # . . push args
-254     68/push  _test-stream/imm32
-255     # . . call
-256     e8/call  clear-stream/disp32
-257     # . . discard args
-258     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
-259     # write(_test-stream, "ab")
-260     # . . push args
-261     68/push  "ab"/imm32
-262     68/push  _test-stream/imm32
-263     # . . call
-264     e8/call  write/disp32
-265     # . . discard args
-266     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
-267     # skip-chars-matching(_test-stream, 0x20/space)
-268     # . . push args
-269     68/push  0x20/imm32
-270     68/push  _test-stream/imm32
-271     # . . call
-272     e8/call  skip-chars-matching/disp32
-273     # . . discard args
-274     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
-275     # check-ints-equal(_test-stream->read, 0, msg)
-276     # . . push args
-277     68/push  "F - test-skip-chars-matching-none"/imm32
-278     68/push  0/imm32
-279     # . . push *_test-stream->read
-280     b8/copy-to-EAX  _test-stream/imm32
-281     ff          6/subop/push        1/mod/*+disp8   0/rm32/EAX    .           .             .           .           4/disp8         .                 # push *(EAX+4)
-282     # . . call
-283     e8/call  check-ints-equal/disp32
-284     # . . discard args
-285     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
-286     # end
-287     c3/return
-288 
-289 # minor fork of 'skip-chars-matching'
-290 skip-chars-not-matching:  # in : (address stream), delimiter : byte
-291     # . prolog
-292     55/push-EBP
-293     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
-294     # . save registers
-295     50/push-EAX
-296     51/push-ECX
-297     52/push-EDX
-298     56/push-ESI
-299     # ESI = in
-300     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           6/r32/ESI   8/disp8         .                 # copy *(EBP+8) to ESI
-301     # ECX = in->read
-302     8b/copy                         1/mod/*+disp8   6/rm32/ESI    .           .             .           1/r32/ECX   4/disp8         .                 # copy *(ESI+4) to ECX
-303     # EBX = in->write
-304     8b/copy                         0/mod/indirect  6/rm32/ESI    .           .             .           3/r32/EBX   .               .                 # copy *ESI to EBX
-305     # EDX = delimiter
-306     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           2/r32/EDX   0xc/disp8       .                 # copy *(EBP+12) to EDX
-307 $skip-chars-not-matching:loop:
-308     # if (in->read >= in->write) break
-309     3b/compare                      3/mod/direct    3/rm32/EBX    .           .             .           1/r32/ECX   .               .                 # compare ECX with *EBX
-310     7d/jump-if-greater-or-equal  $skip-chars-not-matching:end/disp8
-311     # EAX = in->data[in->read]
-312     31/xor                          3/mod/direct    0/rm32/EAX    .           .             .           0/r32/EAX   .               .                 # clear EAX
-313     8a/copy-byte                    1/mod/*+disp8   4/rm32/sib    6/base/ESI  1/index/ECX   .           0/r32/AL    0xc/disp8       .                 # copy byte at *(ESI+ECX+12) to AL
-314     # if (EAX == delimiter) break
-315     39/compare                      3/mod/direct    0/rm32/EAX    .           .             .           2/r32/EDX   .               .                 # compare EAX and EDX
-316     74/jump-if-equal  $skip-chars-not-matching:end/disp8
-317     # ++in->read
-318     41/inc-ECX
-319     eb/jump  $skip-chars-not-matching:loop/disp8
-320 $skip-chars-not-matching:end:
-321     # persist in->read
-322     89/copy                         1/mod/*+disp8   6/rm32/ESI    .           .             .           1/r32/ECX   4/disp8         .                 # copy ECX to *(ESI+4)
-323     # . restore registers
-324     5e/pop-to-ESI
-325     5a/pop-to-EDX
-326     59/pop-to-ECX
-327     58/pop-to-EAX
-328     # . epilog
-329     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
-330     5d/pop-to-EBP
-331     c3/return
-332 
-333 test-skip-chars-not-matching:
-334     # setup
-335     # . clear-stream(_test-stream)
-336     # . . push args
-337     68/push  _test-stream/imm32
-338     # . . call
-339     e8/call  clear-stream/disp32
-340     # . . discard args
-341     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
-342     # write(_test-stream, "ab ")
-343     # . . push args
-344     68/push  "ab "/imm32
-345     68/push  _test-stream/imm32
-346     # . . call
-347     e8/call  write/disp32
-348     # . . discard args
-349     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
-350     # skip-chars-not-matching(_test-stream, 0x20/space)
-351     # . . push args
-352     68/push  0x20/imm32
-353     68/push  _test-stream/imm32
-354     # . . call
-355     e8/call  skip-chars-not-matching/disp32
-356     # . . discard args
-357     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
-358     # check-ints-equal(_test-stream->read, 2, msg)
-359     # . . push args
-360     68/push  "F - test-skip-chars-not-matching"/imm32
-361     68/push  2/imm32
-362     # . . push *_test-stream->read
-363     b8/copy-to-EAX  _test-stream/imm32
-364     ff          6/subop/push        1/mod/*+disp8   0/rm32/EAX    .           .             .           .           4/disp8         .                 # push *(EAX+4)
-365     # . . call
-366     e8/call  check-ints-equal/disp32
-367     # . . discard args
-368     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
-369     # end
-370     c3/return
-371 
-372 test-skip-chars-not-matching-none:
-373     # setup
-374     # . clear-stream(_test-stream)
-375     # . . push args
-376     68/push  _test-stream/imm32
-377     # . . call
-378     e8/call  clear-stream/disp32
-379     # . . discard args
-380     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
-381     # write(_test-stream, " ab")
-382     # . . push args
-383     68/push  " ab"/imm32
-384     68/push  _test-stream/imm32
-385     # . . call
-386     e8/call  write/disp32
-387     # . . discard args
-388     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
-389     # skip-chars-not-matching(_test-stream, 0x20/space)
-390     # . . push args
-391     68/push  0x20/imm32
-392     68/push  _test-stream/imm32
-393     # . . call
-394     e8/call  skip-chars-not-matching/disp32
-395     # . . discard args
-396     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
-397     # check-ints-equal(_test-stream->read, 0, msg)
-398     # . . push args
-399     68/push  "F - test-skip-chars-not-matching-none"/imm32
-400     68/push  0/imm32
-401     # . . push *_test-stream->read
-402     b8/copy-to-EAX  _test-stream/imm32
-403     ff          6/subop/push        1/mod/*+disp8   0/rm32/EAX    .           .             .           .           4/disp8         .                 # push *(EAX+4)
-404     # . . call
-405     e8/call  check-ints-equal/disp32
-406     # . . discard args
-407     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
-408     # end
-409     c3/return
-410 
-411 test-skip-chars-not-matching-all:
-412     # setup
-413     # . clear-stream(_test-stream)
-414     # . . push args
-415     68/push  _test-stream/imm32
-416     # . . call
-417     e8/call  clear-stream/disp32
-418     # . . discard args
-419     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
-420     # write(_test-stream, "ab")
-421     # . . push args
-422     68/push  "ab"/imm32
-423     68/push  _test-stream/imm32
-424     # . . call
-425     e8/call  write/disp32
-426     # . . discard args
-427     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
-428     # skip-chars-not-matching(_test-stream, 0x20/space)
-429     # . . push args
-430     68/push  0x20/imm32
-431     68/push  _test-stream/imm32
-432     # . . call
-433     e8/call  skip-chars-not-matching/disp32
-434     # . . discard args
-435     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
-436     # check-ints-equal(_test-stream->read, 2, msg)
-437     # . . push args
-438     68/push  "F - test-skip-chars-not-matching-all"/imm32
-439     68/push  2/imm32
-440     # . . push *_test-stream->read
-441     b8/copy-to-EAX  _test-stream/imm32
-442     ff          6/subop/push        1/mod/*+disp8   0/rm32/EAX    .           .             .           .           4/disp8         .                 # push *(EAX+4)
-443     # . . call
-444     e8/call  check-ints-equal/disp32
-445     # . . discard args
-446     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
-447     # end
-448     c3/return
-449 
-450 # . . vim:nowrap:textwidth=0
-
- - - diff --git a/html/subx/069slice.subx.html b/html/subx/069slice.subx.html new file mode 100644 index 00000000..a959259d --- /dev/null +++ b/html/subx/069slice.subx.html @@ -0,0 +1,452 @@ + + + + +Mu - subx/069slice.subx + + + + + + + + + + +https://github.com/akkartik/mu/blob/master/subx/069slice.subx +
+  1 # new data structure: a slice is an open interval of addresses [start, end)
+  2 # that includes 'start' but not 'end'
+  3 
+  4 == code
+  5 #   instruction                     effective address                                                   register    displacement    immediate
+  6 # . op          subop               mod             rm32          base        index         scale       r32
+  7 # . 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
+  8 
+  9 # main:
+ 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 slice-empty?:  # s : (address slice) -> bool/EAX
+ 17     # . prolog
+ 18     55/push-EBP
+ 19     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+ 20     # . save registers
+ 21     51/push-ECX
+ 22     # ECX = s
+ 23     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           1/r32/ECX   8/disp8         .                 # copy *(EBP+8) to ECX
+ 24     # if s->start == s->end return true
+ 25     # . EAX = s->start
+ 26     8b/copy                         0/mod/indirect  1/rm32/ECX    .           .             .           0/r32/EAX   .               .                 # copy *ECX to EAX
+ 27     # . compare EAX with s->end
+ 28     39/compare                      1/mod/*+disp8   1/rm32/ECX    .           .             .           0/r32/EAX   4/disp8         .                 # compare EAX and *(ECX+4)
+ 29     b8/copy-to-EAX  1/imm32/false
+ 30     74/jump-if-equal  $slice-empty?:end/disp8
+ 31     b8/copy-to-EAX  0/imm32/false
+ 32 $slice-empty?:end:
+ 33     # . restore registers
+ 34     59/pop-to-ECX
+ 35     # . epilog
+ 36     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
+ 37     5d/pop-to-EBP
+ 38     c3/return
+ 39 
+ 40 test-slice-empty-true:
+ 41     # . prolog
+ 42     55/push-EBP
+ 43     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+ 44     # var slice/ECX = {34, 34}
+ 45     68/push  34/imm32/end
+ 46     68/push  34/imm32/start
+ 47     89/copy                         3/mod/direct    1/rm32/ECX    .           .             .           4/r32/ESP   .               .                 # copy ESP to ECX
+ 48     # slice-empty?(slice)
+ 49     # . . push args
+ 50     51/push-ECX
+ 51     # . . call
+ 52     e8/call  slice-empty?/disp32
+ 53     # . . discard args
+ 54     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+ 55     # check-ints-equal(EAX, 1, msg)
+ 56     # . . push args
+ 57     68/push  "F - test-slice-empty-true"/imm32
+ 58     68/push  1/imm32
+ 59     50/push-EAX
+ 60     # . . call
+ 61     e8/call  check-ints-equal/disp32
+ 62     # . . discard args
+ 63     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+ 64     # . epilog
+ 65     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
+ 66     5d/pop-to-EBP
+ 67     c3/return
+ 68 
+ 69 test-slice-empty-false:
+ 70     # . prolog
+ 71     55/push-EBP
+ 72     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+ 73     # var slice/ECX = {34, 23}
+ 74     68/push  23/imm32/end
+ 75     68/push  34/imm32/start
+ 76     89/copy                         3/mod/direct    1/rm32/ECX    .           .             .           4/r32/ESP   .               .                 # copy ESP to ECX
+ 77     # slice-empty?(slice)
+ 78     # . . push args
+ 79     51/push-ECX
+ 80     # . . call
+ 81     e8/call  slice-empty?/disp32
+ 82     # . . discard args
+ 83     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+ 84     # check-ints-equal(EAX, 0, msg)
+ 85     # . . push args
+ 86     68/push  "F - test-slice-empty-false"/imm32
+ 87     68/push  0/imm32
+ 88     50/push-EAX
+ 89     # . . call
+ 90     e8/call  check-ints-equal/disp32
+ 91     # . . discard args
+ 92     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+ 93     # . epilog
+ 94     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
+ 95     5d/pop-to-EBP
+ 96     c3/return
+ 97 
+ 98 slice-equal?:  # s : (address slice), k : (address kernel-string) -> bool/EAX
+ 99     # . prolog
+100     55/push-EBP
+101     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+102     # . save registers
+103     51/push-ECX
+104     52/push-EDX
+105     53/push-EBX
+106     56/push-ESI
+107     # EAX = ECX = false
+108     31/xor                          3/mod/direct    0/rm32/EAX    .           .             .           0/r32/EAX   .               .                 # clear EAX
+109     31/xor                          3/mod/direct    1/rm32/ECX    .           .             .           1/r32/ECX   .               .                 # clear ECX
+110     # ESI = s
+111     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           6/r32/ESI   8/disp8         .                 # copy *(EBP+8) to ESI
+112     # curr/EDX = s->start
+113     8b/copy                         0/mod/indirect  6/rm32/ESI    .           .             .           2/r32/EDX   .               .                 # copy *ESI to EDX
+114     # max/ESI = s->end
+115     8b/copy                         1/mod/*+disp8   6/rm32/ESI    .           .             .           6/r32/ESI   4/disp8         .                 # copy *(ESI+4) to ESI
+116     # EBX = k
+117     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           3/r32/EBX   0xc/disp8       .                 # copy *(EBP+12) to EBX
+118 $slice-equal?:loop:
+119     # AL = *k
+120     8a/copy-byte                    0/mod/indirect  3/rm32/EBX    .           .             .           0/r32/AL    .               .                 # copy byte at *EBX to AL
+121     # if (curr >= max) return *k == 0
+122     39/compare                      3/mod/direct    2/rm32/EDX    .           .             .           6/r32/ESI   .               .                 # compare EDX and ESI
+123     7c/jump-if-lesser  $slice-equal?:check2/disp8
+124     3d/compare-with-EAX  0/imm32
+125     74/jump-if-equal  $slice-equal?:true/disp8
+126     eb/jump  $slice-equal?:false/disp8
+127 $slice-equal?:check2:
+128     # if (EAX == 0) return false
+129     3d/compare-with-EAX  0/imm32
+130     74/jump-if-equal  $slice-equal?:false/disp8
+131     # CL = *curr
+132     8a/copy-byte                    0/mod/indirect  2/rm32/EDX    .           .             .           1/r32/CL    .               .                 # copy byte at *EDX to CL
+133     # if (EAX != ECX) return false
+134     39/compare                      3/mod/direct    0/rm32/EAX    .           .             .           1/r32/ECX   .               .                 # compare EAX and ECX
+135     75/jump-if-not-equal  $slice-equal?:false/disp8
+136     # ++k
+137     43/increment-EBX
+138     # ++curr
+139     42/increment-EDX
+140     eb/jump $slice-equal?:loop/disp8
+141 $slice-equal?:false:
+142     b8/copy-to-EAX  0/imm32
+143     eb/jump  $slice-equal?:end/disp8
+144 $slice-equal?:true:
+145     b8/copy-to-EAX  1/imm32
+146 $slice-equal?:end:
+147     # . restore registers
+148     5e/pop-to-ESI
+149     5b/pop-to-EBX
+150     5a/pop-to-EDX
+151     59/pop-to-ECX
+152     # . epilog
+153     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
+154     5d/pop-to-EBP
+155     c3/return
+156 
+157 test-slice-equal:
+158     # - slice-equal?(slice("Abc"), "Abc") == 1
+159     # . prolog
+160     55/push-EBP
+161     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+162     # var slice/ECX
+163     68/push  _test-slice-data-3/imm32/end
+164     68/push  _test-slice-data-0/imm32/start
+165     89/copy                         3/mod/direct    1/rm32/ECX    .           .             .           4/r32/ESP   .               .                 # copy ESP to ECX
+166     # EAX = slice-equal?(ECX, "Abc")
+167     # . . push args
+168     68/push  _test-Abc-kernel-string/imm32
+169     51/push-ECX
+170     # . . call
+171     e8/call  slice-equal?/disp32
+172     # . . discard args
+173     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+174     # check-ints-equal(EAX, 1, msg)
+175     # . . push args
+176     68/push  "F - test-slice-equal"/imm32
+177     68/push  1/imm32
+178     50/push-EAX
+179     # . . call
+180     e8/call  check-ints-equal/disp32
+181     # . . discard args
+182     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+183     # . epilog
+184     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
+185     5d/pop-to-EBP
+186     c3/return
+187 
+188 test-slice-equal-false:
+189     # - slice-equal?(slice("bcd"), "Abc") == 0
+190     # . prolog
+191     55/push-EBP
+192     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+193     # var slice/ECX
+194     68/push  _test-slice-data-4/imm32/end
+195     68/push  _test-slice-data-1/imm32/start
+196     89/copy                         3/mod/direct    1/rm32/ECX    .           .             .           4/r32/ESP   .               .                 # copy ESP to ECX
+197     # EAX = slice-equal?(ECX, "Abc")
+198     # . . push args
+199     68/push  _test-Abc-kernel-string/imm32
+200     51/push-ECX
+201     # . . call
+202     e8/call  slice-equal?/disp32
+203     # . . discard args
+204     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+205     # check-ints-equal(EAX, 0, msg)
+206     # . . push args
+207     68/push  "F - test-slice-equal-false"/imm32
+208     68/push  0/imm32
+209     50/push-EAX
+210     # . . call
+211     e8/call  check-ints-equal/disp32
+212     # . . discard args
+213     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+214     # . epilog
+215     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
+216     5d/pop-to-EBP
+217     c3/return
+218 
+219 test-slice-equal-too-long:
+220     # - slice-equal?(slice("Abcd"), "Abc") == 0
+221     # . prolog
+222     55/push-EBP
+223     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+224     # var slice/ECX
+225     68/push  _test-slice-data-4/imm32/end
+226     68/push  _test-slice-data-0/imm32/start
+227     89/copy                         3/mod/direct    1/rm32/ECX    .           .             .           4/r32/ESP   .               .                 # copy ESP to ECX
+228     # EAX = slice-equal?(ECX, "Abc")
+229     # . . push args
+230     68/push  _test-Abc-kernel-string/imm32
+231     51/push-ECX
+232     # . . call
+233     e8/call  slice-equal?/disp32
+234     # . . discard args
+235     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+236     # check-ints-equal(EAX, 0, msg)
+237     # . . push args
+238     68/push  "F - test-slice-equal-too-long"/imm32
+239     68/push  0/imm32
+240     50/push-EAX
+241     # . . call
+242     e8/call  check-ints-equal/disp32
+243     # . . discard args
+244     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+245     # . epilog
+246     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
+247     5d/pop-to-EBP
+248     c3/return
+249 
+250 test-slice-equal-too-short:
+251     # - slice-equal?(slice("A"), "Abc") == 0
+252     # . prolog
+253     55/push-EBP
+254     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+255     # var slice/ECX
+256     68/push  _test-slice-data-1/imm32/end
+257     68/push  _test-slice-data-0/imm32/start
+258     89/copy                         3/mod/direct    1/rm32/ECX    .           .             .           4/r32/ESP   .               .                 # copy ESP to ECX
+259     # EAX = slice-equal?(ECX, "Abc")
+260     # . . push args
+261     68/push  _test-Abc-kernel-string/imm32
+262     51/push-ECX
+263     # . . call
+264     e8/call  slice-equal?/disp32
+265     # . . discard args
+266     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+267     # check-ints-equal(EAX, 0, msg)
+268     # . . push args
+269     68/push  "F - test-slice-equal-too-short"/imm32
+270     68/push  0/imm32
+271     50/push-EAX
+272     # . . call
+273     e8/call  check-ints-equal/disp32
+274     # . . discard args
+275     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+276     # . epilog
+277     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
+278     5d/pop-to-EBP
+279     c3/return
+280 
+281 test-slice-equal-empty:
+282     # - slice-equal?(slice(""), "Abc") == 0
+283     # . prolog
+284     55/push-EBP
+285     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+286     # var slice/ECX
+287     68/push  _test-slice-data-0/imm32/end
+288     68/push  _test-slice-data-0/imm32/start
+289     89/copy                         3/mod/direct    1/rm32/ECX    .           .             .           4/r32/ESP   .               .                 # copy ESP to ECX
+290     # EAX = slice-equal?(ECX, "Abc")
+291     # . . push args
+292     68/push  _test-Abc-kernel-string/imm32
+293     51/push-ECX
+294     # . . call
+295     e8/call  slice-equal?/disp32
+296     # . . discard args
+297     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+298     # check-ints-equal(EAX, 0, msg)
+299     # . . push args
+300     68/push  "F - test-slice-equal-empty"/imm32
+301     68/push  0/imm32
+302     50/push-EAX
+303     # . . call
+304     e8/call  check-ints-equal/disp32
+305     # . . discard args
+306     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+307     # . epilog
+308     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
+309     5d/pop-to-EBP
+310     c3/return
+311 
+312 test-slice-equal-with-empty:
+313     # - slice-equal?(slice("Ab"), "") == 0
+314     # . prolog
+315     55/push-EBP
+316     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+317     # var slice/ECX
+318     68/push  _test-slice-data-2/imm32/end
+319     68/push  _test-slice-data-0/imm32/start
+320     89/copy                         3/mod/direct    1/rm32/ECX    .           .             .           4/r32/ESP   .               .                 # copy ESP to ECX
+321     # EAX = slice-equal?(ECX, "")
+322     # . . push args
+323     68/push  Null-kernel-string/imm32
+324     51/push-ECX
+325     # . . call
+326     e8/call  slice-equal?/disp32
+327     # . . discard args
+328     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+329     # check-ints-equal(EAX, 0, msg)
+330     # . . push args
+331     68/push  "F - test-slice-equal-with-empty"/imm32
+332     68/push  0/imm32
+333     50/push-EAX
+334     # . . call
+335     e8/call  check-ints-equal/disp32
+336     # . . discard args
+337     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+338     # . epilog
+339     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
+340     5d/pop-to-EBP
+341     c3/return
+342 
+343 test-slice-equal-empty-with-empty:
+344     # - slice-equal?(slice(""), "") == 1
+345     # . prolog
+346     55/push-EBP
+347     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+348     # var slice/ECX
+349     68/push  _test-slice-data-0/imm32/end
+350     68/push  _test-slice-data-0/imm32/start
+351     89/copy                         3/mod/direct    1/rm32/ECX    .           .             .           4/r32/ESP   .               .                 # copy ESP to ECX
+352     # EAX = slice-equal?(ECX, "")
+353     # . . push args
+354     68/push  Null-kernel-string/imm32
+355     51/push-ECX
+356     # . . call
+357     e8/call  slice-equal?/disp32
+358     # . . discard args
+359     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+360     # check-ints-equal(EAX, 1, msg)
+361     # . . push args
+362     68/push  "F - test-slice-equal-empty-with-empty"/imm32
+363     68/push  1/imm32
+364     50/push-EAX
+365     # . . call
+366     e8/call  check-ints-equal/disp32
+367     # . . discard args
+368     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+369     # . epilog
+370     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
+371     5d/pop-to-EBP
+372     c3/return
+373 
+374 == data
+375 
+376 _test-slice-data-0:
+377     41/A
+378 _test-slice-data-1:
+379     62/b
+380 _test-slice-data-2:
+381     63/c
+382 _test-slice-data-3:
+383     64/d
+384 _test-slice-data-4:
+385 
+386 # . . vim:nowrap:textwidth=0
+
+ + + diff --git a/html/subx/070next-token.subx.html b/html/subx/070next-token.subx.html new file mode 100644 index 00000000..fa6a82c9 --- /dev/null +++ b/html/subx/070next-token.subx.html @@ -0,0 +1,512 @@ + + + + +Mu - subx/070next-token.subx + + + + + + + + + + +https://github.com/akkartik/mu/blob/master/subx/070next-token.subx +
+  1 == code
+  2 #   instruction                     effective address                                                   register    displacement    immediate
+  3 # . op          subop               mod             rm32          base        index         scale       r32
+  4 # . 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
+  5 
+  6 # main:
+  7     e8/call  run-tests/disp32  # 'run-tests' is a function created automatically by SubX. It calls all functions that start with 'test-'.
+  8     # syscall(exit, Num-test-failures)
+  9     8b/copy                         0/mod/indirect  5/rm32/.disp32            .             .           3/r32/EBX   Num-test-failures/disp32          # copy *Num-test-failures to EBX
+ 10     b8/copy-to-EAX  1/imm32/exit
+ 11     cd/syscall  0x80/imm8
+ 12 
+ 13 # extract the next run of characters that are different from a given 'delimiter'
+ 14 # on eof return an empty interval
+ 15 next-token:  # in : (address stream), delimiter : byte, out : (address slice)
+ 16     # . prolog
+ 17     55/push-EBP
+ 18     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+ 19     # . save registers
+ 20     50/push-EAX
+ 21     51/push-ECX
+ 22     56/push-ESI
+ 23     57/push-EDI
+ 24     # ESI = in
+ 25     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           6/r32/ESI   8/disp8         .                 # copy *(EBP+8) to ESI
+ 26     # EDI = out
+ 27     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           7/r32/EDI   0x10/disp8      .                 # copy *(EBP+16) to EDI
+ 28     # skip-chars-matching(in, delimiter)
+ 29     # . . push args
+ 30     ff          6/subop/push        1/mod/*+disp8   5/rm32/EBP    .           .             .           .           0xc/disp8       .                 # push *(EBP+12)
+ 31     ff          6/subop/push        1/mod/*+disp8   5/rm32/EBP    .           .             .           .           8/disp8         .                 # push *(EBP+8)
+ 32     # . . call
+ 33     e8/call  skip-chars-matching/disp32
+ 34     # . . discard args
+ 35     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+ 36     # out->start = &in->data[in->read]
+ 37     8b/copy                         1/mod/*+disp8   6/rm32/ESI    .           .             .           1/r32/ECX   4/disp8         .                 # copy *(ESI+4) to ECX
+ 38     8d/copy-address                 1/mod/*+disp8   4/rm32/sib    6/base/ESI  1/index/ECX   .           0/r32/EAX   0xc/disp8       .                 # copy ESI+ECX+12 to EAX
+ 39     89/copy                         0/mod/indirect  7/rm32/EDI    .           .             .           0/r32/EAX   .               .                 # copy EAX to *EDI
+ 40     # skip-chars-not-matching(in, delimiter)
+ 41     # . . push args
+ 42     ff          6/subop/push        1/mod/*+disp8   5/rm32/EBP    .           .             .           .           0xc/disp8       .                 # push *(EBP+12)
+ 43     ff          6/subop/push        1/mod/*+disp8   5/rm32/EBP    .           .             .           .           8/disp8         .                 # push *(EBP+8)
+ 44     # . . call
+ 45     e8/call  skip-chars-not-matching/disp32
+ 46     # . . discard args
+ 47     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+ 48     # out->end = &in->data[in->read]
+ 49     8b/copy                         1/mod/*+disp8   6/rm32/ESI    .           .             .           1/r32/ECX   4/disp8         .                 # copy *(ESI+4) to ECX
+ 50     8d/copy-address                 1/mod/*+disp8   4/rm32/sib    6/base/ESI  1/index/ECX   .           0/r32/EAX   0xc/disp8       .                 # copy ESI+ECX+12 to EAX
+ 51     89/copy                         1/mod/*+disp8   7/rm32/EDI    .           .             .           0/r32/EAX   4/disp8         .                 # copy EAX to *(EDI+4)
+ 52     # . restore registers
+ 53     5f/pop-to-EDI
+ 54     5e/pop-to-ESI
+ 55     59/pop-to-ECX
+ 56     58/pop-to-EAX
+ 57     # . epilog
+ 58     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
+ 59     5d/pop-to-EBP
+ 60     c3/return
+ 61 
+ 62 test-next-token:
+ 63     # . prolog
+ 64     55/push-EBP
+ 65     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+ 66     # setup
+ 67     # . clear-stream(_test-stream)
+ 68     # . . push args
+ 69     68/push  _test-stream/imm32
+ 70     # . . call
+ 71     e8/call  clear-stream/disp32
+ 72     # . . discard args
+ 73     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+ 74     # var slice/ECX = {0, 0}
+ 75     68/push  0/imm32/end
+ 76     68/push  0/imm32/start
+ 77     89/copy                         3/mod/direct    1/rm32/ECX    .           .             .           4/r32/ESP   .               .                 # copy ESP to ECX
+ 78     # write(_test-stream, "  ab")
+ 79     # . . push args
+ 80     68/push  "  ab"/imm32
+ 81     68/push  _test-stream/imm32
+ 82     # . . call
+ 83     e8/call  write/disp32
+ 84     # . . discard args
+ 85     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+ 86     # next-token(_test-stream, 0x20/space, slice)
+ 87     # . . push args
+ 88     51/push-ECX
+ 89     68/push  0x20/imm32
+ 90     68/push  _test-stream/imm32
+ 91     # . . call
+ 92     e8/call  next-token/disp32
+ 93     # . . discard args
+ 94     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+ 95     # check-ints-equal(slice->start - _test-stream->data, 2, msg)
+ 96     # . check-ints-equal(slice->start - _test-stream, 14, msg)
+ 97     # . . push args
+ 98     68/push  "F - test-next-token: start"/imm32
+ 99     68/push  0xe/imm32
+100     # . . push slice->start - _test-stream
+101     8b/copy                         0/mod/indirect  1/rm32/ECX    .           .             .           0/r32/EAX   .               .                 # copy *ECX to EAX
+102     81          5/subop/subtract    3/mod/direct    0/rm32/EAX    .           .             .           .           .               _test-stream/imm32 # subtract from EAX
+103     50/push-EAX
+104     # . . call
+105     e8/call  check-ints-equal/disp32
+106     # . . discard args
+107     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+108     # check-ints-equal(slice->end - _test-stream->data, 4, msg)
+109     # . check-ints-equal(slice->end - _test-stream, 16, msg)
+110     # . . push args
+111     68/push  "F - test-next-token: end"/imm32
+112     68/push  0x10/imm32
+113     # . . push slice->end - _test-stream
+114     8b/copy                         1/mod/*+disp8   1/rm32/ECX    .           .             .           0/r32/EAX   4/disp8         .                 # copy *(ECX+4) to EAX
+115     81          5/subop/subtract    3/mod/direct    0/rm32/EAX    .           .             .           .           .               _test-stream/imm32 # subtract from EAX
+116     50/push-EAX
+117     # . . call
+118     e8/call  check-ints-equal/disp32
+119     # . . discard args
+120     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+121     # . epilog
+122     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
+123     5d/pop-to-EBP
+124     c3/return
+125 
+126 test-next-token-eof:
+127     # . prolog
+128     55/push-EBP
+129     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+130     # setup
+131     # . clear-stream(_test-stream)
+132     # . . push args
+133     68/push  _test-stream/imm32
+134     # . . call
+135     e8/call  clear-stream/disp32
+136     # . . discard args
+137     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+138     # var slice/ECX = {0, 0}
+139     68/push  0/imm32/end
+140     68/push  0/imm32/start
+141     89/copy                         3/mod/direct    1/rm32/ECX    .           .             .           4/r32/ESP   .               .                 # copy ESP to ECX
+142     # write nothing to _test-stream
+143     # next-token(_test-stream, 0x20/space, slice)
+144     # . . push args
+145     51/push-ECX
+146     68/push  0x20/imm32
+147     68/push  _test-stream/imm32
+148     # . . call
+149     e8/call  next-token/disp32
+150     # . . discard args
+151     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+152     # check-ints-equal(slice->end, slice->start, msg)
+153     # . . push args
+154     68/push  "F - test-next-token-eof"/imm32
+155     ff          6/subop/push        1/mod/*+disp8   1/rm32/ECX    .           .             .           .           4/disp8         .                 # push *(ECX+4)
+156     ff          6/subop/push        0/mod/indirect  1/rm32/ECX    .           .             .           .           .               .                 # push *ECX
+157     # . . call
+158     e8/call  check-ints-equal/disp32
+159     # . . discard args
+160     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+161     # . epilog
+162     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
+163     5d/pop-to-EBP
+164     c3/return
+165 
+166 skip-chars-matching:  # in : (address stream), delimiter : byte
+167     # . prolog
+168     55/push-EBP
+169     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+170     # . save registers
+171     50/push-EAX
+172     51/push-ECX
+173     52/push-EDX
+174     56/push-ESI
+175     # ESI = in
+176     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           6/r32/ESI   8/disp8         .                 # copy *(EBP+8) to ESI
+177     # ECX = in->read
+178     8b/copy                         1/mod/*+disp8   6/rm32/ESI    .           .             .           1/r32/ECX   4/disp8         .                 # copy *(ESI+4) to ECX
+179     # EBX = in->write
+180     8b/copy                         0/mod/indirect  6/rm32/ESI    .           .             .           3/r32/EBX   .               .                 # copy *ESI to EBX
+181     # EDX = delimiter
+182     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           2/r32/EDX   0xc/disp8       .                 # copy *(EBP+12) to EDX
+183 $skip-chars-matching:loop:
+184     # if (in->read >= in->write) break
+185     3b/compare                      3/mod/direct    3/rm32/EBX    .           .             .           1/r32/ECX   .               .                 # compare ECX with *EBX
+186     7d/jump-if-greater-or-equal  $skip-chars-matching:end/disp8
+187     # EAX = in->data[in->read]
+188     31/xor                          3/mod/direct    0/rm32/EAX    .           .             .           0/r32/EAX   .               .                 # clear EAX
+189     8a/copy-byte                    1/mod/*+disp8   4/rm32/sib    6/base/ESI  1/index/ECX   .           0/r32/AL    0xc/disp8       .                 # copy byte at *(ESI+ECX+12) to AL
+190     # if (EAX != delimiter) break
+191     39/compare                      3/mod/direct    0/rm32/EAX    .           .             .           2/r32/EDX   .               .                 # compare EAX and EDX
+192     75/jump-if-not-equal  $skip-chars-matching:end/disp8
+193     # ++in->read
+194     41/inc-ECX
+195     eb/jump  $skip-chars-matching:loop/disp8
+196 $skip-chars-matching:end:
+197     # persist in->read
+198     89/copy                         1/mod/*+disp8   6/rm32/ESI    .           .             .           1/r32/ECX   4/disp8         .                 # copy ECX to *(ESI+4)
+199     # . restore registers
+200     5e/pop-to-ESI
+201     5a/pop-to-EDX
+202     59/pop-to-ECX
+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-skip-chars-matching:
+210     # setup
+211     # . clear-stream(_test-stream)
+212     # . . push args
+213     68/push  _test-stream/imm32
+214     # . . call
+215     e8/call  clear-stream/disp32
+216     # . . discard args
+217     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+218     # write(_test-stream, "  ab")
+219     # . . push args
+220     68/push  "  ab"/imm32
+221     68/push  _test-stream/imm32
+222     # . . call
+223     e8/call  write/disp32
+224     # . . discard args
+225     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+226     # skip-chars-matching(_test-stream, 0x20/space)
+227     # . . push args
+228     68/push  0x20/imm32
+229     68/push  _test-stream/imm32
+230     # . . call
+231     e8/call  skip-chars-matching/disp32
+232     # . . discard args
+233     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+234     # check-ints-equal(_test-stream->read, 2, msg)
+235     # . . push args
+236     68/push  "F - test-skip-chars-matching"/imm32
+237     68/push  2/imm32
+238     # . . push *_test-stream->read
+239     b8/copy-to-EAX  _test-stream/imm32
+240     ff          6/subop/push        1/mod/*+disp8   0/rm32/EAX    .           .             .           .           4/disp8         .                 # push *(EAX+4)
+241     # . . call
+242     e8/call  check-ints-equal/disp32
+243     # . . discard args
+244     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+245     # end
+246     c3/return
+247 
+248 test-skip-chars-matching-none:
+249     # setup
+250     # . clear-stream(_test-stream)
+251     # . . push args
+252     68/push  _test-stream/imm32
+253     # . . call
+254     e8/call  clear-stream/disp32
+255     # . . discard args
+256     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+257     # write(_test-stream, "ab")
+258     # . . push args
+259     68/push  "ab"/imm32
+260     68/push  _test-stream/imm32
+261     # . . call
+262     e8/call  write/disp32
+263     # . . discard args
+264     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+265     # skip-chars-matching(_test-stream, 0x20/space)
+266     # . . push args
+267     68/push  0x20/imm32
+268     68/push  _test-stream/imm32
+269     # . . call
+270     e8/call  skip-chars-matching/disp32
+271     # . . discard args
+272     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+273     # check-ints-equal(_test-stream->read, 0, msg)
+274     # . . push args
+275     68/push  "F - test-skip-chars-matching-none"/imm32
+276     68/push  0/imm32
+277     # . . push *_test-stream->read
+278     b8/copy-to-EAX  _test-stream/imm32
+279     ff          6/subop/push        1/mod/*+disp8   0/rm32/EAX    .           .             .           .           4/disp8         .                 # push *(EAX+4)
+280     # . . call
+281     e8/call  check-ints-equal/disp32
+282     # . . discard args
+283     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+284     # end
+285     c3/return
+286 
+287 # minor fork of 'skip-chars-matching'
+288 skip-chars-not-matching:  # in : (address stream), delimiter : byte
+289     # . prolog
+290     55/push-EBP
+291     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+292     # . save registers
+293     50/push-EAX
+294     51/push-ECX
+295     52/push-EDX
+296     56/push-ESI
+297     # ESI = in
+298     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           6/r32/ESI   8/disp8         .                 # copy *(EBP+8) to ESI
+299     # ECX = in->read
+300     8b/copy                         1/mod/*+disp8   6/rm32/ESI    .           .             .           1/r32/ECX   4/disp8         .                 # copy *(ESI+4) to ECX
+301     # EBX = in->write
+302     8b/copy                         0/mod/indirect  6/rm32/ESI    .           .             .           3/r32/EBX   .               .                 # copy *ESI to EBX
+303     # EDX = delimiter
+304     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           2/r32/EDX   0xc/disp8       .                 # copy *(EBP+12) to EDX
+305 $skip-chars-not-matching:loop:
+306     # if (in->read >= in->write) break
+307     3b/compare                      3/mod/direct    3/rm32/EBX    .           .             .           1/r32/ECX   .               .                 # compare ECX with *EBX
+308     7d/jump-if-greater-or-equal  $skip-chars-not-matching:end/disp8
+309     # EAX = in->data[in->read]
+310     31/xor                          3/mod/direct    0/rm32/EAX    .           .             .           0/r32/EAX   .               .                 # clear EAX
+311     8a/copy-byte                    1/mod/*+disp8   4/rm32/sib    6/base/ESI  1/index/ECX   .           0/r32/AL    0xc/disp8       .                 # copy byte at *(ESI+ECX+12) to AL
+312     # if (EAX == delimiter) break
+313     39/compare                      3/mod/direct    0/rm32/EAX    .           .             .           2/r32/EDX   .               .                 # compare EAX and EDX
+314     74/jump-if-equal  $skip-chars-not-matching:end/disp8
+315     # ++in->read
+316     41/inc-ECX
+317     eb/jump  $skip-chars-not-matching:loop/disp8
+318 $skip-chars-not-matching:end:
+319     # persist in->read
+320     89/copy                         1/mod/*+disp8   6/rm32/ESI    .           .             .           1/r32/ECX   4/disp8         .                 # copy ECX to *(ESI+4)
+321     # . restore registers
+322     5e/pop-to-ESI
+323     5a/pop-to-EDX
+324     59/pop-to-ECX
+325     58/pop-to-EAX
+326     # . epilog
+327     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
+328     5d/pop-to-EBP
+329     c3/return
+330 
+331 test-skip-chars-not-matching:
+332     # setup
+333     # . clear-stream(_test-stream)
+334     # . . push args
+335     68/push  _test-stream/imm32
+336     # . . call
+337     e8/call  clear-stream/disp32
+338     # . . discard args
+339     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+340     # write(_test-stream, "ab ")
+341     # . . push args
+342     68/push  "ab "/imm32
+343     68/push  _test-stream/imm32
+344     # . . call
+345     e8/call  write/disp32
+346     # . . discard args
+347     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+348     # skip-chars-not-matching(_test-stream, 0x20/space)
+349     # . . push args
+350     68/push  0x20/imm32
+351     68/push  _test-stream/imm32
+352     # . . call
+353     e8/call  skip-chars-not-matching/disp32
+354     # . . discard args
+355     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+356     # check-ints-equal(_test-stream->read, 2, msg)
+357     # . . push args
+358     68/push  "F - test-skip-chars-not-matching"/imm32
+359     68/push  2/imm32
+360     # . . push *_test-stream->read
+361     b8/copy-to-EAX  _test-stream/imm32
+362     ff          6/subop/push        1/mod/*+disp8   0/rm32/EAX    .           .             .           .           4/disp8         .                 # push *(EAX+4)
+363     # . . call
+364     e8/call  check-ints-equal/disp32
+365     # . . discard args
+366     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+367     # end
+368     c3/return
+369 
+370 test-skip-chars-not-matching-none:
+371     # setup
+372     # . clear-stream(_test-stream)
+373     # . . push args
+374     68/push  _test-stream/imm32
+375     # . . call
+376     e8/call  clear-stream/disp32
+377     # . . discard args
+378     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+379     # write(_test-stream, " ab")
+380     # . . push args
+381     68/push  " ab"/imm32
+382     68/push  _test-stream/imm32
+383     # . . call
+384     e8/call  write/disp32
+385     # . . discard args
+386     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+387     # skip-chars-not-matching(_test-stream, 0x20/space)
+388     # . . push args
+389     68/push  0x20/imm32
+390     68/push  _test-stream/imm32
+391     # . . call
+392     e8/call  skip-chars-not-matching/disp32
+393     # . . discard args
+394     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+395     # check-ints-equal(_test-stream->read, 0, msg)
+396     # . . push args
+397     68/push  "F - test-skip-chars-not-matching-none"/imm32
+398     68/push  0/imm32
+399     # . . push *_test-stream->read
+400     b8/copy-to-EAX  _test-stream/imm32
+401     ff          6/subop/push        1/mod/*+disp8   0/rm32/EAX    .           .             .           .           4/disp8         .                 # push *(EAX+4)
+402     # . . call
+403     e8/call  check-ints-equal/disp32
+404     # . . discard args
+405     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+406     # end
+407     c3/return
+408 
+409 test-skip-chars-not-matching-all:
+410     # setup
+411     # . clear-stream(_test-stream)
+412     # . . push args
+413     68/push  _test-stream/imm32
+414     # . . call
+415     e8/call  clear-stream/disp32
+416     # . . discard args
+417     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+418     # write(_test-stream, "ab")
+419     # . . push args
+420     68/push  "ab"/imm32
+421     68/push  _test-stream/imm32
+422     # . . call
+423     e8/call  write/disp32
+424     # . . discard args
+425     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+426     # skip-chars-not-matching(_test-stream, 0x20/space)
+427     # . . push args
+428     68/push  0x20/imm32
+429     68/push  _test-stream/imm32
+430     # . . call
+431     e8/call  skip-chars-not-matching/disp32
+432     # . . discard args
+433     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+434     # check-ints-equal(_test-stream->read, 2, msg)
+435     # . . push args
+436     68/push  "F - test-skip-chars-not-matching-all"/imm32
+437     68/push  2/imm32
+438     # . . push *_test-stream->read
+439     b8/copy-to-EAX  _test-stream/imm32
+440     ff          6/subop/push        1/mod/*+disp8   0/rm32/EAX    .           .             .           .           4/disp8         .                 # push *(EAX+4)
+441     # . . call
+442     e8/call  check-ints-equal/disp32
+443     # . . discard args
+444     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+445     # end
+446     c3/return
+447 
+448 # . . vim:nowrap:textwidth=0
+
+ + + diff --git a/html/subx/apps/hex.subx.html b/html/subx/apps/hex.subx.html index 2980f7e8..01eb2cda 100644 --- a/html/subx/apps/hex.subx.html +++ b/html/subx/apps/hex.subx.html @@ -104,1675 +104,1669 @@ if ('onhashchange' in window) { 41 3d/compare-EAX 1/imm32 42 75/jump-if-not-equal $run-main/disp8 43 # . run-tests() - 44 #? e8/call test-hex-below-0/disp32 - 45 #? e8/call test-scan-next-byte/disp32 - 46 #? e8/call test-scan-next-byte-handles-eof/disp32 - 47 #? e8/call test-scan-next-byte-skips-comment/disp32 - 48 #? e8/call test-scan-next-byte-aborts-on-invalid-byte/disp32 - 49 #? e8/call test-convert-next-octet/disp32 - 50 e8/call run-tests/disp32 - 51 8b/copy 0/mod/indirect 5/rm32/.disp32 . . 3/r32/EBX Num-test-failures/disp32 # copy *Num-test-failures to EBX - 52 eb/jump $main:end/disp8 - 53 $run-main: - 54 # - otherwise convert stdin - 55 # var ed/EAX : exit-descriptor - 56 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP - 57 89/copy 3/mod/direct 0/rm32/EAX . . . 4/r32/ESP . . # copy ESP to EAX - 58 # configure ed to really exit() - 59 # . ed->target = 0 - 60 c7 0/subop/copy 0/mod/direct 0/rm32/EAX . . . . . 0/imm32 # copy to *EAX - 61 # return convert(Stdin, 1/stdout, 2/stderr, ed) - 62 # . . push args - 63 50/push-EAX/ed - 64 68/push Stderr/imm32 - 65 68/push Stdout/imm32 - 66 68/push Stdin/imm32 - 67 # . . call - 68 e8/call convert/disp32 - 69 # . . discard args - 70 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP - 71 # . syscall(exit, 0) - 72 bb/copy-to-EBX 0/imm32 - 73 $main:end: - 74 b8/copy-to-EAX 1/imm32/exit - 75 cd/syscall 0x80/imm8 - 76 - 77 # the main entry point - 78 convert: # in : (address buffered-file), out : (address buffered-file), err : (address buffered-file), ed : (address exit-descriptor) -> <void> - 79 # pseudocode: - 80 # repeatedly - 81 # EAX = convert-next-octet(in, err, ed) - 82 # if EAX == 0xffffffff break # eof - 83 # write-byte(out, AL) - 84 # flush(out) - 85 # - 86 # . prolog - 87 55/push-EBP - 88 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP - 89 # . save registers - 90 50/push-EAX - 91 $convert:loop: - 92 # EAX = convert-next-octet(in, err, ed) - 93 # . . push args - 94 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0x14/disp8 . # push *(EBP+20) - 95 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0x10/disp8 . # push *(EBP+16) - 96 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) - 97 # . . call - 98 e8/call convert-next-octet/disp32 - 99 # . . discard first 2 args - 100 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 101 # if EAX == 0xffffffff break - 102 81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0xffffffff/imm32 # compare EAX - 103 74/jump-if-equal $convert:loop-end/disp8 - 104 # write-byte(out, AL) - 105 # . . push args - 106 50/push-EAX - 107 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) - 108 # . . call - 109 e8/call write-byte/disp32 - 110 # . . discard args - 111 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 112 # loop - 113 eb/jump $convert:loop/disp8 - 114 $convert:loop-end: - 115 # flush(out) - 116 # . . push args - 117 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) - 118 # . . call - 119 e8/call flush/disp32 - 120 # . . discard args - 121 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 122 $convert:end: - 123 # . restore registers - 124 58/pop-to-EAX - 125 # . epilog - 126 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP - 127 5d/pop-to-EBP - 128 c3/return - 129 - 130 # read bytes from 'in' until a sequence of two lowercase hex (0-9, a-f) bytes - 131 # skip spaces and newlines - 132 # on '#' skip bytes until newline - 133 # raise an error and abort on all other unexpected bytes - 134 # return in EAX an _octet_ containing the binary value of the two hex characters - 135 # return 0xffffffff on end of file - 136 convert-next-octet: # in : (address buffered-file), err : (address buffered-file), ed : (address exit-descriptor) -> byte-or-eof/EAX - 137 # pseudocode: - 138 # EAX = scan-next-byte(in, err, ed) - 139 # if (EAX == 0xffffffff) return - 140 # ECX = parse-hex-digit(EAX) - 141 # EAX = scan-next-byte(in, err, ed) - 142 # if (EAX == 0xffffffff) error("partial byte found.") - 143 # EAX = parse-hex-digit(EAX) - 144 # EAX = (ECX << 4) | EAX - 145 # return - 146 # - 147 # . prolog - 148 55/push-EBP - 149 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP - 150 # . save registers - 151 51/push-ECX - 152 # EAX = scan-next-byte(in, err, ed) - 153 # . . push args - 154 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0x10/disp8 . # push *(EBP+16) - 155 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) - 156 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) - 157 # . . call - 158 e8/call scan-next-byte/disp32 - 159 # . . discard args - 160 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 161 # if (EAX == 0xffffffff) return - 162 81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0xffffffff/imm32 # compare EAX - 163 74/jump-if-equal $convert-next-octet:end/disp8 - 164 # EAX = parse-hex-digit(EAX) - 165 e8/call parse-hex-digit/disp32 - 166 # ECX = EAX - 167 89/copy 3/mod/direct 1/rm32/ECX . . . 0/r32/EAX . . # copy EAX to ECX - 168 # EAX = scan-next-byte(in, err, ed) - 169 # . . push args - 170 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0x10/disp8 . # push *(EBP+16) - 171 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) - 172 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) - 173 # . . call - 174 e8/call scan-next-byte/disp32 - 175 # . . discard args - 176 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 177 # if (EAX == 0xffffffff) error(ed, err, "partial byte found.") - 178 81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0xffffffff/imm32 # compare EAX - 179 75/jump-if-not-equal $convert-next-octet:convert/disp8 - 180 # . error-byte(ed, err, msg, '.') # reusing error-byte to avoid creating _yet_ another helper - 181 # . . push args - 182 68/push 0x2e/imm32/period/dummy - 183 68/push "convert-next-octet: partial byte found"/imm32 - 184 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) - 185 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0x10/disp8 . # push *(EBP+16) - 186 # . . call - 187 e8/call error-byte/disp32 # never returns - 188 $convert-next-octet:convert: - 189 # EAX = parse-hex-digit(EAX) - 190 e8/call parse-hex-digit/disp32 - 191 # EAX = (ECX << 4) | EAX - 192 # . ECX <<= 4 - 193 c1/shift 4/subop/left 3/mod/direct 1/rm32/ECX . . . . . 4/imm8 # shift ECX left by 4 bits - 194 # . EAX |= ECX - 195 09/or 3/mod/direct 0/rm32/EAX . . . 1/r32/ECX . . # EAX = bitwise OR with ECX - 196 $convert-next-octet:end: - 197 # . restore registers - 198 59/pop-to-ECX - 199 # . epilog - 200 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP - 201 5d/pop-to-EBP - 202 c3/return - 203 - 204 test-convert-next-octet: - 205 # - check that the first two bytes of the input are assembled into the resulting octet - 206 # This test uses exit-descriptors. Use EBP for setting up local variables. - 207 55/push-EBP - 208 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP - 209 # clear all streams - 210 # . clear-stream(_test-stream) - 211 # . . push args - 212 68/push _test-stream/imm32 - 213 # . . call - 214 e8/call clear-stream/disp32 - 215 # . . discard args - 216 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 217 # . clear-stream(_test-buffered-file+4) - 218 # . . push args - 219 b8/copy-to-EAX _test-buffered-file/imm32 - 220 05/add-to-EAX 4/imm32 - 221 50/push-EAX - 222 # . . call - 223 e8/call clear-stream/disp32 - 224 # . . discard args - 225 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 226 # . clear-stream(_test-error-stream) - 227 # . . push args - 228 68/push _test-error-stream/imm32 - 229 # . . call - 230 e8/call clear-stream/disp32 - 231 # . . discard args - 232 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 233 # . clear-stream(_test-error-buffered-file+4) - 234 # . . push args - 235 b8/copy-to-EAX _test-error-buffered-file/imm32 - 236 05/add-to-EAX 4/imm32 - 237 50/push-EAX - 238 # . . call - 239 e8/call clear-stream/disp32 - 240 # . . discard args - 241 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 242 # initialize '_test-stream' to "abc" - 243 # . write(_test-stream, "abc") - 244 # . . push args - 245 68/push "abc"/imm32 - 246 68/push _test-stream/imm32 - 247 # . . call - 248 e8/call write/disp32 - 249 # . . discard args - 250 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 251 # initialize exit-descriptor 'ed' for the call to 'convert-next-octet' below - 252 # . var ed/ECX : exit-descriptor - 253 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP - 254 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX - 255 # . tailor-exit-descriptor(ed, 12) - 256 # . . push args - 257 68/push 0xc/imm32/nbytes-of-args-for-convert-next-octet - 258 51/push-ECX/ed - 259 # . . call - 260 e8/call tailor-exit-descriptor/disp32 - 261 # . . discard args - 262 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 263 # EAX = convert-next-octet(_test-buffered-file, _test-error-buffered-file, ed) - 264 # . . push args - 265 51/push-ECX/ed - 266 68/push _test-error-buffered-file/imm32 - 267 68/push _test-buffered-file/imm32 - 268 # . . call - 269 e8/call convert-next-octet/disp32 - 270 # registers except ESP may be clobbered at this point - 271 # pop args to convert-next-octet - 272 # . . discard first 2 args - 273 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 274 # . . restore ed - 275 59/pop-to-ECX - 276 # check that convert-next-octet didn't abort - 277 # . check-ints-equal(ed->value, 0, msg) - 278 # . . push args - 279 68/push "F - test-convert-next-octet: unexpected abort"/imm32 - 280 68/push 0/imm32 - 281 # . . push ed->value - 282 ff 6/subop/push 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 . # push *(ECX+4) - 283 # . . call - 284 e8/call check-ints-equal/disp32 - 285 # . . discard args - 286 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 287 # return if abort - 288 81 7/subop/compare 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 0/imm32 # compare *(ECX+4) - 289 75/jump-if-not-equal $test-convert-next-octet:end/disp8 - 290 # check-ints-equal(EAX, 0xab, msg) - 291 # . . push args - 292 68/push "F - test-convert-next-octet"/imm32 - 293 68/push 0xab/imm32/ab - 294 50/push-EAX - 295 # . . call - 296 e8/call check-ints-equal/disp32 - 297 # . . discard args - 298 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 299 $test-convert-next-octet:end: - 300 # . epilog - 301 # don't restore ESP from EBP; manually reclaim locals - 302 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 303 5d/pop-to-EBP - 304 c3/return - 305 - 306 test-convert-next-octet-handles-eof: - 307 # - check that eof returns the sentinel octet - 308 # This test uses exit-descriptors. Use EBP for setting up local variables. - 309 55/push-EBP - 310 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP - 311 # clear all streams - 312 # . clear-stream(_test-stream) - 313 # . . push args - 314 68/push _test-stream/imm32 - 315 # . . call - 316 e8/call clear-stream/disp32 - 317 # . . discard args - 318 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 319 # . clear-stream(_test-buffered-file+4) - 320 # . . push args - 321 b8/copy-to-EAX _test-buffered-file/imm32 - 322 05/add-to-EAX 4/imm32 - 323 50/push-EAX - 324 # . . call - 325 e8/call clear-stream/disp32 - 326 # . . discard args - 327 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 328 # . clear-stream(_test-error-stream) - 329 # . . push args - 330 68/push _test-error-stream/imm32 - 331 # . . call - 332 e8/call clear-stream/disp32 - 333 # . . discard args - 334 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 335 # . clear-stream(_test-error-buffered-file+4) - 336 # . . push args - 337 b8/copy-to-EAX _test-error-buffered-file/imm32 - 338 05/add-to-EAX 4/imm32 - 339 50/push-EAX - 340 # . . call - 341 e8/call clear-stream/disp32 - 342 # . . discard args - 343 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 344 # don't initialize '_test-stream' - 345 # initialize exit-descriptor 'ed' for the call to 'convert-next-octet' below - 346 # . var ed/ECX : exit-descriptor - 347 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP - 348 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX - 349 # . tailor-exit-descriptor(ed, 12) - 350 # . . push args - 351 68/push 0xc/imm32/nbytes-of-args-for-convert-next-octet - 352 51/push-ECX/ed - 353 # . . call - 354 e8/call tailor-exit-descriptor/disp32 - 355 # . . discard args - 356 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 357 # EAX = convert-next-octet(_test-buffered-file, _test-error-buffered-file, ed) - 358 # . . push args - 359 51/push-ECX/ed - 360 68/push _test-error-buffered-file/imm32 - 361 68/push _test-buffered-file/imm32 - 362 # . . call - 363 e8/call convert-next-octet/disp32 - 364 # registers except ESP may be clobbered at this point - 365 # pop args to convert-next-octet - 366 # . . discard first 2 args - 367 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 368 # . . restore ed - 369 59/pop-to-ECX - 370 # check that convert-next-octet didn't abort - 371 # . check-ints-equal(ed->value, 0, msg) - 372 # . . push args - 373 68/push "F - test-convert-next-octet: unexpected abort"/imm32 - 374 68/push 0/imm32 - 375 # . . push ed->value - 376 ff 6/subop/push 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 . # push *(ECX+4) - 377 # . . call - 378 e8/call check-ints-equal/disp32 - 379 # . . discard args - 380 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 381 # return if abort - 382 81 7/subop/compare 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 0/imm32 # compare *(ECX+4) - 383 75/jump-if-not-equal $test-convert-next-octet-handles-eof:end/disp8 - 384 # check-ints-equal(EAX, 0xffffffff, msg) - 385 # . . push args - 386 68/push "F - test-convert-next-octet-handles-eof"/imm32 - 387 68/push 0xffffffff/imm32/eof - 388 50/push-EAX - 389 # . . call - 390 e8/call check-ints-equal/disp32 - 391 # . . discard args - 392 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 393 $test-convert-next-octet-handles-eof:end: - 394 # . epilog - 395 # don't restore ESP from EBP; manually reclaim locals - 396 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 397 5d/pop-to-EBP - 398 c3/return - 399 - 400 test-convert-next-octet-aborts-on-single-hex-byte: - 401 # - check that a single unaccompanied hex byte aborts - 402 # This test uses exit-descriptors. Use EBP for setting up local variables. - 403 55/push-EBP - 404 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP - 405 # clear all streams - 406 # . clear-stream(_test-stream) - 407 # . . push args - 408 68/push _test-stream/imm32 - 409 # . . call - 410 e8/call clear-stream/disp32 - 411 # . . discard args - 412 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 413 # . clear-stream(_test-buffered-file+4) - 414 # . . push args - 415 b8/copy-to-EAX _test-buffered-file/imm32 - 416 05/add-to-EAX 4/imm32 - 417 50/push-EAX - 418 # . . call - 419 e8/call clear-stream/disp32 - 420 # . . discard args - 421 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 422 # . clear-stream(_test-error-stream) - 423 # . . push args - 424 68/push _test-error-stream/imm32 - 425 # . . call - 426 e8/call clear-stream/disp32 - 427 # . . discard args - 428 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 429 # . clear-stream(_test-error-buffered-file+4) - 430 # . . push args - 431 b8/copy-to-EAX _test-error-buffered-file/imm32 - 432 05/add-to-EAX 4/imm32 - 433 50/push-EAX - 434 # . . call - 435 e8/call clear-stream/disp32 - 436 # . . discard args - 437 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 438 # initialize '_test-stream' to "a" - 439 # . write(_test-stream, "a") - 440 # . . push args - 441 68/push "a"/imm32 - 442 68/push _test-stream/imm32 - 443 # . . call - 444 e8/call write/disp32 - 445 # . . discard args - 446 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 447 # initialize exit-descriptor 'ed' for the call to 'convert-next-octet' below - 448 # . var ed/ECX : exit-descriptor - 449 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP - 450 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX - 451 # . tailor-exit-descriptor(ed, 12) - 452 # . . push args - 453 68/push 0xc/imm32/nbytes-of-args-for-convert-next-octet - 454 51/push-ECX/ed - 455 # . . call - 456 e8/call tailor-exit-descriptor/disp32 - 457 # . . discard args - 458 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 459 # EAX = convert-next-octet(_test-buffered-file, _test-error-buffered-file, ed) - 460 # . . push args - 461 51/push-ECX/ed - 462 68/push _test-error-buffered-file/imm32 - 463 68/push _test-buffered-file/imm32 - 464 # . . call - 465 e8/call convert-next-octet/disp32 - 466 # registers except ESP may be clobbered at this point - 467 # pop args to convert-next-octet - 468 # . . discard first 2 args - 469 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 470 # . . restore ed - 471 59/pop-to-ECX - 472 # check that convert-next-octet aborted - 473 # . check-ints-equal(ed->value, 2, msg) - 474 # . . push args - 475 68/push "F - test-convert-next-octet-aborts-on-single-hex-byte: unexpected abort"/imm32 - 476 68/push 2/imm32 - 477 # . . push ed->value - 478 ff 6/subop/push 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 . # push *(ECX+4) - 479 # . . call - 480 e8/call check-ints-equal/disp32 - 481 # . . discard args - 482 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 483 $test-convert-next-octet-aborts-on-single-hex-byte:end: - 484 # . epilog - 485 # don't restore ESP from EBP; manually reclaim locals - 486 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 487 5d/pop-to-EBP - 488 c3/return - 489 - 490 # read whitespace until a hex byte, and return it - 491 # return 0xffffffff if file ends without finding a hex byte - 492 # on '#' skip all bytes until newline - 493 # abort on any other byte - 494 scan-next-byte: # in : (address buffered-file), err : (address buffered-file), ed : (address exit-descriptor) -> byte-or-eof/EAX - 495 # pseudocode: - 496 # repeatedly - 497 # EAX = read-byte(in) - 498 # if EAX == 0xffffffff return EAX - 499 # if is-hex-lowercase-byte?(EAX) return EAX - 500 # if EAX == ' ' or '\t' or '\n' continue - 501 # if EAX == '#' skip-until-newline(in) - 502 # else error-byte(ed, err, "invalid byte: " EAX) - 503 # - 504 # . prolog - 505 55/push-EBP - 506 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP - 507 # . save registers - 508 $scan-next-byte:loop: - 509 # EAX = read-byte(in) - 510 # . . push args - 511 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) - 512 # . . call - 513 e8/call read-byte/disp32 - 514 # . . discard args - 515 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 516 # if (EAX == 0xffffffff) return EAX - 517 3d/compare-with-EAX 0xffffffff/imm32 - 518 74/jump-if-equal $scan-next-byte:end/disp8 - 519 # if is-hex-lowercase-byte?(EAX) return EAX - 520 # . save EAX for now - 521 50/push-EAX - 522 # . is-hex-lowercase-byte?(EAX) - 523 # . . push args - 524 50/push-EAX - 525 # . . call - 526 e8/call is-hex-lowercase-byte?/disp32 - 527 # . . discard args - 528 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 529 # . compare with 'false' - 530 3d/compare-with-EAX 0/imm32 - 531 # . restore EAX (does not affect flags) - 532 58/pop-to-EAX - 533 # . check whether to return - 534 75/jump-if-not-equal $scan-next-byte:end/disp8 - 535 $scan-next-byte:check1: - 536 # if EAX == ' ' continue - 537 81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0x20/imm32 # compare EAX + 44 e8/call run-tests/disp32 + 45 8b/copy 0/mod/indirect 5/rm32/.disp32 . . 3/r32/EBX Num-test-failures/disp32 # copy *Num-test-failures to EBX + 46 eb/jump $main:end/disp8 + 47 $run-main: + 48 # - otherwise convert stdin + 49 # var ed/EAX : exit-descriptor + 50 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP + 51 89/copy 3/mod/direct 0/rm32/EAX . . . 4/r32/ESP . . # copy ESP to EAX + 52 # configure ed to really exit() + 53 # . ed->target = 0 + 54 c7 0/subop/copy 0/mod/direct 0/rm32/EAX . . . . . 0/imm32 # copy to *EAX + 55 # return convert(Stdin, 1/stdout, 2/stderr, ed) + 56 # . . push args + 57 50/push-EAX/ed + 58 68/push Stderr/imm32 + 59 68/push Stdout/imm32 + 60 68/push Stdin/imm32 + 61 # . . call + 62 e8/call convert/disp32 + 63 # . . discard args + 64 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP + 65 # . syscall(exit, 0) + 66 bb/copy-to-EBX 0/imm32 + 67 $main:end: + 68 b8/copy-to-EAX 1/imm32/exit + 69 cd/syscall 0x80/imm8 + 70 + 71 # the main entry point + 72 convert: # in : (address buffered-file), out : (address buffered-file), err : (address buffered-file), ed : (address exit-descriptor) -> <void> + 73 # pseudocode: + 74 # repeatedly + 75 # EAX = convert-next-octet(in, err, ed) + 76 # if EAX == 0xffffffff break # eof + 77 # write-byte(out, AL) + 78 # flush(out) + 79 # + 80 # . prolog + 81 55/push-EBP + 82 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + 83 # . save registers + 84 50/push-EAX + 85 $convert:loop: + 86 # EAX = convert-next-octet(in, err, ed) + 87 # . . push args + 88 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0x14/disp8 . # push *(EBP+20) + 89 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0x10/disp8 . # push *(EBP+16) + 90 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) + 91 # . . call + 92 e8/call convert-next-octet/disp32 + 93 # . . discard first 2 args + 94 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 95 # if EAX == 0xffffffff break + 96 81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0xffffffff/imm32 # compare EAX + 97 74/jump-if-equal $convert:loop-end/disp8 + 98 # write-byte(out, AL) + 99 # . . push args + 100 50/push-EAX + 101 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) + 102 # . . call + 103 e8/call write-byte/disp32 + 104 # . . discard args + 105 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 106 # loop + 107 eb/jump $convert:loop/disp8 + 108 $convert:loop-end: + 109 # flush(out) + 110 # . . push args + 111 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) + 112 # . . call + 113 e8/call flush/disp32 + 114 # . . discard args + 115 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 116 $convert:end: + 117 # . restore registers + 118 58/pop-to-EAX + 119 # . epilog + 120 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP + 121 5d/pop-to-EBP + 122 c3/return + 123 + 124 # read bytes from 'in' until a sequence of two lowercase hex (0-9, a-f) bytes + 125 # skip spaces and newlines + 126 # on '#' skip bytes until newline + 127 # raise an error and abort on all other unexpected bytes + 128 # return in EAX an _octet_ containing the binary value of the two hex characters + 129 # return 0xffffffff on end of file + 130 convert-next-octet: # in : (address buffered-file), err : (address buffered-file), ed : (address exit-descriptor) -> byte-or-eof/EAX + 131 # pseudocode: + 132 # EAX = scan-next-byte(in, err, ed) + 133 # if (EAX == 0xffffffff) return + 134 # ECX = parse-hex-digit(EAX) + 135 # EAX = scan-next-byte(in, err, ed) + 136 # if (EAX == 0xffffffff) error("partial byte found.") + 137 # EAX = parse-hex-digit(EAX) + 138 # EAX = (ECX << 4) | EAX + 139 # return + 140 # + 141 # . prolog + 142 55/push-EBP + 143 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + 144 # . save registers + 145 51/push-ECX + 146 # EAX = scan-next-byte(in, err, ed) + 147 # . . push args + 148 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0x10/disp8 . # push *(EBP+16) + 149 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) + 150 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) + 151 # . . call + 152 e8/call scan-next-byte/disp32 + 153 # . . discard args + 154 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 155 # if (EAX == 0xffffffff) return + 156 81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0xffffffff/imm32 # compare EAX + 157 74/jump-if-equal $convert-next-octet:end/disp8 + 158 # EAX = parse-hex-digit(EAX) + 159 e8/call parse-hex-digit/disp32 + 160 # ECX = EAX + 161 89/copy 3/mod/direct 1/rm32/ECX . . . 0/r32/EAX . . # copy EAX to ECX + 162 # EAX = scan-next-byte(in, err, ed) + 163 # . . push args + 164 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0x10/disp8 . # push *(EBP+16) + 165 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) + 166 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) + 167 # . . call + 168 e8/call scan-next-byte/disp32 + 169 # . . discard args + 170 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 171 # if (EAX == 0xffffffff) error(ed, err, "partial byte found.") + 172 81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0xffffffff/imm32 # compare EAX + 173 75/jump-if-not-equal $convert-next-octet:convert/disp8 + 174 # . error-byte(ed, err, msg, '.') # reusing error-byte to avoid creating _yet_ another helper + 175 # . . push args + 176 68/push 0x2e/imm32/period/dummy + 177 68/push "convert-next-octet: partial byte found"/imm32 + 178 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) + 179 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0x10/disp8 . # push *(EBP+16) + 180 # . . call + 181 e8/call error-byte/disp32 # never returns + 182 $convert-next-octet:convert: + 183 # EAX = parse-hex-digit(EAX) + 184 e8/call parse-hex-digit/disp32 + 185 # EAX = (ECX << 4) | EAX + 186 # . ECX <<= 4 + 187 c1/shift 4/subop/left 3/mod/direct 1/rm32/ECX . . . . . 4/imm8 # shift ECX left by 4 bits + 188 # . EAX |= ECX + 189 09/or 3/mod/direct 0/rm32/EAX . . . 1/r32/ECX . . # EAX = bitwise OR with ECX + 190 $convert-next-octet:end: + 191 # . restore registers + 192 59/pop-to-ECX + 193 # . epilog + 194 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP + 195 5d/pop-to-EBP + 196 c3/return + 197 + 198 test-convert-next-octet: + 199 # - check that the first two bytes of the input are assembled into the resulting octet + 200 # This test uses exit-descriptors. Use EBP for setting up local variables. + 201 55/push-EBP + 202 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + 203 # clear all streams + 204 # . clear-stream(_test-stream) + 205 # . . push args + 206 68/push _test-stream/imm32 + 207 # . . call + 208 e8/call clear-stream/disp32 + 209 # . . discard args + 210 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 211 # . clear-stream(_test-buffered-file+4) + 212 # . . push args + 213 b8/copy-to-EAX _test-buffered-file/imm32 + 214 05/add-to-EAX 4/imm32 + 215 50/push-EAX + 216 # . . call + 217 e8/call clear-stream/disp32 + 218 # . . discard args + 219 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 220 # . clear-stream(_test-error-stream) + 221 # . . push args + 222 68/push _test-error-stream/imm32 + 223 # . . call + 224 e8/call clear-stream/disp32 + 225 # . . discard args + 226 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 227 # . clear-stream(_test-error-buffered-file+4) + 228 # . . push args + 229 b8/copy-to-EAX _test-error-buffered-file/imm32 + 230 05/add-to-EAX 4/imm32 + 231 50/push-EAX + 232 # . . call + 233 e8/call clear-stream/disp32 + 234 # . . discard args + 235 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 236 # initialize '_test-stream' to "abc" + 237 # . write(_test-stream, "abc") + 238 # . . push args + 239 68/push "abc"/imm32 + 240 68/push _test-stream/imm32 + 241 # . . call + 242 e8/call write/disp32 + 243 # . . discard args + 244 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 245 # initialize exit-descriptor 'ed' for the call to 'convert-next-octet' below + 246 # . var ed/ECX : exit-descriptor + 247 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP + 248 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX + 249 # . tailor-exit-descriptor(ed, 12) + 250 # . . push args + 251 68/push 0xc/imm32/nbytes-of-args-for-convert-next-octet + 252 51/push-ECX/ed + 253 # . . call + 254 e8/call tailor-exit-descriptor/disp32 + 255 # . . discard args + 256 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 257 # EAX = convert-next-octet(_test-buffered-file, _test-error-buffered-file, ed) + 258 # . . push args + 259 51/push-ECX/ed + 260 68/push _test-error-buffered-file/imm32 + 261 68/push _test-buffered-file/imm32 + 262 # . . call + 263 e8/call convert-next-octet/disp32 + 264 # registers except ESP may be clobbered at this point + 265 # pop args to convert-next-octet + 266 # . . discard first 2 args + 267 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 268 # . . restore ed + 269 59/pop-to-ECX + 270 # check that convert-next-octet didn't abort + 271 # . check-ints-equal(ed->value, 0, msg) + 272 # . . push args + 273 68/push "F - test-convert-next-octet: unexpected abort"/imm32 + 274 68/push 0/imm32 + 275 # . . push ed->value + 276 ff 6/subop/push 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 . # push *(ECX+4) + 277 # . . call + 278 e8/call check-ints-equal/disp32 + 279 # . . discard args + 280 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 281 # return if abort + 282 81 7/subop/compare 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 0/imm32 # compare *(ECX+4) + 283 75/jump-if-not-equal $test-convert-next-octet:end/disp8 + 284 # check-ints-equal(EAX, 0xab, msg) + 285 # . . push args + 286 68/push "F - test-convert-next-octet"/imm32 + 287 68/push 0xab/imm32/ab + 288 50/push-EAX + 289 # . . call + 290 e8/call check-ints-equal/disp32 + 291 # . . discard args + 292 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 293 $test-convert-next-octet:end: + 294 # . epilog + 295 # don't restore ESP from EBP; manually reclaim locals + 296 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 297 5d/pop-to-EBP + 298 c3/return + 299 + 300 test-convert-next-octet-handles-eof: + 301 # - check that eof returns the sentinel octet + 302 # This test uses exit-descriptors. Use EBP for setting up local variables. + 303 55/push-EBP + 304 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + 305 # clear all streams + 306 # . clear-stream(_test-stream) + 307 # . . push args + 308 68/push _test-stream/imm32 + 309 # . . call + 310 e8/call clear-stream/disp32 + 311 # . . discard args + 312 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 313 # . clear-stream(_test-buffered-file+4) + 314 # . . push args + 315 b8/copy-to-EAX _test-buffered-file/imm32 + 316 05/add-to-EAX 4/imm32 + 317 50/push-EAX + 318 # . . call + 319 e8/call clear-stream/disp32 + 320 # . . discard args + 321 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 322 # . clear-stream(_test-error-stream) + 323 # . . push args + 324 68/push _test-error-stream/imm32 + 325 # . . call + 326 e8/call clear-stream/disp32 + 327 # . . discard args + 328 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 329 # . clear-stream(_test-error-buffered-file+4) + 330 # . . push args + 331 b8/copy-to-EAX _test-error-buffered-file/imm32 + 332 05/add-to-EAX 4/imm32 + 333 50/push-EAX + 334 # . . call + 335 e8/call clear-stream/disp32 + 336 # . . discard args + 337 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 338 # don't initialize '_test-stream' + 339 # initialize exit-descriptor 'ed' for the call to 'convert-next-octet' below + 340 # . var ed/ECX : exit-descriptor + 341 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP + 342 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX + 343 # . tailor-exit-descriptor(ed, 12) + 344 # . . push args + 345 68/push 0xc/imm32/nbytes-of-args-for-convert-next-octet + 346 51/push-ECX/ed + 347 # . . call + 348 e8/call tailor-exit-descriptor/disp32 + 349 # . . discard args + 350 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 351 # EAX = convert-next-octet(_test-buffered-file, _test-error-buffered-file, ed) + 352 # . . push args + 353 51/push-ECX/ed + 354 68/push _test-error-buffered-file/imm32 + 355 68/push _test-buffered-file/imm32 + 356 # . . call + 357 e8/call convert-next-octet/disp32 + 358 # registers except ESP may be clobbered at this point + 359 # pop args to convert-next-octet + 360 # . . discard first 2 args + 361 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 362 # . . restore ed + 363 59/pop-to-ECX + 364 # check that convert-next-octet didn't abort + 365 # . check-ints-equal(ed->value, 0, msg) + 366 # . . push args + 367 68/push "F - test-convert-next-octet: unexpected abort"/imm32 + 368 68/push 0/imm32 + 369 # . . push ed->value + 370 ff 6/subop/push 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 . # push *(ECX+4) + 371 # . . call + 372 e8/call check-ints-equal/disp32 + 373 # . . discard args + 374 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 375 # return if abort + 376 81 7/subop/compare 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 0/imm32 # compare *(ECX+4) + 377 75/jump-if-not-equal $test-convert-next-octet-handles-eof:end/disp8 + 378 # check-ints-equal(EAX, 0xffffffff, msg) + 379 # . . push args + 380 68/push "F - test-convert-next-octet-handles-eof"/imm32 + 381 68/push 0xffffffff/imm32/eof + 382 50/push-EAX + 383 # . . call + 384 e8/call check-ints-equal/disp32 + 385 # . . discard args + 386 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 387 $test-convert-next-octet-handles-eof:end: + 388 # . epilog + 389 # don't restore ESP from EBP; manually reclaim locals + 390 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 391 5d/pop-to-EBP + 392 c3/return + 393 + 394 test-convert-next-octet-aborts-on-single-hex-byte: + 395 # - check that a single unaccompanied hex byte aborts + 396 # This test uses exit-descriptors. Use EBP for setting up local variables. + 397 55/push-EBP + 398 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + 399 # clear all streams + 400 # . clear-stream(_test-stream) + 401 # . . push args + 402 68/push _test-stream/imm32 + 403 # . . call + 404 e8/call clear-stream/disp32 + 405 # . . discard args + 406 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 407 # . clear-stream(_test-buffered-file+4) + 408 # . . push args + 409 b8/copy-to-EAX _test-buffered-file/imm32 + 410 05/add-to-EAX 4/imm32 + 411 50/push-EAX + 412 # . . call + 413 e8/call clear-stream/disp32 + 414 # . . discard args + 415 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 416 # . clear-stream(_test-error-stream) + 417 # . . push args + 418 68/push _test-error-stream/imm32 + 419 # . . call + 420 e8/call clear-stream/disp32 + 421 # . . discard args + 422 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 423 # . clear-stream(_test-error-buffered-file+4) + 424 # . . push args + 425 b8/copy-to-EAX _test-error-buffered-file/imm32 + 426 05/add-to-EAX 4/imm32 + 427 50/push-EAX + 428 # . . call + 429 e8/call clear-stream/disp32 + 430 # . . discard args + 431 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 432 # initialize '_test-stream' to "a" + 433 # . write(_test-stream, "a") + 434 # . . push args + 435 68/push "a"/imm32 + 436 68/push _test-stream/imm32 + 437 # . . call + 438 e8/call write/disp32 + 439 # . . discard args + 440 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 441 # initialize exit-descriptor 'ed' for the call to 'convert-next-octet' below + 442 # . var ed/ECX : exit-descriptor + 443 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP + 444 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX + 445 # . tailor-exit-descriptor(ed, 12) + 446 # . . push args + 447 68/push 0xc/imm32/nbytes-of-args-for-convert-next-octet + 448 51/push-ECX/ed + 449 # . . call + 450 e8/call tailor-exit-descriptor/disp32 + 451 # . . discard args + 452 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 453 # EAX = convert-next-octet(_test-buffered-file, _test-error-buffered-file, ed) + 454 # . . push args + 455 51/push-ECX/ed + 456 68/push _test-error-buffered-file/imm32 + 457 68/push _test-buffered-file/imm32 + 458 # . . call + 459 e8/call convert-next-octet/disp32 + 460 # registers except ESP may be clobbered at this point + 461 # pop args to convert-next-octet + 462 # . . discard first 2 args + 463 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 464 # . . restore ed + 465 59/pop-to-ECX + 466 # check that convert-next-octet aborted + 467 # . check-ints-equal(ed->value, 2, msg) + 468 # . . push args + 469 68/push "F - test-convert-next-octet-aborts-on-single-hex-byte: unexpected abort"/imm32 + 470 68/push 2/imm32 + 471 # . . push ed->value + 472 ff 6/subop/push 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 . # push *(ECX+4) + 473 # . . call + 474 e8/call check-ints-equal/disp32 + 475 # . . discard args + 476 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 477 $test-convert-next-octet-aborts-on-single-hex-byte:end: + 478 # . epilog + 479 # don't restore ESP from EBP; manually reclaim locals + 480 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 481 5d/pop-to-EBP + 482 c3/return + 483 + 484 # read whitespace until a hex byte, and return it + 485 # return 0xffffffff if file ends without finding a hex byte + 486 # on '#' skip all bytes until newline + 487 # abort on any other byte + 488 scan-next-byte: # in : (address buffered-file), err : (address buffered-file), ed : (address exit-descriptor) -> byte-or-eof/EAX + 489 # pseudocode: + 490 # repeatedly + 491 # EAX = read-byte(in) + 492 # if EAX == 0xffffffff return EAX + 493 # if is-hex-lowercase-byte?(EAX) return EAX + 494 # if EAX == ' ' or '\t' or '\n' continue + 495 # if EAX == '#' skip-until-newline(in) + 496 # else error-byte(ed, err, "invalid byte: " EAX) + 497 # + 498 # . prolog + 499 55/push-EBP + 500 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + 501 # . save registers + 502 $scan-next-byte:loop: + 503 # EAX = read-byte(in) + 504 # . . push args + 505 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) + 506 # . . call + 507 e8/call read-byte/disp32 + 508 # . . discard args + 509 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 510 # if (EAX == 0xffffffff) return EAX + 511 3d/compare-with-EAX 0xffffffff/imm32 + 512 74/jump-if-equal $scan-next-byte:end/disp8 + 513 # if is-hex-lowercase-byte?(EAX) return EAX + 514 # . save EAX for now + 515 50/push-EAX + 516 # . is-hex-lowercase-byte?(EAX) + 517 # . . push args + 518 50/push-EAX + 519 # . . call + 520 e8/call is-hex-lowercase-byte?/disp32 + 521 # . . discard args + 522 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 523 # . compare with 'false' + 524 3d/compare-with-EAX 0/imm32 + 525 # . restore EAX (does not affect flags) + 526 58/pop-to-EAX + 527 # . check whether to return + 528 75/jump-if-not-equal $scan-next-byte:end/disp8 + 529 $scan-next-byte:check1: + 530 # if EAX == ' ' continue + 531 81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0x20/imm32 # compare EAX + 532 74/jump-if-equal $scan-next-byte:loop/disp8 + 533 # if EAX == '\t' continue + 534 81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0x9/imm32 # compare EAX + 535 74/jump-if-equal $scan-next-byte:loop/disp8 + 536 # if EAX == '\n' continue + 537 81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0xa/imm32 # compare EAX 538 74/jump-if-equal $scan-next-byte:loop/disp8 - 539 # if EAX == '\t' continue - 540 81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0x9/imm32 # compare EAX - 541 74/jump-if-equal $scan-next-byte:loop/disp8 - 542 # if EAX == '\n' continue - 543 81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0xa/imm32 # compare EAX - 544 74/jump-if-equal $scan-next-byte:loop/disp8 - 545 $scan-next-byte:check2: - 546 # if EAX == '#' skip-until-newline(in) - 547 3d/compare-with-EAX 0x23/imm32 - 548 75/jump-if-not-equal $scan-next-byte:check3/disp8 - 549 # . skip-until-newline(in) - 550 # . . push args - 551 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) - 552 # . . call - 553 e8/call skip-until-newline/disp32 - 554 # . . discard args - 555 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 556 eb/jump $scan-next-byte:loop/disp8 - 557 $scan-next-byte:check3: - 558 # otherwise error-byte(ed, err, msg, EAX) - 559 # . . push args - 560 50/push-EAX - 561 68/push "scan-next-byte: invalid byte"/imm32 - 562 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) - 563 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0x10/disp8 . # push *(EBP+16) - 564 # . . call - 565 e8/call error-byte/disp32 # never returns - 566 $scan-next-byte:end: - 567 # . restore registers - 568 # . epilog - 569 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP - 570 5d/pop-to-EBP - 571 c3/return - 572 - 573 test-scan-next-byte: - 574 # - check that the first byte of the input is returned - 575 # This test uses exit-descriptors. Use EBP for setting up local variables. - 576 55/push-EBP - 577 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP - 578 # clear all streams - 579 # . clear-stream(_test-stream) - 580 # . . push args - 581 68/push _test-stream/imm32 - 582 # . . call - 583 e8/call clear-stream/disp32 - 584 # . . discard args - 585 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 586 # . clear-stream(_test-buffered-file+4) - 587 # . . push args - 588 b8/copy-to-EAX _test-buffered-file/imm32 - 589 05/add-to-EAX 4/imm32 - 590 50/push-EAX - 591 # . . call - 592 e8/call clear-stream/disp32 - 593 # . . discard args - 594 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 595 # . clear-stream(_test-error-stream) - 596 # . . push args - 597 68/push _test-error-stream/imm32 - 598 # . . call - 599 e8/call clear-stream/disp32 - 600 # . . discard args - 601 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 602 # . clear-stream(_test-error-buffered-file+4) - 603 # . . push args - 604 b8/copy-to-EAX _test-error-buffered-file/imm32 - 605 05/add-to-EAX 4/imm32 - 606 50/push-EAX - 607 # . . call - 608 e8/call clear-stream/disp32 - 609 # . . discard args - 610 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 611 # initialize '_test-stream' to "abc" - 612 # . write(_test-stream, "abc") - 613 # . . push args - 614 68/push "abc"/imm32 - 615 68/push _test-stream/imm32 - 616 # . . call - 617 e8/call write/disp32 - 618 # . . discard args - 619 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 620 # initialize exit-descriptor 'ed' for the call to 'scan-next-byte' below - 621 # . var ed/ECX : exit-descriptor - 622 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP - 623 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX - 624 # . tailor-exit-descriptor(ed, 12) - 625 # . . push args - 626 68/push 0xc/imm32/nbytes-of-args-for-scan-next-byte - 627 51/push-ECX/ed - 628 # . . call - 629 e8/call tailor-exit-descriptor/disp32 - 630 # . . discard args - 631 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 632 # EAX = scan-next-byte(_test-buffered-file, _test-error-buffered-file, ed) - 633 # . . push args - 634 51/push-ECX/ed - 635 68/push _test-error-buffered-file/imm32 - 636 68/push _test-buffered-file/imm32 - 637 # . . call - 638 e8/call scan-next-byte/disp32 - 639 # registers except ESP may be clobbered at this point - 640 # pop args to scan-next-byte - 641 # . . discard first 2 args - 642 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 643 # . . restore ed - 644 59/pop-to-ECX - 645 # check that scan-next-byte didn't abort - 646 # . check-ints-equal(ed->value, 0, msg) - 647 # . . push args - 648 68/push "F - test-scan-next-byte: unexpected abort"/imm32 - 649 68/push 0/imm32 - 650 # . . push ed->value - 651 ff 6/subop/push 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 . # push *(ECX+4) - 652 # . . call - 653 e8/call check-ints-equal/disp32 - 654 # . . discard args - 655 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 656 # return if abort - 657 81 7/subop/compare 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 0/imm32 # compare *(ECX+4) - 658 75/jump-if-not-equal $test-scan-next-byte:end/disp8 - 659 # check-ints-equal(EAX, 0x61/a, msg) - 660 # . . push args - 661 68/push "F - test-scan-next-byte"/imm32 - 662 68/push 0x61/imm32/a - 663 50/push-EAX - 664 # . . call - 665 e8/call check-ints-equal/disp32 - 666 # . . discard args - 667 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 668 $test-scan-next-byte:end: - 669 # . epilog - 670 # don't restore ESP from EBP; manually reclaim locals - 671 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 672 5d/pop-to-EBP - 673 c3/return - 674 - 675 test-scan-next-byte-skips-whitespace: - 676 # - check that the first byte after whitespace is returned - 677 # This test uses exit-descriptors. Use EBP for setting up local variables. - 678 55/push-EBP - 679 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP - 680 # clear all streams - 681 # . clear-stream(_test-stream) - 682 # . . push args - 683 68/push _test-stream/imm32 - 684 # . . call - 685 e8/call clear-stream/disp32 - 686 # . . discard args - 687 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 688 # . clear-stream(_test-buffered-file+4) - 689 # . . push args - 690 b8/copy-to-EAX _test-buffered-file/imm32 - 691 05/add-to-EAX 4/imm32 - 692 50/push-EAX - 693 # . . call - 694 e8/call clear-stream/disp32 - 695 # . . discard args - 696 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 697 # . clear-stream(_test-error-stream) - 698 # . . push args - 699 68/push _test-error-stream/imm32 - 700 # . . call - 701 e8/call clear-stream/disp32 - 702 # . . discard args - 703 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 704 # . clear-stream(_test-error-buffered-file+4) - 705 # . . push args - 706 b8/copy-to-EAX _test-error-buffered-file/imm32 - 707 05/add-to-EAX 4/imm32 - 708 50/push-EAX - 709 # . . call - 710 e8/call clear-stream/disp32 - 711 # . . discard args - 712 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 713 # initialize '_test-stream' to input with leading whitespace - 714 # . write(_test-stream, text) - 715 # . . push args - 716 68/push " abc"/imm32 - 717 68/push _test-stream/imm32 - 718 # . . call - 719 e8/call write/disp32 - 720 # . . discard args - 721 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 722 # initialize exit-descriptor 'ed' for the call to 'scan-next-byte' below - 723 # . var ed/ECX : exit-descriptor - 724 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP - 725 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX - 726 # . tailor-exit-descriptor(ed, 12) - 727 # . . push args - 728 68/push 0xc/imm32/nbytes-of-args-for-scan-next-byte - 729 51/push-ECX/ed - 730 # . . call - 731 e8/call tailor-exit-descriptor/disp32 - 732 # . . discard args - 733 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 734 # EAX = scan-next-byte(_test-buffered-file, _test-error-buffered-file, ed) - 735 # . . push args - 736 51/push-ECX/ed - 737 68/push _test-error-buffered-file/imm32 - 738 68/push _test-buffered-file/imm32 - 739 # . . call - 740 e8/call scan-next-byte/disp32 - 741 # registers except ESP may be clobbered at this point - 742 # pop args to scan-next-byte - 743 # . . discard first 2 args - 744 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 745 # . . restore ed - 746 59/pop-to-ECX - 747 # check that scan-next-byte didn't abort - 748 # . check-ints-equal(ed->value, 0, msg) - 749 # . . push args - 750 68/push "F - test-scan-next-byte-skips-whitespace: unexpected abort"/imm32 - 751 68/push 0/imm32 - 752 # . . push ed->value - 753 ff 6/subop/push 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 . # push *(ECX+4) - 754 # . . call - 755 e8/call check-ints-equal/disp32 - 756 # . . discard args - 757 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 758 # return if abort - 759 81 7/subop/compare 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 0/imm32 # compare *(ECX+4) - 760 75/jump-if-not-equal $test-scan-next-byte-skips-whitespace:end/disp8 - 761 # check-ints-equal(EAX, 0x61/a, msg) - 762 # . . push args - 763 68/push "F - test-scan-next-byte-skips-whitespace"/imm32 - 764 68/push 0x61/imm32/a - 765 50/push-EAX - 766 # . . call - 767 e8/call check-ints-equal/disp32 - 768 # . . discard args - 769 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 770 $test-scan-next-byte-skips-whitespace:end: - 771 # . epilog - 772 # don't restore ESP from EBP; manually reclaim locals - 773 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 774 5d/pop-to-EBP - 775 c3/return - 776 - 777 test-scan-next-byte-skips-comment: - 778 # - check that the first byte after a comment (and newline) is returned - 779 # This test uses exit-descriptors. Use EBP for setting up local variables. - 780 55/push-EBP - 781 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP - 782 # clear all streams - 783 # . clear-stream(_test-stream) - 784 # . . push args - 785 68/push _test-stream/imm32 - 786 # . . call - 787 e8/call clear-stream/disp32 - 788 # . . discard args - 789 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 790 # . clear-stream(_test-buffered-file+4) - 791 # . . push args - 792 b8/copy-to-EAX _test-buffered-file/imm32 - 793 05/add-to-EAX 4/imm32 - 794 50/push-EAX - 795 # . . call - 796 e8/call clear-stream/disp32 - 797 # . . discard args - 798 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 799 # . clear-stream(_test-error-stream) - 800 # . . push args - 801 68/push _test-error-stream/imm32 - 802 # . . call - 803 e8/call clear-stream/disp32 - 804 # . . discard args - 805 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 806 # . clear-stream(_test-error-buffered-file+4) - 807 # . . push args - 808 b8/copy-to-EAX _test-error-buffered-file/imm32 - 809 05/add-to-EAX 4/imm32 - 810 50/push-EAX - 811 # . . call - 812 e8/call clear-stream/disp32 - 813 # . . discard args - 814 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 815 # initialize '_test-stream' to input with leading comment - 816 # . write(_test-stream, comment) - 817 # . . push args - 818 68/push "#x"/imm32 - 819 68/push _test-stream/imm32 - 820 # . . call - 821 e8/call write/disp32 - 822 # . . discard args - 823 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 824 # . write(_test-stream, Newline) - 825 # . . push args - 826 68/push Newline/imm32 - 827 68/push _test-stream/imm32 - 828 # . . call - 829 e8/call write/disp32 - 830 # . . discard args - 831 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 832 # . write(_test-stream, real text) - 833 # . . push args - 834 68/push "ab"/imm32 - 835 68/push _test-stream/imm32 - 836 # . . call - 837 e8/call write/disp32 - 838 # . . discard args - 839 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 840 # initialize exit-descriptor 'ed' for the call to 'scan-next-byte' below - 841 # . var ed/ECX : exit-descriptor - 842 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP - 843 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX - 844 # . tailor-exit-descriptor(ed, 12) - 845 # . . push args - 846 68/push 0xc/imm32/nbytes-of-args-for-scan-next-byte - 847 51/push-ECX/ed - 848 # . . call - 849 e8/call tailor-exit-descriptor/disp32 - 850 # . . discard args - 851 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 852 # EAX = scan-next-byte(_test-buffered-file, _test-error-buffered-file, ed) - 853 # . . push args - 854 51/push-ECX/ed - 855 68/push _test-error-buffered-file/imm32 - 856 68/push _test-buffered-file/imm32 - 857 # . . call - 858 e8/call scan-next-byte/disp32 - 859 # registers except ESP may be clobbered at this point - 860 # pop args to scan-next-byte - 861 # . . discard first 2 args - 862 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 863 # . . restore ed - 864 59/pop-to-ECX - 865 # check that scan-next-byte didn't abort - 866 # . check-ints-equal(ed->value, 0, msg) - 867 # . . push args - 868 68/push "F - test-scan-next-byte-skips-comment: unexpected abort"/imm32 - 869 68/push 0/imm32 - 870 # . . push ed->value - 871 ff 6/subop/push 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 . # push *(ECX+4) - 872 # . . call - 873 e8/call check-ints-equal/disp32 - 874 # . . discard args - 875 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 876 # return if abort - 877 81 7/subop/compare 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 0/imm32 # compare *(ECX+4) - 878 75/jump-if-not-equal $test-scan-next-byte-skips-comment:end/disp8 - 879 # check-ints-equal(EAX, 0x61/a, msg) - 880 # . . push args - 881 68/push "F - test-scan-next-byte-skips-comment"/imm32 - 882 68/push 0x61/imm32/a - 883 50/push-EAX - 884 # . . call - 885 e8/call check-ints-equal/disp32 - 886 # . . discard args - 887 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 888 $test-scan-next-byte-skips-comment:end: - 889 # . epilog - 890 # don't restore ESP from EBP; manually reclaim locals - 891 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 892 5d/pop-to-EBP - 893 c3/return - 894 - 895 test-scan-next-byte-skips-comment-and-whitespace: - 896 # - check that the first byte after a comment and any further whitespace is returned - 897 # This test uses exit-descriptors. Use EBP for setting up local variables. - 898 55/push-EBP - 899 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP - 900 # clear all streams - 901 # . clear-stream(_test-stream) - 902 # . . push args - 903 68/push _test-stream/imm32 - 904 # . . call - 905 e8/call clear-stream/disp32 - 906 # . . discard args - 907 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 908 # . clear-stream(_test-buffered-file+4) - 909 # . . push args - 910 b8/copy-to-EAX _test-buffered-file/imm32 - 911 05/add-to-EAX 4/imm32 - 912 50/push-EAX - 913 # . . call - 914 e8/call clear-stream/disp32 - 915 # . . discard args - 916 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 917 # . clear-stream(_test-error-stream) - 918 # . . push args - 919 68/push _test-error-stream/imm32 - 920 # . . call - 921 e8/call clear-stream/disp32 - 922 # . . discard args - 923 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 924 # . clear-stream(_test-error-buffered-file+4) - 925 # . . push args - 926 b8/copy-to-EAX _test-error-buffered-file/imm32 - 927 05/add-to-EAX 4/imm32 - 928 50/push-EAX - 929 # . . call - 930 e8/call clear-stream/disp32 - 931 # . . discard args - 932 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 933 # initialize '_test-stream' to input with leading comment and more whitespace after newline - 934 # . write(_test-stream, comment) - 935 # . . push args - 936 68/push "#x"/imm32 - 937 68/push _test-stream/imm32 - 938 # . . call - 939 e8/call write/disp32 - 940 # . . discard args - 941 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 942 # . write(_test-stream, Newline) - 943 # . . push args - 944 68/push Newline/imm32 - 945 68/push _test-stream/imm32 - 946 # . . call - 947 e8/call write/disp32 - 948 # . . discard args - 949 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 950 # . write(_test-stream, real text) - 951 # . . push args - 952 68/push " ab"/imm32 - 953 68/push _test-stream/imm32 - 954 # . . call - 955 e8/call write/disp32 - 956 # . . discard args - 957 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 958 # initialize exit-descriptor 'ed' for the call to 'scan-next-byte' below - 959 # . var ed/ECX : exit-descriptor - 960 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP - 961 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX - 962 # . tailor-exit-descriptor(ed, 12) - 963 # . . push args - 964 68/push 0xc/imm32/nbytes-of-args-for-scan-next-byte - 965 51/push-ECX/ed - 966 # . . call - 967 e8/call tailor-exit-descriptor/disp32 - 968 # . . discard args - 969 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 970 # EAX = scan-next-byte(_test-buffered-file, _test-error-buffered-file, ed) - 971 # . . push args - 972 51/push-ECX/ed - 973 68/push _test-error-buffered-file/imm32 - 974 68/push _test-buffered-file/imm32 - 975 # . . call - 976 e8/call scan-next-byte/disp32 - 977 # registers except ESP may be clobbered at this point - 978 # pop args to scan-next-byte - 979 # . . discard first 2 args - 980 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 981 # . . restore ed - 982 59/pop-to-ECX - 983 # check that scan-next-byte didn't abort - 984 # . check-ints-equal(ed->value, 0, msg) - 985 # . . push args - 986 68/push "F - test-scan-next-byte-skips-comment-and-whitespace: unexpected abort"/imm32 - 987 68/push 0/imm32 - 988 # . . push ed->value - 989 ff 6/subop/push 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 . # push *(ECX+4) - 990 # . . call - 991 e8/call check-ints-equal/disp32 - 992 # . . discard args - 993 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 994 # return if abort - 995 81 7/subop/compare 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 0/imm32 # compare *(ECX+4) - 996 75/jump-if-not-equal $test-scan-next-byte-skips-comment-and-whitespace:end/disp8 - 997 # check-ints-equal(EAX, 0x61/a, msg) - 998 # . . push args - 999 68/push "F - test-scan-next-byte-skips-comment-and-whitespace"/imm32 -1000 68/push 0x61/imm32/a -1001 50/push-EAX -1002 # . . call -1003 e8/call check-ints-equal/disp32 -1004 # . . discard args -1005 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1006 $test-scan-next-byte-skips-comment-and-whitespace:end: -1007 # . epilog -1008 # don't restore ESP from EBP; manually reclaim locals -1009 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1010 5d/pop-to-EBP -1011 c3/return -1012 -1013 test-scan-next-byte-skips-whitespace-and-comment: -1014 # - check that the first byte after any whitespace and comments is returned -1015 # This test uses exit-descriptors. Use EBP for setting up local variables. -1016 55/push-EBP -1017 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -1018 # clear all streams -1019 # . clear-stream(_test-stream) -1020 # . . push args -1021 68/push _test-stream/imm32 -1022 # . . call -1023 e8/call clear-stream/disp32 -1024 # . . discard args -1025 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1026 # . clear-stream(_test-buffered-file+4) -1027 # . . push args -1028 b8/copy-to-EAX _test-buffered-file/imm32 -1029 05/add-to-EAX 4/imm32 -1030 50/push-EAX -1031 # . . call -1032 e8/call clear-stream/disp32 -1033 # . . discard args -1034 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1035 # . clear-stream(_test-error-stream) -1036 # . . push args -1037 68/push _test-error-stream/imm32 -1038 # . . call -1039 e8/call clear-stream/disp32 -1040 # . . discard args -1041 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1042 # . clear-stream(_test-error-buffered-file+4) -1043 # . . push args -1044 b8/copy-to-EAX _test-error-buffered-file/imm32 -1045 05/add-to-EAX 4/imm32 -1046 50/push-EAX -1047 # . . call -1048 e8/call clear-stream/disp32 -1049 # . . discard args -1050 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1051 # initialize '_test-stream' to input with leading whitespace and comment -1052 # . write(_test-stream, comment) -1053 # . . push args -1054 68/push " #x"/imm32 -1055 68/push _test-stream/imm32 -1056 # . . call -1057 e8/call write/disp32 -1058 # . . discard args -1059 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1060 # . write(_test-stream, Newline) -1061 # . . push args -1062 68/push Newline/imm32 -1063 68/push _test-stream/imm32 -1064 # . . call -1065 e8/call write/disp32 -1066 # . . discard args -1067 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1068 # . write(_test-stream, real text) -1069 # . . push args -1070 68/push "ab"/imm32 -1071 68/push _test-stream/imm32 -1072 # . . call -1073 e8/call write/disp32 -1074 # . . discard args -1075 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1076 # initialize exit-descriptor 'ed' for the call to 'scan-next-byte' below -1077 # . var ed/ECX : exit-descriptor -1078 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP -1079 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX -1080 # . tailor-exit-descriptor(ed, 12) -1081 # . . push args -1082 68/push 0xc/imm32/nbytes-of-args-for-scan-next-byte -1083 51/push-ECX/ed -1084 # . . call -1085 e8/call tailor-exit-descriptor/disp32 -1086 # . . discard args -1087 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1088 # EAX = scan-next-byte(_test-buffered-file, _test-error-buffered-file, ed) -1089 # . . push args -1090 51/push-ECX/ed -1091 68/push _test-error-buffered-file/imm32 -1092 68/push _test-buffered-file/imm32 -1093 # . . call -1094 e8/call scan-next-byte/disp32 -1095 # registers except ESP may be clobbered at this point -1096 # pop args to scan-next-byte -1097 # . . discard first 2 args -1098 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1099 # . . restore ed -1100 59/pop-to-ECX -1101 # check that scan-next-byte didn't abort -1102 # . check-ints-equal(ed->value, 0, msg) -1103 # . . push args -1104 68/push "F - test-scan-next-byte-skips-whitespace-and-comment: unexpected abort"/imm32 -1105 68/push 0/imm32 -1106 # . . push ed->value -1107 ff 6/subop/push 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 . # push *(ECX+4) -1108 # . . call -1109 e8/call check-ints-equal/disp32 -1110 # . . discard args -1111 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1112 # return if abort -1113 81 7/subop/compare 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 0/imm32 # compare *(ECX+4) -1114 75/jump-if-not-equal $test-scan-next-byte-skips-whitespace-and-comment:end/disp8 -1115 # check-ints-equal(EAX, 0x61/a, msg) -1116 # . . push args -1117 68/push "F - test-scan-next-byte-skips-whitespace-and-comment"/imm32 -1118 68/push 0x61/imm32/a -1119 50/push-EAX -1120 # . . call -1121 e8/call check-ints-equal/disp32 -1122 # . . discard args -1123 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1124 $test-scan-next-byte-skips-whitespace-and-comment:end: -1125 # . epilog -1126 # don't restore ESP from EBP; manually reclaim locals -1127 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1128 5d/pop-to-EBP -1129 c3/return -1130 -1131 test-scan-next-byte-reads-final-byte: -1132 # - check that the final byte in input is returned -1133 # This test uses exit-descriptors. Use EBP for setting up local variables. -1134 55/push-EBP -1135 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -1136 # clear all streams -1137 # . clear-stream(_test-stream) -1138 # . . push args -1139 68/push _test-stream/imm32 -1140 # . . call -1141 e8/call clear-stream/disp32 -1142 # . . discard args -1143 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1144 # . clear-stream(_test-buffered-file+4) -1145 # . . push args -1146 b8/copy-to-EAX _test-buffered-file/imm32 -1147 05/add-to-EAX 4/imm32 -1148 50/push-EAX -1149 # . . call -1150 e8/call clear-stream/disp32 -1151 # . . discard args -1152 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1153 # . clear-stream(_test-error-stream) -1154 # . . push args -1155 68/push _test-error-stream/imm32 -1156 # . . call -1157 e8/call clear-stream/disp32 -1158 # . . discard args -1159 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1160 # . clear-stream(_test-error-buffered-file+4) -1161 # . . push args -1162 b8/copy-to-EAX _test-error-buffered-file/imm32 -1163 05/add-to-EAX 4/imm32 -1164 50/push-EAX -1165 # . . call -1166 e8/call clear-stream/disp32 -1167 # . . discard args -1168 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1169 # initialize '_test-stream' to input with single character -1170 # . write(_test-stream, character) -1171 # . . push args -1172 68/push "a"/imm32 -1173 68/push _test-stream/imm32 -1174 # . . call -1175 e8/call write/disp32 -1176 # . . discard args -1177 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1178 # initialize exit-descriptor 'ed' for the call to 'scan-next-byte' below -1179 # . var ed/ECX : exit-descriptor -1180 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP -1181 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX -1182 # . tailor-exit-descriptor(ed, 12) -1183 # . . push args -1184 68/push 0xc/imm32/nbytes-of-args-for-scan-next-byte -1185 51/push-ECX/ed -1186 # . . call -1187 e8/call tailor-exit-descriptor/disp32 -1188 # . . discard args -1189 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1190 # EAX = scan-next-byte(_test-buffered-file, _test-error-buffered-file, ed) -1191 # . . push args -1192 51/push-ECX/ed -1193 68/push _test-error-buffered-file/imm32 -1194 68/push _test-buffered-file/imm32 -1195 # . . call -1196 e8/call scan-next-byte/disp32 -1197 # registers except ESP may be clobbered at this point -1198 # pop args to scan-next-byte -1199 # . . discard first 2 args -1200 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1201 # . . restore ed -1202 59/pop-to-ECX -1203 # check that scan-next-byte didn't abort -1204 # . check-ints-equal(ed->value, 0, msg) -1205 # . . push args -1206 68/push "F - test-scan-next-byte-reads-final-byte: unexpected abort"/imm32 -1207 68/push 0/imm32 -1208 # . . push ed->value -1209 ff 6/subop/push 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 . # push *(ECX+4) -1210 # . . call -1211 e8/call check-ints-equal/disp32 -1212 # . . discard args -1213 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1214 # return if abort -1215 81 7/subop/compare 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 0/imm32 # compare *(ECX+4) -1216 75/jump-if-not-equal $test-scan-next-byte-reads-final-byte:end/disp8 -1217 # check-ints-equal(EAX, 0x61/a, msg) -1218 # . . push args -1219 68/push "F - test-scan-next-byte-reads-final-byte"/imm32 -1220 68/push 0x61/imm32/a -1221 50/push-EAX -1222 # . . call -1223 e8/call check-ints-equal/disp32 -1224 # . . discard args -1225 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1226 $test-scan-next-byte-reads-final-byte:end: -1227 # . epilog -1228 # don't restore ESP from EBP; manually reclaim locals -1229 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1230 5d/pop-to-EBP -1231 c3/return -1232 -1233 test-scan-next-byte-handles-eof: -1234 # - check that the right sentinel value is returned when there's no data remaining to be read -1235 # This test uses exit-descriptors. Use EBP for setting up local variables. -1236 55/push-EBP -1237 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -1238 # clear all streams -1239 # . clear-stream(_test-stream) -1240 # . . push args -1241 68/push _test-stream/imm32 -1242 # . . call -1243 e8/call clear-stream/disp32 -1244 # . . discard args -1245 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1246 # . clear-stream(_test-buffered-file+4) -1247 # . . push args -1248 b8/copy-to-EAX _test-buffered-file/imm32 -1249 05/add-to-EAX 4/imm32 -1250 50/push-EAX -1251 # . . call -1252 e8/call clear-stream/disp32 -1253 # . . discard args -1254 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1255 # . clear-stream(_test-error-stream) -1256 # . . push args -1257 68/push _test-error-stream/imm32 -1258 # . . call -1259 e8/call clear-stream/disp32 -1260 # . . discard args -1261 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1262 # . clear-stream(_test-error-buffered-file+4) -1263 # . . push args -1264 b8/copy-to-EAX _test-error-buffered-file/imm32 -1265 05/add-to-EAX 4/imm32 -1266 50/push-EAX -1267 # . . call -1268 e8/call clear-stream/disp32 -1269 # . . discard args -1270 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1271 # leave '_test-stream' empty -1272 # initialize exit-descriptor 'ed' for the call to 'scan-next-byte' below -1273 # . var ed/ECX : exit-descriptor -1274 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP -1275 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX -1276 # . tailor-exit-descriptor(ed, 12) -1277 # . . push args -1278 68/push 0xc/imm32/nbytes-of-args-for-scan-next-byte -1279 51/push-ECX/ed -1280 # . . call -1281 e8/call tailor-exit-descriptor/disp32 -1282 # . . discard args -1283 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1284 # EAX = scan-next-byte(_test-buffered-file, _test-error-buffered-file, ed) -1285 # . . push args -1286 51/push-ECX/ed -1287 68/push _test-error-buffered-file/imm32 -1288 68/push _test-buffered-file/imm32 -1289 # . . call -1290 e8/call scan-next-byte/disp32 -1291 # registers except ESP may be clobbered at this point -1292 # pop args to scan-next-byte -1293 # . . discard first 2 args -1294 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1295 # . . restore ed -1296 59/pop-to-ECX -1297 # check that scan-next-byte didn't abort -1298 # . check-ints-equal(ed->value, 0, msg) -1299 # . . push args -1300 68/push "F - test-scan-next-byte-handles-eof: unexpected abort"/imm32 -1301 68/push 0/imm32 -1302 # . . push ed->value -1303 ff 6/subop/push 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 . # push *(ECX+4) -1304 # . . call -1305 e8/call check-ints-equal/disp32 -1306 # . . discard args -1307 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1308 # return if abort -1309 81 7/subop/compare 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 0/imm32 # compare *(ECX+4) -1310 75/jump-if-not-equal $test-scan-next-byte-handles-eof:end/disp8 -1311 # check-ints-equal(EAX, 0xffffffff/eof, msg) -1312 # . . push args -1313 68/push "F - test-scan-next-byte-handles-eof"/imm32 -1314 68/push 0xffffffff/imm32/eof -1315 50/push-EAX -1316 # . . call -1317 e8/call check-ints-equal/disp32 -1318 # . . discard args -1319 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1320 $test-scan-next-byte-handles-eof:end: -1321 # . epilog -1322 # don't restore ESP from EBP; manually reclaim locals -1323 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1324 5d/pop-to-EBP -1325 c3/return -1326 -1327 test-scan-next-byte-aborts-on-invalid-byte: -1328 # - check that the a bad byte immediately aborts -1329 # This test uses exit-descriptors. Use EBP for setting up local variables. -1330 55/push-EBP -1331 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -1332 # clear all streams -1333 # . clear-stream(_test-stream) -1334 # . . push args -1335 68/push _test-stream/imm32 -1336 # . . call -1337 e8/call clear-stream/disp32 -1338 # . . discard args -1339 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1340 # . clear-stream(_test-buffered-file+4) -1341 # . . push args -1342 b8/copy-to-EAX _test-buffered-file/imm32 -1343 05/add-to-EAX 4/imm32 -1344 50/push-EAX -1345 # . . call -1346 e8/call clear-stream/disp32 -1347 # . . discard args -1348 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1349 # . clear-stream(_test-error-stream) -1350 # . . push args -1351 68/push _test-error-stream/imm32 -1352 # . . call -1353 e8/call clear-stream/disp32 -1354 # . . discard args -1355 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1356 # . clear-stream(_test-error-buffered-file+4) -1357 # . . push args -1358 b8/copy-to-EAX _test-error-buffered-file/imm32 -1359 05/add-to-EAX 4/imm32 -1360 50/push-EAX -1361 # . . call -1362 e8/call clear-stream/disp32 -1363 # . . discard args -1364 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1365 # initialize '_test-stream' to "x" -1366 # . write(_test-stream, "x") -1367 # . . push args -1368 68/push "x"/imm32 -1369 68/push _test-stream/imm32 -1370 # . . call -1371 e8/call write/disp32 -1372 # . . discard args -1373 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1374 # initialize exit-descriptor 'ed' for the call to 'scan-next-byte' below -1375 # . var ed/ECX : exit-descriptor -1376 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP -1377 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX -1378 # . tailor-exit-descriptor(ed, 12) -1379 # . . push args -1380 68/push 0xc/imm32/nbytes-of-args-for-scan-next-byte -1381 51/push-ECX/ed -1382 # . . call -1383 e8/call tailor-exit-descriptor/disp32 -1384 # . . discard args -1385 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1386 # EAX = scan-next-byte(_test-buffered-file, _test-error-buffered-file, ed) -1387 # . . push args -1388 51/push-ECX/ed -1389 68/push _test-error-buffered-file/imm32 -1390 68/push _test-buffered-file/imm32 -1391 # . . call -1392 e8/call scan-next-byte/disp32 -1393 # registers except ESP may be clobbered at this point -1394 # pop args to scan-next-byte -1395 # . . discard first 2 args -1396 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1397 # . . restore ed -1398 59/pop-to-ECX -1399 # check that scan-next-byte aborted -1400 # . check-ints-equal(ed->value, 2, msg) -1401 # . . push args -1402 68/push "F - test-scan-next-byte-aborts-on-invalid-byte"/imm32 -1403 68/push 2/imm32 -1404 # . . push ed->value -1405 ff 6/subop/push 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 . # push *(ECX+4) -1406 # . . call -1407 e8/call check-ints-equal/disp32 -1408 # . . discard args -1409 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1410 $test-scan-next-byte-aborts-on-invalid-byte:end: -1411 # . epilog -1412 # don't restore ESP from EBP; manually reclaim locals -1413 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1414 5d/pop-to-EBP -1415 c3/return -1416 -1417 is-hex-lowercase-byte?: # c : byte -> bool/EAX -1418 # . prolog -1419 55/push-EBP -1420 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -1421 # . save registers -1422 51/push-ECX -1423 # ECX = c -1424 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 1/r32/ECX 8/disp8 . # copy *(EBP+8) to ECX -1425 # return false if c < '0' -1426 b8/copy-to-EAX 0/imm32/false -1427 81 7/subop/compare 3/mod/direct 1/rm32/ECX . . . . . 0x30/imm32 # compare ECX -1428 7c/jump-if-lesser $is-hex-lowercase-byte?:end/disp8 -1429 # return false if c > 'f' -1430 81 7/subop/compare 3/mod/direct 1/rm32/ECX . . . . . 0x66/imm32 # compare ECX -1431 7f/jump-if-greater $is-hex-lowercase-byte?:end/disp8 -1432 # return true if c <= '9' -1433 b8/copy-to-EAX 1/imm32/true -1434 81 7/subop/compare 3/mod/direct 1/rm32/ECX . . . . . 0x39/imm32 # compare ECX -1435 7e/jump-if-lesser-or-equal $is-hex-lowercase-byte?:end/disp8 -1436 # return true if c >= 'a' -1437 81 7/subop/compare 3/mod/direct 1/rm32/ECX . . . . . 0x61/imm32 # compare ECX -1438 7d/jump-if-greater-or-equal $is-hex-lowercase-byte?:end/disp8 -1439 # otherwise return false -1440 b8/copy-to-EAX 0/imm32/false -1441 $is-hex-lowercase-byte?:end: -1442 # . restore registers -1443 59/pop-to-ECX -1444 # . epilog -1445 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -1446 5d/pop-to-EBP -1447 c3/return -1448 -1449 test-hex-below-0: -1450 # is-hex-lowercase-byte?(0x2f) -1451 # . . push args -1452 68/push 0x2f/imm32 -1453 # . . call -1454 e8/call is-hex-lowercase-byte?/disp32 -1455 # . . discard args -1456 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1457 # check-ints-equal(EAX, 0, msg) -1458 # . . push args -1459 68/push "F - test-hex-below-0"/imm32 -1460 68/push 0/imm32/false -1461 50/push-EAX -1462 # . . call -1463 e8/call check-ints-equal/disp32 -1464 # . . discard args -1465 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1466 c3/return -1467 -1468 test-hex-0-to-9: -1469 # is-hex-lowercase-byte?(0x30) -1470 # . . push args -1471 68/push 0x30/imm32 -1472 # . . call -1473 e8/call is-hex-lowercase-byte?/disp32 -1474 # . . discard args -1475 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1476 # check-ints-equal(EAX, 1, msg) -1477 # . . push args -1478 68/push "F - test-hex-at-0"/imm32 -1479 68/push 1/imm32/true -1480 50/push-EAX -1481 # . . call -1482 e8/call check-ints-equal/disp32 -1483 # . . discard args -1484 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1485 # is-hex-lowercase-byte?(0x39) -1486 # . . push args -1487 68/push 0x39/imm32 -1488 # . . call -1489 e8/call is-hex-lowercase-byte?/disp32 -1490 # . . discard args -1491 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1492 # check-ints-equal(EAX, 1, msg) -1493 # . . push args -1494 68/push "F - test-hex-at-9"/imm32 -1495 68/push 1/imm32/true -1496 50/push-EAX -1497 # . . call -1498 e8/call check-ints-equal/disp32 -1499 # . . discard args -1500 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1501 c3/return -1502 -1503 test-hex-above-9-to-a: -1504 # is-hex-lowercase-byte?(0x3a) -1505 # . . push args -1506 68/push 0x3a/imm32 -1507 # . . call -1508 e8/call is-hex-lowercase-byte?/disp32 -1509 # . . discard args -1510 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1511 # check-ints-equal(EAX, 0, msg) -1512 # . . push args -1513 68/push "F - test-hex-above-9-to-a"/imm32 -1514 68/push 0/imm32/false -1515 50/push-EAX -1516 # . . call -1517 e8/call check-ints-equal/disp32 -1518 # . . discard args -1519 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1520 c3/return -1521 -1522 test-hex-a-to-f: -1523 # is-hex-lowercase-byte?(0x61) -1524 # . . push args -1525 68/push 0x61/imm32 -1526 # . . call -1527 e8/call is-hex-lowercase-byte?/disp32 -1528 # . . discard args -1529 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1530 # check-ints-equal(EAX, 1, msg) -1531 # . . push args -1532 68/push "F - test-hex-at-a"/imm32 -1533 68/push 1/imm32/true -1534 50/push-EAX -1535 # . . call -1536 e8/call check-ints-equal/disp32 -1537 # . . discard args -1538 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1539 # is-hex-lowercase-byte?(0x66) -1540 # . . push args -1541 68/push 0x66/imm32 -1542 # . . call -1543 e8/call is-hex-lowercase-byte?/disp32 -1544 # . . discard args -1545 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1546 # check-ints-equal(EAX, 1, msg) -1547 # . . push args -1548 68/push "F - test-hex-at-f"/imm32 -1549 68/push 1/imm32/true -1550 50/push-EAX -1551 # . . call -1552 e8/call check-ints-equal/disp32 -1553 # . . discard args -1554 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1555 c3/return -1556 -1557 test-hex-above-f: -1558 # is-hex-lowercase-byte?(0x67) -1559 # . . push args -1560 68/push 0x67/imm32 -1561 # . . call -1562 e8/call is-hex-lowercase-byte?/disp32 -1563 # . . discard args -1564 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1565 # check-ints-equal(EAX, 0, msg) -1566 # . . push args -1567 68/push "F - test-hex-above-f"/imm32 -1568 68/push 0/imm32/false -1569 50/push-EAX -1570 # . . call -1571 e8/call check-ints-equal/disp32 -1572 # . . discard args -1573 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1574 c3/return -1575 -1576 parse-hex-digit: # in/EAX : byte -> out/EAX : num -1577 # no error checking; accepts argument in EAX -1578 # if EAX <= '9' return EAX - '0' -1579 3d/compare-EAX 0x39/imm32/9 -1580 7f/jump-if-greater $parse-hex-digit:else/disp8 -1581 2d/subtract-from-EAX 0x30/imm32/0 -1582 c3/return -1583 $parse-hex-digit:else: -1584 # otherwise return EAX - 'a' + 10 -1585 2d/subtract-from-EAX 0x57/imm32/a-10 -1586 c3/return -1587 -1588 skip-until-newline: # in : (address buffered-file) -> <void> -1589 # pseudocode: -1590 # push EAX -1591 # repeatedly: -1592 # EAX = read-byte(in) -1593 # if EAX == 0xffffffff break -1594 # if EAX == 0x0a break -1595 # pop EAX -1596 # . prolog -1597 55/push-EBP -1598 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -1599 # . save registers -1600 50/push-EAX -1601 $skip-until-newline:loop: -1602 # . EAX = read-byte(in) -1603 # . . push args -1604 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) -1605 # . . call -1606 e8/call read-byte/disp32 -1607 # . . discard args -1608 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1609 # . if EAX == 0xffffffff break -1610 81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0xffffffff/imm32 # compare EAX -1611 74/jump-if-equal $skip-until-newline:end/disp8 -1612 # . if EAX != 0xa/newline loop -1613 81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0xa/imm32 # compare EAX -1614 75/jump-if-not-equal $skip-until-newline:loop/disp8 -1615 $skip-until-newline:end: -1616 # . restore registers -1617 58/pop-to-EAX -1618 # . epilog -1619 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -1620 5d/pop-to-EBP -1621 c3/return -1622 -1623 test-skip-until-newline: -1624 # - check that the read pointer points after the newline -1625 # setup -1626 # . clear-stream(_test-stream) -1627 # . . push args -1628 68/push _test-stream/imm32 -1629 # . . call -1630 e8/call clear-stream/disp32 -1631 # . . discard args -1632 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1633 # . clear-stream(_test-buffered-file+4) -1634 # . . push args -1635 b8/copy-to-EAX _test-buffered-file/imm32 -1636 05/add-to-EAX 4/imm32 -1637 50/push-EAX -1638 # . . call -1639 e8/call clear-stream/disp32 -1640 # . . discard args -1641 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1642 # initialize '_test-stream' to "abc\nde" -1643 # . write(_test-stream, "abc") -1644 # . . push args -1645 68/push "abc"/imm32 -1646 68/push _test-stream/imm32 -1647 # . . call -1648 e8/call write/disp32 -1649 # . . discard args -1650 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1651 # . write(_test-stream, Newline) -1652 # . . push args -1653 68/push Newline/imm32 -1654 68/push _test-stream/imm32 -1655 # . . call -1656 e8/call write/disp32 -1657 # . . discard args -1658 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1659 # . write(_test-stream, "de") -1660 # . . push args -1661 68/push "de"/imm32 -1662 68/push _test-stream/imm32 -1663 # . . call -1664 e8/call write/disp32 -1665 # . . discard args -1666 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1667 # skip-until-newline(_test-buffered-file) -1668 # . . push args -1669 68/push _test-buffered-file/imm32 -1670 # . . call -1671 e8/call skip-until-newline/disp32 -1672 # . . discard args -1673 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1674 # check-ints-equal(_test-buffered-file->read, 4, msg) -1675 # . . push args -1676 68/push "F - test-skip-until-newline"/imm32 -1677 68/push 4/imm32 -1678 b8/copy-to-EAX _test-buffered-file/imm32 -1679 ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 8/disp8 . # push *(EAX+8) -1680 # . . call -1681 e8/call check-ints-equal/disp32 -1682 # . . discard args -1683 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1684 # . end -1685 c3/return -1686 -1687 == data -1688 -1689 _test-error-stream: -1690 # current write index -1691 00 00 00 00 -1692 # current read index -1693 00 00 00 00 -1694 # length (= 8) -1695 08 00 00 00 -1696 # data -1697 00 00 00 00 00 00 00 00 # 8 bytes -1698 -1699 # a test buffered file for _test-stream -1700 _test-error-buffered-file: -1701 # file descriptor or (address stream) -1702 _test-error-stream/imm32 -1703 # current write index -1704 00 00 00 00 -1705 # current read index -1706 00 00 00 00 -1707 # length (6) -1708 06 00 00 00 -1709 # data -1710 00 00 00 00 00 00 # 6 bytes -1711 -1712 # . . vim:nowrap:textwidth=0 + 539 $scan-next-byte:check2: + 540 # if EAX == '#' skip-until-newline(in) + 541 3d/compare-with-EAX 0x23/imm32 + 542 75/jump-if-not-equal $scan-next-byte:check3/disp8 + 543 # . skip-until-newline(in) + 544 # . . push args + 545 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) + 546 # . . call + 547 e8/call skip-until-newline/disp32 + 548 # . . discard args + 549 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 550 eb/jump $scan-next-byte:loop/disp8 + 551 $scan-next-byte:check3: + 552 # otherwise error-byte(ed, err, msg, EAX) + 553 # . . push args + 554 50/push-EAX + 555 68/push "scan-next-byte: invalid byte"/imm32 + 556 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) + 557 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0x10/disp8 . # push *(EBP+16) + 558 # . . call + 559 e8/call error-byte/disp32 # never returns + 560 $scan-next-byte:end: + 561 # . restore registers + 562 # . epilog + 563 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP + 564 5d/pop-to-EBP + 565 c3/return + 566 + 567 test-scan-next-byte: + 568 # - check that the first byte of the input is returned + 569 # This test uses exit-descriptors. Use EBP for setting up local variables. + 570 55/push-EBP + 571 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + 572 # clear all streams + 573 # . clear-stream(_test-stream) + 574 # . . push args + 575 68/push _test-stream/imm32 + 576 # . . call + 577 e8/call clear-stream/disp32 + 578 # . . discard args + 579 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 580 # . clear-stream(_test-buffered-file+4) + 581 # . . push args + 582 b8/copy-to-EAX _test-buffered-file/imm32 + 583 05/add-to-EAX 4/imm32 + 584 50/push-EAX + 585 # . . call + 586 e8/call clear-stream/disp32 + 587 # . . discard args + 588 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 589 # . clear-stream(_test-error-stream) + 590 # . . push args + 591 68/push _test-error-stream/imm32 + 592 # . . call + 593 e8/call clear-stream/disp32 + 594 # . . discard args + 595 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 596 # . clear-stream(_test-error-buffered-file+4) + 597 # . . push args + 598 b8/copy-to-EAX _test-error-buffered-file/imm32 + 599 05/add-to-EAX 4/imm32 + 600 50/push-EAX + 601 # . . call + 602 e8/call clear-stream/disp32 + 603 # . . discard args + 604 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 605 # initialize '_test-stream' to "abc" + 606 # . write(_test-stream, "abc") + 607 # . . push args + 608 68/push "abc"/imm32 + 609 68/push _test-stream/imm32 + 610 # . . call + 611 e8/call write/disp32 + 612 # . . discard args + 613 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 614 # initialize exit-descriptor 'ed' for the call to 'scan-next-byte' below + 615 # . var ed/ECX : exit-descriptor + 616 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP + 617 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX + 618 # . tailor-exit-descriptor(ed, 12) + 619 # . . push args + 620 68/push 0xc/imm32/nbytes-of-args-for-scan-next-byte + 621 51/push-ECX/ed + 622 # . . call + 623 e8/call tailor-exit-descriptor/disp32 + 624 # . . discard args + 625 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 626 # EAX = scan-next-byte(_test-buffered-file, _test-error-buffered-file, ed) + 627 # . . push args + 628 51/push-ECX/ed + 629 68/push _test-error-buffered-file/imm32 + 630 68/push _test-buffered-file/imm32 + 631 # . . call + 632 e8/call scan-next-byte/disp32 + 633 # registers except ESP may be clobbered at this point + 634 # pop args to scan-next-byte + 635 # . . discard first 2 args + 636 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 637 # . . restore ed + 638 59/pop-to-ECX + 639 # check that scan-next-byte didn't abort + 640 # . check-ints-equal(ed->value, 0, msg) + 641 # . . push args + 642 68/push "F - test-scan-next-byte: unexpected abort"/imm32 + 643 68/push 0/imm32 + 644 # . . push ed->value + 645 ff 6/subop/push 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 . # push *(ECX+4) + 646 # . . call + 647 e8/call check-ints-equal/disp32 + 648 # . . discard args + 649 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 650 # return if abort + 651 81 7/subop/compare 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 0/imm32 # compare *(ECX+4) + 652 75/jump-if-not-equal $test-scan-next-byte:end/disp8 + 653 # check-ints-equal(EAX, 0x61/a, msg) + 654 # . . push args + 655 68/push "F - test-scan-next-byte"/imm32 + 656 68/push 0x61/imm32/a + 657 50/push-EAX + 658 # . . call + 659 e8/call check-ints-equal/disp32 + 660 # . . discard args + 661 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 662 $test-scan-next-byte:end: + 663 # . epilog + 664 # don't restore ESP from EBP; manually reclaim locals + 665 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 666 5d/pop-to-EBP + 667 c3/return + 668 + 669 test-scan-next-byte-skips-whitespace: + 670 # - check that the first byte after whitespace is returned + 671 # This test uses exit-descriptors. Use EBP for setting up local variables. + 672 55/push-EBP + 673 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + 674 # clear all streams + 675 # . clear-stream(_test-stream) + 676 # . . push args + 677 68/push _test-stream/imm32 + 678 # . . call + 679 e8/call clear-stream/disp32 + 680 # . . discard args + 681 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 682 # . clear-stream(_test-buffered-file+4) + 683 # . . push args + 684 b8/copy-to-EAX _test-buffered-file/imm32 + 685 05/add-to-EAX 4/imm32 + 686 50/push-EAX + 687 # . . call + 688 e8/call clear-stream/disp32 + 689 # . . discard args + 690 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 691 # . clear-stream(_test-error-stream) + 692 # . . push args + 693 68/push _test-error-stream/imm32 + 694 # . . call + 695 e8/call clear-stream/disp32 + 696 # . . discard args + 697 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 698 # . clear-stream(_test-error-buffered-file+4) + 699 # . . push args + 700 b8/copy-to-EAX _test-error-buffered-file/imm32 + 701 05/add-to-EAX 4/imm32 + 702 50/push-EAX + 703 # . . call + 704 e8/call clear-stream/disp32 + 705 # . . discard args + 706 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 707 # initialize '_test-stream' to input with leading whitespace + 708 # . write(_test-stream, text) + 709 # . . push args + 710 68/push " abc"/imm32 + 711 68/push _test-stream/imm32 + 712 # . . call + 713 e8/call write/disp32 + 714 # . . discard args + 715 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 716 # initialize exit-descriptor 'ed' for the call to 'scan-next-byte' below + 717 # . var ed/ECX : exit-descriptor + 718 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP + 719 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX + 720 # . tailor-exit-descriptor(ed, 12) + 721 # . . push args + 722 68/push 0xc/imm32/nbytes-of-args-for-scan-next-byte + 723 51/push-ECX/ed + 724 # . . call + 725 e8/call tailor-exit-descriptor/disp32 + 726 # . . discard args + 727 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 728 # EAX = scan-next-byte(_test-buffered-file, _test-error-buffered-file, ed) + 729 # . . push args + 730 51/push-ECX/ed + 731 68/push _test-error-buffered-file/imm32 + 732 68/push _test-buffered-file/imm32 + 733 # . . call + 734 e8/call scan-next-byte/disp32 + 735 # registers except ESP may be clobbered at this point + 736 # pop args to scan-next-byte + 737 # . . discard first 2 args + 738 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 739 # . . restore ed + 740 59/pop-to-ECX + 741 # check that scan-next-byte didn't abort + 742 # . check-ints-equal(ed->value, 0, msg) + 743 # . . push args + 744 68/push "F - test-scan-next-byte-skips-whitespace: unexpected abort"/imm32 + 745 68/push 0/imm32 + 746 # . . push ed->value + 747 ff 6/subop/push 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 . # push *(ECX+4) + 748 # . . call + 749 e8/call check-ints-equal/disp32 + 750 # . . discard args + 751 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 752 # return if abort + 753 81 7/subop/compare 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 0/imm32 # compare *(ECX+4) + 754 75/jump-if-not-equal $test-scan-next-byte-skips-whitespace:end/disp8 + 755 # check-ints-equal(EAX, 0x61/a, msg) + 756 # . . push args + 757 68/push "F - test-scan-next-byte-skips-whitespace"/imm32 + 758 68/push 0x61/imm32/a + 759 50/push-EAX + 760 # . . call + 761 e8/call check-ints-equal/disp32 + 762 # . . discard args + 763 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 764 $test-scan-next-byte-skips-whitespace:end: + 765 # . epilog + 766 # don't restore ESP from EBP; manually reclaim locals + 767 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 768 5d/pop-to-EBP + 769 c3/return + 770 + 771 test-scan-next-byte-skips-comment: + 772 # - check that the first byte after a comment (and newline) is returned + 773 # This test uses exit-descriptors. Use EBP for setting up local variables. + 774 55/push-EBP + 775 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + 776 # clear all streams + 777 # . clear-stream(_test-stream) + 778 # . . push args + 779 68/push _test-stream/imm32 + 780 # . . call + 781 e8/call clear-stream/disp32 + 782 # . . discard args + 783 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 784 # . clear-stream(_test-buffered-file+4) + 785 # . . push args + 786 b8/copy-to-EAX _test-buffered-file/imm32 + 787 05/add-to-EAX 4/imm32 + 788 50/push-EAX + 789 # . . call + 790 e8/call clear-stream/disp32 + 791 # . . discard args + 792 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 793 # . clear-stream(_test-error-stream) + 794 # . . push args + 795 68/push _test-error-stream/imm32 + 796 # . . call + 797 e8/call clear-stream/disp32 + 798 # . . discard args + 799 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 800 # . clear-stream(_test-error-buffered-file+4) + 801 # . . push args + 802 b8/copy-to-EAX _test-error-buffered-file/imm32 + 803 05/add-to-EAX 4/imm32 + 804 50/push-EAX + 805 # . . call + 806 e8/call clear-stream/disp32 + 807 # . . discard args + 808 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 809 # initialize '_test-stream' to input with leading comment + 810 # . write(_test-stream, comment) + 811 # . . push args + 812 68/push "#x"/imm32 + 813 68/push _test-stream/imm32 + 814 # . . call + 815 e8/call write/disp32 + 816 # . . discard args + 817 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 818 # . write(_test-stream, Newline) + 819 # . . push args + 820 68/push Newline/imm32 + 821 68/push _test-stream/imm32 + 822 # . . call + 823 e8/call write/disp32 + 824 # . . discard args + 825 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 826 # . write(_test-stream, real text) + 827 # . . push args + 828 68/push "ab"/imm32 + 829 68/push _test-stream/imm32 + 830 # . . call + 831 e8/call write/disp32 + 832 # . . discard args + 833 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 834 # initialize exit-descriptor 'ed' for the call to 'scan-next-byte' below + 835 # . var ed/ECX : exit-descriptor + 836 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP + 837 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX + 838 # . tailor-exit-descriptor(ed, 12) + 839 # . . push args + 840 68/push 0xc/imm32/nbytes-of-args-for-scan-next-byte + 841 51/push-ECX/ed + 842 # . . call + 843 e8/call tailor-exit-descriptor/disp32 + 844 # . . discard args + 845 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 846 # EAX = scan-next-byte(_test-buffered-file, _test-error-buffered-file, ed) + 847 # . . push args + 848 51/push-ECX/ed + 849 68/push _test-error-buffered-file/imm32 + 850 68/push _test-buffered-file/imm32 + 851 # . . call + 852 e8/call scan-next-byte/disp32 + 853 # registers except ESP may be clobbered at this point + 854 # pop args to scan-next-byte + 855 # . . discard first 2 args + 856 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 857 # . . restore ed + 858 59/pop-to-ECX + 859 # check that scan-next-byte didn't abort + 860 # . check-ints-equal(ed->value, 0, msg) + 861 # . . push args + 862 68/push "F - test-scan-next-byte-skips-comment: unexpected abort"/imm32 + 863 68/push 0/imm32 + 864 # . . push ed->value + 865 ff 6/subop/push 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 . # push *(ECX+4) + 866 # . . call + 867 e8/call check-ints-equal/disp32 + 868 # . . discard args + 869 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 870 # return if abort + 871 81 7/subop/compare 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 0/imm32 # compare *(ECX+4) + 872 75/jump-if-not-equal $test-scan-next-byte-skips-comment:end/disp8 + 873 # check-ints-equal(EAX, 0x61/a, msg) + 874 # . . push args + 875 68/push "F - test-scan-next-byte-skips-comment"/imm32 + 876 68/push 0x61/imm32/a + 877 50/push-EAX + 878 # . . call + 879 e8/call check-ints-equal/disp32 + 880 # . . discard args + 881 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 882 $test-scan-next-byte-skips-comment:end: + 883 # . epilog + 884 # don't restore ESP from EBP; manually reclaim locals + 885 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 886 5d/pop-to-EBP + 887 c3/return + 888 + 889 test-scan-next-byte-skips-comment-and-whitespace: + 890 # - check that the first byte after a comment and any further whitespace is returned + 891 # This test uses exit-descriptors. Use EBP for setting up local variables. + 892 55/push-EBP + 893 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + 894 # clear all streams + 895 # . clear-stream(_test-stream) + 896 # . . push args + 897 68/push _test-stream/imm32 + 898 # . . call + 899 e8/call clear-stream/disp32 + 900 # . . discard args + 901 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 902 # . clear-stream(_test-buffered-file+4) + 903 # . . push args + 904 b8/copy-to-EAX _test-buffered-file/imm32 + 905 05/add-to-EAX 4/imm32 + 906 50/push-EAX + 907 # . . call + 908 e8/call clear-stream/disp32 + 909 # . . discard args + 910 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 911 # . clear-stream(_test-error-stream) + 912 # . . push args + 913 68/push _test-error-stream/imm32 + 914 # . . call + 915 e8/call clear-stream/disp32 + 916 # . . discard args + 917 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 918 # . clear-stream(_test-error-buffered-file+4) + 919 # . . push args + 920 b8/copy-to-EAX _test-error-buffered-file/imm32 + 921 05/add-to-EAX 4/imm32 + 922 50/push-EAX + 923 # . . call + 924 e8/call clear-stream/disp32 + 925 # . . discard args + 926 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 927 # initialize '_test-stream' to input with leading comment and more whitespace after newline + 928 # . write(_test-stream, comment) + 929 # . . push args + 930 68/push "#x"/imm32 + 931 68/push _test-stream/imm32 + 932 # . . call + 933 e8/call write/disp32 + 934 # . . discard args + 935 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 936 # . write(_test-stream, Newline) + 937 # . . push args + 938 68/push Newline/imm32 + 939 68/push _test-stream/imm32 + 940 # . . call + 941 e8/call write/disp32 + 942 # . . discard args + 943 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 944 # . write(_test-stream, real text) + 945 # . . push args + 946 68/push " ab"/imm32 + 947 68/push _test-stream/imm32 + 948 # . . call + 949 e8/call write/disp32 + 950 # . . discard args + 951 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 952 # initialize exit-descriptor 'ed' for the call to 'scan-next-byte' below + 953 # . var ed/ECX : exit-descriptor + 954 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP + 955 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX + 956 # . tailor-exit-descriptor(ed, 12) + 957 # . . push args + 958 68/push 0xc/imm32/nbytes-of-args-for-scan-next-byte + 959 51/push-ECX/ed + 960 # . . call + 961 e8/call tailor-exit-descriptor/disp32 + 962 # . . discard args + 963 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 964 # EAX = scan-next-byte(_test-buffered-file, _test-error-buffered-file, ed) + 965 # . . push args + 966 51/push-ECX/ed + 967 68/push _test-error-buffered-file/imm32 + 968 68/push _test-buffered-file/imm32 + 969 # . . call + 970 e8/call scan-next-byte/disp32 + 971 # registers except ESP may be clobbered at this point + 972 # pop args to scan-next-byte + 973 # . . discard first 2 args + 974 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 975 # . . restore ed + 976 59/pop-to-ECX + 977 # check that scan-next-byte didn't abort + 978 # . check-ints-equal(ed->value, 0, msg) + 979 # . . push args + 980 68/push "F - test-scan-next-byte-skips-comment-and-whitespace: unexpected abort"/imm32 + 981 68/push 0/imm32 + 982 # . . push ed->value + 983 ff 6/subop/push 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 . # push *(ECX+4) + 984 # . . call + 985 e8/call check-ints-equal/disp32 + 986 # . . discard args + 987 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 988 # return if abort + 989 81 7/subop/compare 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 0/imm32 # compare *(ECX+4) + 990 75/jump-if-not-equal $test-scan-next-byte-skips-comment-and-whitespace:end/disp8 + 991 # check-ints-equal(EAX, 0x61/a, msg) + 992 # . . push args + 993 68/push "F - test-scan-next-byte-skips-comment-and-whitespace"/imm32 + 994 68/push 0x61/imm32/a + 995 50/push-EAX + 996 # . . call + 997 e8/call check-ints-equal/disp32 + 998 # . . discard args + 999 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1000 $test-scan-next-byte-skips-comment-and-whitespace:end: +1001 # . epilog +1002 # don't restore ESP from EBP; manually reclaim locals +1003 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1004 5d/pop-to-EBP +1005 c3/return +1006 +1007 test-scan-next-byte-skips-whitespace-and-comment: +1008 # - check that the first byte after any whitespace and comments is returned +1009 # This test uses exit-descriptors. Use EBP for setting up local variables. +1010 55/push-EBP +1011 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +1012 # clear all streams +1013 # . clear-stream(_test-stream) +1014 # . . push args +1015 68/push _test-stream/imm32 +1016 # . . call +1017 e8/call clear-stream/disp32 +1018 # . . discard args +1019 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1020 # . clear-stream(_test-buffered-file+4) +1021 # . . push args +1022 b8/copy-to-EAX _test-buffered-file/imm32 +1023 05/add-to-EAX 4/imm32 +1024 50/push-EAX +1025 # . . call +1026 e8/call clear-stream/disp32 +1027 # . . discard args +1028 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1029 # . clear-stream(_test-error-stream) +1030 # . . push args +1031 68/push _test-error-stream/imm32 +1032 # . . call +1033 e8/call clear-stream/disp32 +1034 # . . discard args +1035 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1036 # . clear-stream(_test-error-buffered-file+4) +1037 # . . push args +1038 b8/copy-to-EAX _test-error-buffered-file/imm32 +1039 05/add-to-EAX 4/imm32 +1040 50/push-EAX +1041 # . . call +1042 e8/call clear-stream/disp32 +1043 # . . discard args +1044 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1045 # initialize '_test-stream' to input with leading whitespace and comment +1046 # . write(_test-stream, comment) +1047 # . . push args +1048 68/push " #x"/imm32 +1049 68/push _test-stream/imm32 +1050 # . . call +1051 e8/call write/disp32 +1052 # . . discard args +1053 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1054 # . write(_test-stream, Newline) +1055 # . . push args +1056 68/push Newline/imm32 +1057 68/push _test-stream/imm32 +1058 # . . call +1059 e8/call write/disp32 +1060 # . . discard args +1061 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1062 # . write(_test-stream, real text) +1063 # . . push args +1064 68/push "ab"/imm32 +1065 68/push _test-stream/imm32 +1066 # . . call +1067 e8/call write/disp32 +1068 # . . discard args +1069 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1070 # initialize exit-descriptor 'ed' for the call to 'scan-next-byte' below +1071 # . var ed/ECX : exit-descriptor +1072 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP +1073 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +1074 # . tailor-exit-descriptor(ed, 12) +1075 # . . push args +1076 68/push 0xc/imm32/nbytes-of-args-for-scan-next-byte +1077 51/push-ECX/ed +1078 # . . call +1079 e8/call tailor-exit-descriptor/disp32 +1080 # . . discard args +1081 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1082 # EAX = scan-next-byte(_test-buffered-file, _test-error-buffered-file, ed) +1083 # . . push args +1084 51/push-ECX/ed +1085 68/push _test-error-buffered-file/imm32 +1086 68/push _test-buffered-file/imm32 +1087 # . . call +1088 e8/call scan-next-byte/disp32 +1089 # registers except ESP may be clobbered at this point +1090 # pop args to scan-next-byte +1091 # . . discard first 2 args +1092 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1093 # . . restore ed +1094 59/pop-to-ECX +1095 # check that scan-next-byte didn't abort +1096 # . check-ints-equal(ed->value, 0, msg) +1097 # . . push args +1098 68/push "F - test-scan-next-byte-skips-whitespace-and-comment: unexpected abort"/imm32 +1099 68/push 0/imm32 +1100 # . . push ed->value +1101 ff 6/subop/push 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 . # push *(ECX+4) +1102 # . . call +1103 e8/call check-ints-equal/disp32 +1104 # . . discard args +1105 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1106 # return if abort +1107 81 7/subop/compare 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 0/imm32 # compare *(ECX+4) +1108 75/jump-if-not-equal $test-scan-next-byte-skips-whitespace-and-comment:end/disp8 +1109 # check-ints-equal(EAX, 0x61/a, msg) +1110 # . . push args +1111 68/push "F - test-scan-next-byte-skips-whitespace-and-comment"/imm32 +1112 68/push 0x61/imm32/a +1113 50/push-EAX +1114 # . . call +1115 e8/call check-ints-equal/disp32 +1116 # . . discard args +1117 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1118 $test-scan-next-byte-skips-whitespace-and-comment:end: +1119 # . epilog +1120 # don't restore ESP from EBP; manually reclaim locals +1121 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1122 5d/pop-to-EBP +1123 c3/return +1124 +1125 test-scan-next-byte-reads-final-byte: +1126 # - check that the final byte in input is returned +1127 # This test uses exit-descriptors. Use EBP for setting up local variables. +1128 55/push-EBP +1129 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +1130 # clear all streams +1131 # . clear-stream(_test-stream) +1132 # . . push args +1133 68/push _test-stream/imm32 +1134 # . . call +1135 e8/call clear-stream/disp32 +1136 # . . discard args +1137 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1138 # . clear-stream(_test-buffered-file+4) +1139 # . . push args +1140 b8/copy-to-EAX _test-buffered-file/imm32 +1141 05/add-to-EAX 4/imm32 +1142 50/push-EAX +1143 # . . call +1144 e8/call clear-stream/disp32 +1145 # . . discard args +1146 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1147 # . clear-stream(_test-error-stream) +1148 # . . push args +1149 68/push _test-error-stream/imm32 +1150 # . . call +1151 e8/call clear-stream/disp32 +1152 # . . discard args +1153 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1154 # . clear-stream(_test-error-buffered-file+4) +1155 # . . push args +1156 b8/copy-to-EAX _test-error-buffered-file/imm32 +1157 05/add-to-EAX 4/imm32 +1158 50/push-EAX +1159 # . . call +1160 e8/call clear-stream/disp32 +1161 # . . discard args +1162 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1163 # initialize '_test-stream' to input with single character +1164 # . write(_test-stream, character) +1165 # . . push args +1166 68/push "a"/imm32 +1167 68/push _test-stream/imm32 +1168 # . . call +1169 e8/call write/disp32 +1170 # . . discard args +1171 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1172 # initialize exit-descriptor 'ed' for the call to 'scan-next-byte' below +1173 # . var ed/ECX : exit-descriptor +1174 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP +1175 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +1176 # . tailor-exit-descriptor(ed, 12) +1177 # . . push args +1178 68/push 0xc/imm32/nbytes-of-args-for-scan-next-byte +1179 51/push-ECX/ed +1180 # . . call +1181 e8/call tailor-exit-descriptor/disp32 +1182 # . . discard args +1183 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1184 # EAX = scan-next-byte(_test-buffered-file, _test-error-buffered-file, ed) +1185 # . . push args +1186 51/push-ECX/ed +1187 68/push _test-error-buffered-file/imm32 +1188 68/push _test-buffered-file/imm32 +1189 # . . call +1190 e8/call scan-next-byte/disp32 +1191 # registers except ESP may be clobbered at this point +1192 # pop args to scan-next-byte +1193 # . . discard first 2 args +1194 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1195 # . . restore ed +1196 59/pop-to-ECX +1197 # check that scan-next-byte didn't abort +1198 # . check-ints-equal(ed->value, 0, msg) +1199 # . . push args +1200 68/push "F - test-scan-next-byte-reads-final-byte: unexpected abort"/imm32 +1201 68/push 0/imm32 +1202 # . . push ed->value +1203 ff 6/subop/push 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 . # push *(ECX+4) +1204 # . . call +1205 e8/call check-ints-equal/disp32 +1206 # . . discard args +1207 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1208 # return if abort +1209 81 7/subop/compare 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 0/imm32 # compare *(ECX+4) +1210 75/jump-if-not-equal $test-scan-next-byte-reads-final-byte:end/disp8 +1211 # check-ints-equal(EAX, 0x61/a, msg) +1212 # . . push args +1213 68/push "F - test-scan-next-byte-reads-final-byte"/imm32 +1214 68/push 0x61/imm32/a +1215 50/push-EAX +1216 # . . call +1217 e8/call check-ints-equal/disp32 +1218 # . . discard args +1219 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1220 $test-scan-next-byte-reads-final-byte:end: +1221 # . epilog +1222 # don't restore ESP from EBP; manually reclaim locals +1223 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1224 5d/pop-to-EBP +1225 c3/return +1226 +1227 test-scan-next-byte-handles-eof: +1228 # - check that the right sentinel value is returned when there's no data remaining to be read +1229 # This test uses exit-descriptors. Use EBP for setting up local variables. +1230 55/push-EBP +1231 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +1232 # clear all streams +1233 # . clear-stream(_test-stream) +1234 # . . push args +1235 68/push _test-stream/imm32 +1236 # . . call +1237 e8/call clear-stream/disp32 +1238 # . . discard args +1239 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1240 # . clear-stream(_test-buffered-file+4) +1241 # . . push args +1242 b8/copy-to-EAX _test-buffered-file/imm32 +1243 05/add-to-EAX 4/imm32 +1244 50/push-EAX +1245 # . . call +1246 e8/call clear-stream/disp32 +1247 # . . discard args +1248 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1249 # . clear-stream(_test-error-stream) +1250 # . . push args +1251 68/push _test-error-stream/imm32 +1252 # . . call +1253 e8/call clear-stream/disp32 +1254 # . . discard args +1255 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1256 # . clear-stream(_test-error-buffered-file+4) +1257 # . . push args +1258 b8/copy-to-EAX _test-error-buffered-file/imm32 +1259 05/add-to-EAX 4/imm32 +1260 50/push-EAX +1261 # . . call +1262 e8/call clear-stream/disp32 +1263 # . . discard args +1264 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1265 # leave '_test-stream' empty +1266 # initialize exit-descriptor 'ed' for the call to 'scan-next-byte' below +1267 # . var ed/ECX : exit-descriptor +1268 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP +1269 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +1270 # . tailor-exit-descriptor(ed, 12) +1271 # . . push args +1272 68/push 0xc/imm32/nbytes-of-args-for-scan-next-byte +1273 51/push-ECX/ed +1274 # . . call +1275 e8/call tailor-exit-descriptor/disp32 +1276 # . . discard args +1277 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1278 # EAX = scan-next-byte(_test-buffered-file, _test-error-buffered-file, ed) +1279 # . . push args +1280 51/push-ECX/ed +1281 68/push _test-error-buffered-file/imm32 +1282 68/push _test-buffered-file/imm32 +1283 # . . call +1284 e8/call scan-next-byte/disp32 +1285 # registers except ESP may be clobbered at this point +1286 # pop args to scan-next-byte +1287 # . . discard first 2 args +1288 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1289 # . . restore ed +1290 59/pop-to-ECX +1291 # check that scan-next-byte didn't abort +1292 # . check-ints-equal(ed->value, 0, msg) +1293 # . . push args +1294 68/push "F - test-scan-next-byte-handles-eof: unexpected abort"/imm32 +1295 68/push 0/imm32 +1296 # . . push ed->value +1297 ff 6/subop/push 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 . # push *(ECX+4) +1298 # . . call +1299 e8/call check-ints-equal/disp32 +1300 # . . discard args +1301 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1302 # return if abort +1303 81 7/subop/compare 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 0/imm32 # compare *(ECX+4) +1304 75/jump-if-not-equal $test-scan-next-byte-handles-eof:end/disp8 +1305 # check-ints-equal(EAX, 0xffffffff/eof, msg) +1306 # . . push args +1307 68/push "F - test-scan-next-byte-handles-eof"/imm32 +1308 68/push 0xffffffff/imm32/eof +1309 50/push-EAX +1310 # . . call +1311 e8/call check-ints-equal/disp32 +1312 # . . discard args +1313 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1314 $test-scan-next-byte-handles-eof:end: +1315 # . epilog +1316 # don't restore ESP from EBP; manually reclaim locals +1317 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1318 5d/pop-to-EBP +1319 c3/return +1320 +1321 test-scan-next-byte-aborts-on-invalid-byte: +1322 # - check that the a bad byte immediately aborts +1323 # This test uses exit-descriptors. Use EBP for setting up local variables. +1324 55/push-EBP +1325 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +1326 # clear all streams +1327 # . clear-stream(_test-stream) +1328 # . . push args +1329 68/push _test-stream/imm32 +1330 # . . call +1331 e8/call clear-stream/disp32 +1332 # . . discard args +1333 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1334 # . clear-stream(_test-buffered-file+4) +1335 # . . push args +1336 b8/copy-to-EAX _test-buffered-file/imm32 +1337 05/add-to-EAX 4/imm32 +1338 50/push-EAX +1339 # . . call +1340 e8/call clear-stream/disp32 +1341 # . . discard args +1342 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1343 # . clear-stream(_test-error-stream) +1344 # . . push args +1345 68/push _test-error-stream/imm32 +1346 # . . call +1347 e8/call clear-stream/disp32 +1348 # . . discard args +1349 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1350 # . clear-stream(_test-error-buffered-file+4) +1351 # . . push args +1352 b8/copy-to-EAX _test-error-buffered-file/imm32 +1353 05/add-to-EAX 4/imm32 +1354 50/push-EAX +1355 # . . call +1356 e8/call clear-stream/disp32 +1357 # . . discard args +1358 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1359 # initialize '_test-stream' to "x" +1360 # . write(_test-stream, "x") +1361 # . . push args +1362 68/push "x"/imm32 +1363 68/push _test-stream/imm32 +1364 # . . call +1365 e8/call write/disp32 +1366 # . . discard args +1367 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1368 # initialize exit-descriptor 'ed' for the call to 'scan-next-byte' below +1369 # . var ed/ECX : exit-descriptor +1370 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP +1371 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +1372 # . tailor-exit-descriptor(ed, 12) +1373 # . . push args +1374 68/push 0xc/imm32/nbytes-of-args-for-scan-next-byte +1375 51/push-ECX/ed +1376 # . . call +1377 e8/call tailor-exit-descriptor/disp32 +1378 # . . discard args +1379 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1380 # EAX = scan-next-byte(_test-buffered-file, _test-error-buffered-file, ed) +1381 # . . push args +1382 51/push-ECX/ed +1383 68/push _test-error-buffered-file/imm32 +1384 68/push _test-buffered-file/imm32 +1385 # . . call +1386 e8/call scan-next-byte/disp32 +1387 # registers except ESP may be clobbered at this point +1388 # pop args to scan-next-byte +1389 # . . discard first 2 args +1390 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1391 # . . restore ed +1392 59/pop-to-ECX +1393 # check that scan-next-byte aborted +1394 # . check-ints-equal(ed->value, 2, msg) +1395 # . . push args +1396 68/push "F - test-scan-next-byte-aborts-on-invalid-byte"/imm32 +1397 68/push 2/imm32 +1398 # . . push ed->value +1399 ff 6/subop/push 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 . # push *(ECX+4) +1400 # . . call +1401 e8/call check-ints-equal/disp32 +1402 # . . discard args +1403 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1404 $test-scan-next-byte-aborts-on-invalid-byte:end: +1405 # . epilog +1406 # don't restore ESP from EBP; manually reclaim locals +1407 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1408 5d/pop-to-EBP +1409 c3/return +1410 +1411 is-hex-lowercase-byte?: # c : byte -> bool/EAX +1412 # . prolog +1413 55/push-EBP +1414 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +1415 # . save registers +1416 51/push-ECX +1417 # ECX = c +1418 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 1/r32/ECX 8/disp8 . # copy *(EBP+8) to ECX +1419 # return false if c < '0' +1420 b8/copy-to-EAX 0/imm32/false +1421 81 7/subop/compare 3/mod/direct 1/rm32/ECX . . . . . 0x30/imm32 # compare ECX +1422 7c/jump-if-lesser $is-hex-lowercase-byte?:end/disp8 +1423 # return false if c > 'f' +1424 81 7/subop/compare 3/mod/direct 1/rm32/ECX . . . . . 0x66/imm32 # compare ECX +1425 7f/jump-if-greater $is-hex-lowercase-byte?:end/disp8 +1426 # return true if c <= '9' +1427 b8/copy-to-EAX 1/imm32/true +1428 81 7/subop/compare 3/mod/direct 1/rm32/ECX . . . . . 0x39/imm32 # compare ECX +1429 7e/jump-if-lesser-or-equal $is-hex-lowercase-byte?:end/disp8 +1430 # return true if c >= 'a' +1431 81 7/subop/compare 3/mod/direct 1/rm32/ECX . . . . . 0x61/imm32 # compare ECX +1432 7d/jump-if-greater-or-equal $is-hex-lowercase-byte?:end/disp8 +1433 # otherwise return false +1434 b8/copy-to-EAX 0/imm32/false +1435 $is-hex-lowercase-byte?:end: +1436 # . restore registers +1437 59/pop-to-ECX +1438 # . epilog +1439 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +1440 5d/pop-to-EBP +1441 c3/return +1442 +1443 test-hex-below-0: +1444 # is-hex-lowercase-byte?(0x2f) +1445 # . . push args +1446 68/push 0x2f/imm32 +1447 # . . call +1448 e8/call is-hex-lowercase-byte?/disp32 +1449 # . . discard args +1450 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1451 # check-ints-equal(EAX, 0, msg) +1452 # . . push args +1453 68/push "F - test-hex-below-0"/imm32 +1454 68/push 0/imm32/false +1455 50/push-EAX +1456 # . . call +1457 e8/call check-ints-equal/disp32 +1458 # . . discard args +1459 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1460 c3/return +1461 +1462 test-hex-0-to-9: +1463 # is-hex-lowercase-byte?(0x30) +1464 # . . push args +1465 68/push 0x30/imm32 +1466 # . . call +1467 e8/call is-hex-lowercase-byte?/disp32 +1468 # . . discard args +1469 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1470 # check-ints-equal(EAX, 1, msg) +1471 # . . push args +1472 68/push "F - test-hex-at-0"/imm32 +1473 68/push 1/imm32/true +1474 50/push-EAX +1475 # . . call +1476 e8/call check-ints-equal/disp32 +1477 # . . discard args +1478 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1479 # is-hex-lowercase-byte?(0x39) +1480 # . . push args +1481 68/push 0x39/imm32 +1482 # . . call +1483 e8/call is-hex-lowercase-byte?/disp32 +1484 # . . discard args +1485 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1486 # check-ints-equal(EAX, 1, msg) +1487 # . . push args +1488 68/push "F - test-hex-at-9"/imm32 +1489 68/push 1/imm32/true +1490 50/push-EAX +1491 # . . call +1492 e8/call check-ints-equal/disp32 +1493 # . . discard args +1494 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1495 c3/return +1496 +1497 test-hex-above-9-to-a: +1498 # is-hex-lowercase-byte?(0x3a) +1499 # . . push args +1500 68/push 0x3a/imm32 +1501 # . . call +1502 e8/call is-hex-lowercase-byte?/disp32 +1503 # . . discard args +1504 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1505 # check-ints-equal(EAX, 0, msg) +1506 # . . push args +1507 68/push "F - test-hex-above-9-to-a"/imm32 +1508 68/push 0/imm32/false +1509 50/push-EAX +1510 # . . call +1511 e8/call check-ints-equal/disp32 +1512 # . . discard args +1513 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1514 c3/return +1515 +1516 test-hex-a-to-f: +1517 # is-hex-lowercase-byte?(0x61) +1518 # . . push args +1519 68/push 0x61/imm32 +1520 # . . call +1521 e8/call is-hex-lowercase-byte?/disp32 +1522 # . . discard args +1523 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1524 # check-ints-equal(EAX, 1, msg) +1525 # . . push args +1526 68/push "F - test-hex-at-a"/imm32 +1527 68/push 1/imm32/true +1528 50/push-EAX +1529 # . . call +1530 e8/call check-ints-equal/disp32 +1531 # . . discard args +1532 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1533 # is-hex-lowercase-byte?(0x66) +1534 # . . push args +1535 68/push 0x66/imm32 +1536 # . . call +1537 e8/call is-hex-lowercase-byte?/disp32 +1538 # . . discard args +1539 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1540 # check-ints-equal(EAX, 1, msg) +1541 # . . push args +1542 68/push "F - test-hex-at-f"/imm32 +1543 68/push 1/imm32/true +1544 50/push-EAX +1545 # . . call +1546 e8/call check-ints-equal/disp32 +1547 # . . discard args +1548 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1549 c3/return +1550 +1551 test-hex-above-f: +1552 # is-hex-lowercase-byte?(0x67) +1553 # . . push args +1554 68/push 0x67/imm32 +1555 # . . call +1556 e8/call is-hex-lowercase-byte?/disp32 +1557 # . . discard args +1558 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1559 # check-ints-equal(EAX, 0, msg) +1560 # . . push args +1561 68/push "F - test-hex-above-f"/imm32 +1562 68/push 0/imm32/false +1563 50/push-EAX +1564 # . . call +1565 e8/call check-ints-equal/disp32 +1566 # . . discard args +1567 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1568 c3/return +1569 +1570 parse-hex-digit: # in/EAX : byte -> out/EAX : num +1571 # no error checking; accepts argument in EAX +1572 # if EAX <= '9' return EAX - '0' +1573 3d/compare-EAX 0x39/imm32/9 +1574 7f/jump-if-greater $parse-hex-digit:else/disp8 +1575 2d/subtract-from-EAX 0x30/imm32/0 +1576 c3/return +1577 $parse-hex-digit:else: +1578 # otherwise return EAX - 'a' + 10 +1579 2d/subtract-from-EAX 0x57/imm32/a-10 +1580 c3/return +1581 +1582 skip-until-newline: # in : (address buffered-file) -> <void> +1583 # pseudocode: +1584 # push EAX +1585 # repeatedly: +1586 # EAX = read-byte(in) +1587 # if EAX == 0xffffffff break +1588 # if EAX == 0x0a break +1589 # pop EAX +1590 # . prolog +1591 55/push-EBP +1592 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +1593 # . save registers +1594 50/push-EAX +1595 $skip-until-newline:loop: +1596 # . EAX = read-byte(in) +1597 # . . push args +1598 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) +1599 # . . call +1600 e8/call read-byte/disp32 +1601 # . . discard args +1602 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1603 # . if EAX == 0xffffffff break +1604 81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0xffffffff/imm32 # compare EAX +1605 74/jump-if-equal $skip-until-newline:end/disp8 +1606 # . if EAX != 0xa/newline loop +1607 81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0xa/imm32 # compare EAX +1608 75/jump-if-not-equal $skip-until-newline:loop/disp8 +1609 $skip-until-newline:end: +1610 # . restore registers +1611 58/pop-to-EAX +1612 # . epilog +1613 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +1614 5d/pop-to-EBP +1615 c3/return +1616 +1617 test-skip-until-newline: +1618 # - check that the read pointer points after the newline +1619 # setup +1620 # . clear-stream(_test-stream) +1621 # . . push args +1622 68/push _test-stream/imm32 +1623 # . . call +1624 e8/call clear-stream/disp32 +1625 # . . discard args +1626 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1627 # . clear-stream(_test-buffered-file+4) +1628 # . . push args +1629 b8/copy-to-EAX _test-buffered-file/imm32 +1630 05/add-to-EAX 4/imm32 +1631 50/push-EAX +1632 # . . call +1633 e8/call clear-stream/disp32 +1634 # . . discard args +1635 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1636 # initialize '_test-stream' to "abc\nde" +1637 # . write(_test-stream, "abc") +1638 # . . push args +1639 68/push "abc"/imm32 +1640 68/push _test-stream/imm32 +1641 # . . call +1642 e8/call write/disp32 +1643 # . . discard args +1644 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1645 # . write(_test-stream, Newline) +1646 # . . push args +1647 68/push Newline/imm32 +1648 68/push _test-stream/imm32 +1649 # . . call +1650 e8/call write/disp32 +1651 # . . discard args +1652 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1653 # . write(_test-stream, "de") +1654 # . . push args +1655 68/push "de"/imm32 +1656 68/push _test-stream/imm32 +1657 # . . call +1658 e8/call write/disp32 +1659 # . . discard args +1660 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1661 # skip-until-newline(_test-buffered-file) +1662 # . . push args +1663 68/push _test-buffered-file/imm32 +1664 # . . call +1665 e8/call skip-until-newline/disp32 +1666 # . . discard args +1667 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1668 # check-ints-equal(_test-buffered-file->read, 4, msg) +1669 # . . push args +1670 68/push "F - test-skip-until-newline"/imm32 +1671 68/push 4/imm32 +1672 b8/copy-to-EAX _test-buffered-file/imm32 +1673 ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 8/disp8 . # push *(EAX+8) +1674 # . . call +1675 e8/call check-ints-equal/disp32 +1676 # . . discard args +1677 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1678 # . end +1679 c3/return +1680 +1681 == data +1682 +1683 _test-error-stream: +1684 # current write index +1685 00 00 00 00 +1686 # current read index +1687 00 00 00 00 +1688 # length (= 8) +1689 08 00 00 00 +1690 # data +1691 00 00 00 00 00 00 00 00 # 8 bytes +1692 +1693 # a test buffered file for _test-stream +1694 _test-error-buffered-file: +1695 # file descriptor or (address stream) +1696 _test-error-stream/imm32 +1697 # current write index +1698 00 00 00 00 +1699 # current read index +1700 00 00 00 00 +1701 # length (6) +1702 06 00 00 00 +1703 # data +1704 00 00 00 00 00 00 # 6 bytes +1705 +1706 # . . vim:nowrap:textwidth=0 -- cgit 1.4.1-2-gfad0