From 52daf0722f7f4ad9d3f29e3cbbbaddde066f49f3 Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Mon, 20 May 2019 01:44:06 -0700 Subject: 5211 Update syntax-highlighted renderings after a _long_ time. --- html/subx/apps/dquotes.subx.html | 3465 +++++++++++++++++++++++++++----------- 1 file changed, 2473 insertions(+), 992 deletions(-) (limited to 'html/subx/apps/dquotes.subx.html') diff --git a/html/subx/apps/dquotes.subx.html b/html/subx/apps/dquotes.subx.html index 02fd6761..0645f2f4 100644 --- a/html/subx/apps/dquotes.subx.html +++ b/html/subx/apps/dquotes.subx.html @@ -16,6 +16,7 @@ a { color:inherit; } * { font-size:12pt; font-size: 1em; } .subxComment { color: #005faf; } .subxS2Comment { color: #8a8a8a; } +.subxMinorFunction { color: #875f5f; } .LineNr { } .subxS1Comment { color: #0000af; } .SpecialChar { color: #d70000; } @@ -82,1017 +83,2497 @@ if ('onhashchange' in window) { 19 # . op subop mod rm32 base index scale r32 20 # . 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 21 - 22 Entry: # run tests if necessary, convert stdin if not - 23 - 24 # for debugging: run a single test - 25 #? e8/call test-next-word-returns-string-with-escapes/disp32 - 26 #? 8b/copy 0/mod/indirect 5/rm32/.disp32 . . 3/r32/EBX Num-test-failures/disp32 # copy *Num-test-failures to EBX - 27 #? eb/jump $main:end/disp8 - 28 - 29 # . prolog - 30 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP - 31 # - if argc > 1 and argv[1] == "test", then return run_tests() - 32 # . argc > 1 - 33 81 7/subop/compare 1/mod/*+disp8 5/rm32/EBP . . . . 0/disp8 1/imm32 # compare *EBP - 34 7e/jump-if-lesser-or-equal $run-main/disp8 - 35 # . argv[1] == "test" - 36 # . . push args - 37 68/push "test"/imm32 - 38 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) - 39 # . . call - 40 e8/call kernel-string-equal?/disp32 - 41 # . . discard args - 42 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 43 # . check result - 44 3d/compare-EAX-and 1/imm32 - 45 75/jump-if-not-equal $run-main/disp8 - 46 # . run-tests() - 47 e8/call run-tests/disp32 - 48 8b/copy 0/mod/indirect 5/rm32/.disp32 . . 3/r32/EBX Num-test-failures/disp32 # copy *Num-test-failures to EBX - 49 eb/jump $main:end/disp8 - 50 $run-main: - 51 # - otherwise convert stdin - 52 # var ed/EAX : exit-descriptor - 53 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP - 54 89/copy 3/mod/direct 0/rm32/EAX . . . 4/r32/ESP . . # copy ESP to EAX - 55 # configure ed to really exit() - 56 # . ed->target = 0 - 57 c7 0/subop/copy 0/mod/direct 0/rm32/EAX . . . . . 0/imm32 # copy to *EAX - 58 # return convert(Stdin, 1/stdout, 2/stderr, ed) - 59 # . . push args - 60 50/push-EAX/ed - 61 68/push Stderr/imm32 - 62 68/push Stdout/imm32 - 63 68/push Stdin/imm32 - 64 # . . call - 65 e8/call convert/disp32 - 66 # . . discard args - 67 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP - 68 # . syscall(exit, 0) - 69 bb/copy-to-EBX 0/imm32 - 70 $main:end: - 71 b8/copy-to-EAX 1/imm32/exit - 72 cd/syscall 0x80/imm8 - 73 - 74 convert: # in : (address buffered-file), out : (address buffered-file) -> <void> - 75 # pseudocode: - 76 # var line = new-stream(512, 1) - 77 # var new-data-segment = new-stream(Heap, Segment-size, 1) - 78 # write-stream(new-data-segment, "== data\n") - 79 # while true - 80 # clear-stream(line) - 81 # read-line(in, line) - 82 # if (line->write == 0) break # end of file - 83 # while true - 84 # var word-slice = next-word(line) - 85 # if slice-empty?(word-slice) # end of line - 86 # break - 87 # if slice-starts-with?(word-slice, "#") # comment - 88 # continue - 89 # if slice-starts-with?(word-slice, '"') # string literal <== what we're here for - 90 # process-string-literal(word-slice, out, new-data-segment) - 91 # else - 92 # write-slice(out, word-slice) - 93 # write-stream-data(out, new-data-segment) - 94 # flush(out) - 95 # - 96 # . prolog - 97 55/push-EBP - 98 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP - 99 # . save registers - 100 50/push-EAX - 101 51/push-ECX - 102 52/push-EDX - 103 53/push-EBX - 104 56/push-ESI - 105 57/push-EDI - 106 # var line/ECX : (address stream byte) = stream(512) - 107 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 0x200/imm32 # subtract from ESP - 108 68/push 0x200/imm32/length - 109 68/push 0/imm32/read - 110 68/push 0/imm32/write - 111 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX - 112 # var word-slice/EDX = {0, 0} - 113 68/push 0/imm32/end - 114 68/push 0/imm32/curr - 115 89/copy 3/mod/direct 2/rm32/EDX . . . 4/r32/ESP . . # copy ESP to EDX - 116 # new-data-segment/EDI = new-stream(Heap, Segment-size, 1) - 117 # . EAX = new-stream(Heap, Segment-size, 1) - 118 # . . push args - 119 68/push 1/imm32 - 120 ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 . . . Segment-size/disp32 # push *Segment-size - 121 68/push Heap/imm32 - 122 # . . call - 123 e8/call new-stream/disp32 - 124 # . . discard args - 125 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 126 # . EDI = EAX - 127 89/copy 3/mod/direct 7/rm32/EDI . . . 0/r32/EAX . . # copy EAX to EDI - 128 # write(new-data-segment, "== data\n") - 129 # . . push args - 130 68/push "== data\n"/imm32 - 131 57/push-EDI - 132 # . . call - 133 e8/call write/disp32 - 134 # . . discard args - 135 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 136 $convert:line-loop: - 137 # clear-stream(line) - 138 # . . push args - 139 51/push-ECX - 140 # . . call - 141 e8/call clear-stream/disp32 - 142 # . . discard args - 143 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 144 # read-line(in, line) + 22 Entry: + 23 # initialize heap + 24 # . Heap = new-segment(64KB) + 25 # . . push args + 26 68/push Heap/imm32 + 27 68/push 0x10000/imm32/64KB + 28 # . . call + 29 e8/call new-segment/disp32 + 30 # . . discard args + 31 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 32 + 33 # for debugging: run a single test + 34 #? e8/call test-string-length-at-start-of-slice-escaped/disp32 + 35 #? 8b/copy 0/mod/indirect 5/rm32/.disp32 . . 3/r32/EBX Num-test-failures/disp32 # copy *Num-test-failures to EBX + 36 #? eb/jump $main:end/disp8 + 37 + 38 # run tests if necessary, convert stdin if not + 39 # . prolog + 40 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + 41 # - if argc > 1 and argv[1] == "test", then return run_tests() + 42 # . argc > 1 + 43 81 7/subop/compare 1/mod/*+disp8 5/rm32/EBP . . . . 0/disp8 1/imm32 # compare *EBP + 44 7e/jump-if-lesser-or-equal $run-main/disp8 + 45 # . argv[1] == "test" + 46 # . . push args + 47 68/push "test"/imm32 + 48 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) + 49 # . . call + 50 e8/call kernel-string-equal?/disp32 + 51 # . . discard args + 52 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 53 # . check result + 54 3d/compare-EAX-and 1/imm32 + 55 75/jump-if-not-equal $run-main/disp8 + 56 # . run-tests() + 57 e8/call run-tests/disp32 + 58 8b/copy 0/mod/indirect 5/rm32/.disp32 . . 3/r32/EBX Num-test-failures/disp32 # copy *Num-test-failures to EBX + 59 eb/jump $main:end/disp8 + 60 $run-main: + 61 # - otherwise convert stdin + 62 # var ed/EAX : exit-descriptor + 63 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP + 64 89/copy 3/mod/direct 0/rm32/EAX . . . 4/r32/ESP . . # copy ESP to EAX + 65 # configure ed to really exit() + 66 # . ed->target = 0 + 67 c7 0/subop/copy 0/mod/direct 0/rm32/EAX . . . . . 0/imm32 # copy to *EAX + 68 # return convert(Stdin, 1/stdout, 2/stderr, ed) + 69 # . . push args + 70 50/push-EAX/ed + 71 68/push Stderr/imm32 + 72 68/push Stdout/imm32 + 73 68/push Stdin/imm32 + 74 # . . call + 75 e8/call convert/disp32 + 76 # . . discard args + 77 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP + 78 # . syscall(exit, 0) + 79 bb/copy-to-EBX 0/imm32 + 80 $main:end: + 81 b8/copy-to-EAX 1/imm32/exit + 82 cd/syscall 0x80/imm8 + 83 + 84 # conceptual hierarchy within a line: + 85 # line = words separated by ' ', maybe followed by comment starting with '#' + 86 # word = datum until '/', then 0 or more metadata separated by '/' + 87 + 88 convert: # in : (address buffered-file), out : (address buffered-file) -> <void> + 89 # pseudocode: + 90 # var line = new-stream(512, 1) + 91 # var new-data-segment = new-stream(Heap, Segment-size, 1) + 92 # write-stream(new-data-segment, "== data\n") + 93 # while true + 94 # clear-stream(line) + 95 # read-line-buffered(in, line) + 96 # if (line->write == 0) break # end of file + 97 # while true + 98 # var word-slice = next-word(line) + 99 # if slice-empty?(word-slice) # end of line + 100 # break + 101 # if slice-starts-with?(word-slice, "#") # comment + 102 # continue + 103 # if slice-starts-with?(word-slice, '"') # string literal <== what we're here for + 104 # process-string-literal(word-slice, out, new-data-segment) + 105 # else + 106 # write-slice-buffered(out, word-slice) + 107 # write(out, " ") + 108 # write(out, "\n\n") + 109 # write-stream-data(out, new-data-segment) + 110 # flush(out) + 111 # + 112 # . prolog + 113 55/push-EBP + 114 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + 115 # . save registers + 116 50/push-EAX + 117 51/push-ECX + 118 52/push-EDX + 119 53/push-EBX + 120 56/push-ESI + 121 57/push-EDI + 122 # var line/ECX : (address stream byte) = stream(512) + 123 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 0x200/imm32 # subtract from ESP + 124 68/push 0x200/imm32/length + 125 68/push 0/imm32/read + 126 68/push 0/imm32/write + 127 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX + 128 # var word-slice/EDX = {0, 0} + 129 68/push 0/imm32/end + 130 68/push 0/imm32/curr + 131 89/copy 3/mod/direct 2/rm32/EDX . . . 4/r32/ESP . . # copy ESP to EDX + 132 # new-data-segment/EDI = new-stream(Heap, Segment-size, 1) + 133 # . EAX = new-stream(Heap, Segment-size, 1) + 134 # . . push args + 135 68/push 1/imm32 + 136 ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 . . . Segment-size/disp32 # push *Segment-size + 137 68/push Heap/imm32 + 138 # . . call + 139 e8/call new-stream/disp32 + 140 # . . discard args + 141 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 142 # . EDI = EAX + 143 89/copy 3/mod/direct 7/rm32/EDI . . . 0/r32/EAX . . # copy EAX to EDI + 144 # write(new-data-segment, "== data\n") 145 # . . push args - 146 51/push-ECX - 147 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) + 146 68/push "== data\n"/imm32 + 147 57/push-EDI 148 # . . call - 149 e8/call read-line/disp32 + 149 e8/call write/disp32 150 # . . discard args 151 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 152 $convert:check0: - 153 # if (line->write == 0) break - 154 81 7/subop/compare 0/mod/indirect 1/rm32/ECX . . . . . 0/imm32 # compare *ECX - 155 0f 84/jump-if-equal $convert:break/disp32 - 156 $convert:word-loop: - 157 # next-word(line, word-slice) - 158 # . . push args - 159 52/push-EDX - 160 51/push-ECX - 161 # . . call - 162 e8/call next-word/disp32 - 163 # . . discard args - 164 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 165 $convert:check1: - 166 # if (slice-empty?(word-slice)) break - 167 # . EAX = slice-empty?(word-slice) - 168 # . . push args - 169 52/push-EDX - 170 # . . call - 171 e8/call slice-empty?/disp32 - 172 # . . discard args - 173 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 174 # . if (EAX != 0) break - 175 3d/compare-EAX-and 0/imm32 - 176 0f 85/jump-if-not-equal $convert:next-line/disp32 - 177 $convert:check-for-comment: - 178 # if (slice-starts-with?(word-slice, "#")) continue - 179 # . start/ESI = word-slice->start - 180 8b/copy 0/mod/indirect 2/rm32/EDX . . . 6/r32/ESI . . # copy *EDX to ESI - 181 # . c/EAX = *start - 182 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX - 183 8a/copy-byte 0/mod/indirect 6/rm32/ESI . . . 0/r32/AL . . # copy byte at *ESI to AL - 184 # . if (EAX == '#') continue - 185 3d/compare-EAX-and 0x23/imm32/hash - 186 74/jump-if-equal $convert:word-loop/disp8 - 187 $convert:check-for-string-literal: - 188 3d/compare-EAX-and 0x22/imm32/hash - 189 75/jump-if-not-equal $convert:regular-word/disp8 - 190 $convert:string-literal: - 191 # process-string-literal(word-slice, out, new-data-segment) - 192 # . . push args - 193 57/push-EDI - 194 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) - 195 52/push-EDX - 196 # . . call - 197 e8/call process-string-literal/disp32 - 198 # . . discard args - 199 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 200 # continue - 201 eb/jump $convert:next-word/disp8 - 202 $convert:regular-word: - 203 # write-slice(out, word-slice) - 204 # . . push args - 205 52/push-EDX - 206 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) - 207 # . . call - 208 e8/call write-slice/disp32 - 209 # . . discard args - 210 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 211 # fall through - 212 $convert:next-word: - 213 # write-buffered(out, " ") - 214 # . . push args - 215 68/push " "/imm32 - 216 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) - 217 # . . call - 218 e8/call write-buffered/disp32 - 219 # . . discard args - 220 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 221 # loop - 222 eb/jump $convert:word-loop/disp8 - 223 $convert:next-line: - 224 # write-buffered(out, "\n") - 225 # . . push args - 226 68/push Newline/imm32 - 227 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) - 228 # . . call - 229 e8/call write-buffered/disp32 - 230 # . . discard args - 231 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 232 # loop - 233 e9/jump $convert:line-loop/disp32 - 234 $convert:break: - 235 $convert:end: - 236 # . reclaim locals - 237 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x214/imm32 # add to ESP - 238 # . restore registers - 239 5f/pop-to-EDI - 240 5e/pop-to-ESI - 241 5b/pop-to-EBX - 242 5a/pop-to-EDX - 243 59/pop-to-ECX - 244 58/pop-to-EAX - 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 # Write out 'string-literal' in a new format to 'out-segment', assign it a new - 251 # label, and write the new label out to 'out'. - 252 process-string-literal: # string-literal : (address slice), out : (address buffered-file), out-segment : (address stream) - 253 # pseudocode: - 254 # print(out-segment, "_string#{Next-string-literal}:\n") - 255 # emit-string-literal-data(out-segment, string-literal) - 256 # print(out, "_string#{Next-string-literal}") - 257 # emit-metadata(out, string-literal) - 258 # ++ *Next-string-literal - 259 # - 260 # . prolog - 261 55/push-EBP - 262 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP - 263 # . save registers - 264 51/push-ECX - 265 # var int32-stream/ECX = stream(10) # number of decimal digits a 32-bit number can have - 266 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 0xa/imm32 # subtract from ESP - 267 68/push 0xa/imm32/decimal-digits-in-32bit-number - 268 68/push 0/imm32/read - 269 68/push 0/imm32/write - 270 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX - 271 # print(out-segment, "_string#{Next-string-literal}:\n") - 272 # . write(out-segment, "_string") - 273 # . . push args - 274 68/push "_string"/imm32 - 275 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0x10/disp8 . # push *(EBP+16) - 276 # . . call - 277 e8/call write/disp32 - 278 # . . discard args - 279 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 280 # . print-int32-decimal(out-segment, *Next-string-literal) - 281 # . write(out-segment, ":\n") - 282 # . . push args - 283 68/push ":\n"/imm32 - 284 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0x10/disp8 . # push *(EBP+16) - 285 # . . call - 286 e8/call write/disp32 - 287 # . . discard args - 288 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 289 # emit-string-literal-data(out-segment, string-literal) - 290 # write(out-segment, "\n") - 291 # . . push args - 292 68/push Newline/imm32 - 293 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0x10/disp8 . # push *(EBP+16) - 294 # . . call - 295 e8/call write/disp32 - 296 # . . discard args - 297 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 298 # print(out, "_string#{Next-string-literal}") - 299 # . write-buffered(out, "_string") - 300 # . . push args - 301 68/push "_string"/imm32 - 302 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) - 303 # . . call - 304 e8/call write-buffered/disp32 - 305 # . . discard args - 306 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 307 # . print-int32-decimal(tmp, *Next-string-literal) - 308 # emit-metadata(out, string-literal) - 309 # ++ *Next-string-literal - 310 ff 0/subop/increment 0/mod/indirect 5/rm32/.disp32 . . . Next-string-literal/disp32 # increment *Num-test-failures - 311 $process-string-literal:end: - 312 # . reclaim locals - 313 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x16/imm32 # add to ESP - 314 # . restore registers - 315 59/pop-to-ECX - 316 # . epilog - 317 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP - 318 5d/pop-to-EBP - 319 c3/return - 320 - 321 test-convert-is-idempotent-by-default: - 322 # . prolog - 323 55/push-EBP - 324 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP - 325 # setup - 326 # . clear-stream(_test-input-stream) - 327 # . . push args - 328 68/push _test-input-stream/imm32 - 329 # . . call - 330 e8/call clear-stream/disp32 - 331 # . . discard args - 332 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 333 # . clear-stream(_test-input-buffered-file+4) - 334 # . . push args - 335 b8/copy-to-EAX _test-input-buffered-file/imm32 - 336 05/add-to-EAX 4/imm32 - 337 50/push-EAX - 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 # . clear-stream(_test-output-stream) - 343 # . . push args - 344 68/push _test-output-stream/imm32 - 345 # . . call - 346 e8/call clear-stream/disp32 - 347 # . . discard args - 348 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 349 # . clear-stream(_test-output-buffered-file+4) - 350 # . . push args - 351 b8/copy-to-EAX _test-output-buffered-file/imm32 - 352 05/add-to-EAX 4/imm32 - 353 50/push-EAX - 354 # . . call - 355 e8/call clear-stream/disp32 - 356 # . . discard args - 357 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 358 # initialize input (meta comments in parens) - 359 # # comment 1 - 360 # # comment 2 indented - 361 # == code (new segment) - 362 # # comment 3 inside a segment - 363 # 1 - 364 # (empty line) - 365 # 2 3 # comment 4 inline with other contents - 366 # == data (new segment) - 367 # 4 5/imm32 - 368 # . write(_test-input-stream, "# comment 1\n") + 152 $convert:line-loop: + 153 # clear-stream(line) + 154 # . . push args + 155 51/push-ECX + 156 # . . call + 157 e8/call clear-stream/disp32 + 158 # . . discard args + 159 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 160 # read-line-buffered(in, line) + 161 # . . push args + 162 51/push-ECX + 163 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) + 164 # . . call + 165 e8/call read-line-buffered/disp32 + 166 # . . discard args + 167 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 168 $convert:check0: + 169 # if (line->write == 0) break + 170 81 7/subop/compare 0/mod/indirect 1/rm32/ECX . . . . . 0/imm32 # compare *ECX + 171 0f 84/jump-if-equal $convert:break/disp32 + 172 $convert:word-loop: + 173 # next-word(line, word-slice) + 174 # . . push args + 175 52/push-EDX + 176 51/push-ECX + 177 # . . call + 178 e8/call next-word/disp32 + 179 # . . discard args + 180 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 181 $convert:check1: + 182 # if (slice-empty?(word-slice)) break + 183 # . EAX = slice-empty?(word-slice) + 184 # . . push args + 185 52/push-EDX + 186 # . . call + 187 e8/call slice-empty?/disp32 + 188 # . . discard args + 189 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 190 # . if (EAX != 0) break + 191 3d/compare-EAX-and 0/imm32 + 192 0f 85/jump-if-not-equal $convert:next-line/disp32 + 193 $convert:check-for-comment: + 194 # if (slice-starts-with?(word-slice, "#")) continue + 195 # . start/ESI = word-slice->start + 196 8b/copy 0/mod/indirect 2/rm32/EDX . . . 6/r32/ESI . . # copy *EDX to ESI + 197 # . c/EAX = *start + 198 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX + 199 8a/copy-byte 0/mod/indirect 6/rm32/ESI . . . 0/r32/AL . . # copy byte at *ESI to AL + 200 # . if (EAX == '#') continue + 201 3d/compare-EAX-and 0x23/imm32/hash + 202 74/jump-if-equal $convert:word-loop/disp8 + 203 $convert:check-for-string-literal: + 204 3d/compare-EAX-and 0x22/imm32/hash + 205 75/jump-if-not-equal $convert:regular-word/disp8 + 206 $convert:string-literal: + 207 # process-string-literal(word-slice, out, new-data-segment) + 208 # . . push args + 209 57/push-EDI + 210 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) + 211 52/push-EDX + 212 # . . call + 213 e8/call process-string-literal/disp32 + 214 # . . discard args + 215 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 216 # continue + 217 eb/jump $convert:next-word/disp8 + 218 $convert:regular-word: + 219 # write-slice-buffered(out, word-slice) + 220 # . . push args + 221 52/push-EDX + 222 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) + 223 # . . call + 224 e8/call write-slice-buffered/disp32 + 225 # . . discard args + 226 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 227 # fall through + 228 $convert:next-word: + 229 # write-buffered(out, " ") + 230 # . . push args + 231 68/push " "/imm32 + 232 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) + 233 # . . call + 234 e8/call write-buffered/disp32 + 235 # . . discard args + 236 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 237 # loop + 238 eb/jump $convert:word-loop/disp8 + 239 $convert:next-line: + 240 # write-buffered(out, "\n") + 241 # . . push args + 242 68/push Newline/imm32 + 243 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) + 244 # . . call + 245 e8/call write-buffered/disp32 + 246 # . . discard args + 247 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 248 # loop + 249 e9/jump $convert:line-loop/disp32 + 250 $convert:break: + 251 # write-stream-data(out, new-data-segment) + 252 # . . push args + 253 57/push-EDI + 254 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) + 255 # . . call + 256 e8/call write-stream-data/disp32 + 257 # . . discard args + 258 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 259 # flush(out) + 260 # . . push args + 261 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) + 262 # . . call + 263 e8/call flush/disp32 + 264 # . . discard args + 265 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 266 $convert:end: + 267 # . reclaim locals + 268 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x214/imm32 # add to ESP + 269 # . restore registers + 270 5f/pop-to-EDI + 271 5e/pop-to-ESI + 272 5b/pop-to-EBX + 273 5a/pop-to-EDX + 274 59/pop-to-ECX + 275 58/pop-to-EAX + 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 # Write out 'string-literal' in a new format to 'out-segment', assign it a new + 282 # label, and write the new label out to 'out'. + 283 process-string-literal: # string-literal : (address slice), out : (address buffered-file), out-segment : (address stream) + 284 # pseudocode: + 285 # print(out-segment, "_string#{Next-string-literal}:\n") + 286 # emit-string-literal-data(out-segment, string-literal) + 287 # print(out, "_string#{Next-string-literal}") + 288 # emit-metadata(out, string-literal) + 289 # ++ *Next-string-literal + 290 # + 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 51/push-ECX + 296 # var int32-stream/ECX = stream(10) # number of decimal digits a 32-bit number can have + 297 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 0xa/imm32 # subtract from ESP + 298 68/push 0xa/imm32/decimal-digits-in-32bit-number + 299 68/push 0/imm32/read + 300 68/push 0/imm32/write + 301 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX + 302 # print(out-segment, "_string#{Next-string-literal}:\n") + 303 # . write(out-segment, "_string") + 304 # . . push args + 305 68/push "_string"/imm32 + 306 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0x10/disp8 . # push *(EBP+16) + 307 # . . call + 308 e8/call write/disp32 + 309 # . . discard args + 310 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 311 # . print-int32-decimal(out-segment, *Next-string-literal) + 312 # . . push args + 313 ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 . . . Next-string-literal/disp32 # push *Next-string-literal + 314 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0x10/disp8 . # push *(EBP+16) + 315 # . . call + 316 e8/call print-int32-decimal/disp32 + 317 # . . discard args + 318 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 319 # . write(out-segment, ":\n") + 320 # . . push args + 321 68/push ":\n"/imm32 + 322 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0x10/disp8 . # push *(EBP+16) + 323 # . . call + 324 e8/call write/disp32 + 325 # . . discard args + 326 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 327 # emit-string-literal-data(out-segment, string-literal) + 328 # . . push args + 329 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0x8/disp8 . # push *(EBP+8) + 330 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0x10/disp8 . # push *(EBP+16) + 331 # . . call + 332 e8/call emit-string-literal-data/disp32 + 333 # . . discard args + 334 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 335 # write(out-segment, "\n") + 336 # . . push args + 337 68/push Newline/imm32 + 338 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0x10/disp8 . # push *(EBP+16) + 339 # . . call + 340 e8/call write/disp32 + 341 # . . discard args + 342 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 343 # print(out, "_string#{Next-string-literal}") + 344 # . write-buffered(out, "_string") + 345 # . . push args + 346 68/push "_string"/imm32 + 347 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) + 348 # . . call + 349 e8/call write-buffered/disp32 + 350 # . . discard args + 351 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 352 # . print-int32-decimal(int32-stream, *Next-string-literal) + 353 # . . push args + 354 ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 . . . Next-string-literal/disp32 # push *Next-string-literal + 355 51/push-ECX + 356 # . . call + 357 e8/call print-int32-decimal/disp32 + 358 # . . discard args + 359 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 360 # . write-stream-data(out, int32-stream) + 361 # . . push args + 362 51/push-ECX + 363 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) + 364 # . . call + 365 e8/call write-stream-data/disp32 + 366 # . . discard args + 367 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 368 # emit-metadata(out, string-literal) 369 # . . push args - 370 68/push "# comment 1\n"/imm32 - 371 68/push _test-input-stream/imm32 + 370 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) + 371 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) 372 # . . call - 373 e8/call write/disp32 + 373 e8/call emit-metadata/disp32 374 # . . discard args 375 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 376 # . write(_test-input-stream, " # comment 2 indented\n") - 377 # . . push args - 378 68/push " # comment 2 indented\n"/imm32 - 379 68/push _test-input-stream/imm32 - 380 # . . call - 381 e8/call write/disp32 - 382 # . . discard args - 383 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 384 # . write(_test-input-stream, "== code\n") - 385 # . . push args - 386 68/push "== code\n"/imm32 - 387 68/push _test-input-stream/imm32 - 388 # . . call - 389 e8/call write/disp32 - 390 # . . discard args - 391 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 392 # . write(_test-input-stream, "# comment 3 inside a segment\n") - 393 # . . push args - 394 68/push "# comment 3 inside a segment\n"/imm32 + 376 # ++ *Next-string-literal + 377 ff 0/subop/increment 0/mod/indirect 5/rm32/.disp32 . . . Next-string-literal/disp32 # increment *Num-test-failures + 378 $process-string-literal:end: + 379 # . reclaim locals + 380 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x16/imm32 # add to ESP + 381 # . restore registers + 382 59/pop-to-ECX + 383 # . epilog + 384 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP + 385 5d/pop-to-EBP + 386 c3/return + 387 + 388 test-convert-is-idempotent-by-default: + 389 # . prolog + 390 55/push-EBP + 391 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + 392 # setup + 393 # . clear-stream(_test-input-stream) + 394 # . . push args 395 68/push _test-input-stream/imm32 396 # . . call - 397 e8/call write/disp32 + 397 e8/call clear-stream/disp32 398 # . . discard args - 399 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 400 # . write(_test-input-stream, "1\n") + 399 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 400 # . clear-stream(_test-input-buffered-file+4) 401 # . . push args - 402 68/push "1\n"/imm32 - 403 68/push _test-input-stream/imm32 - 404 # . . call - 405 e8/call write/disp32 - 406 # . . discard args - 407 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 408 # . write(_test-input-stream, "\n") # empty line - 409 # . . push args - 410 68/push "\n"/imm32 - 411 68/push _test-input-stream/imm32 + 402 b8/copy-to-EAX _test-input-buffered-file/imm32 + 403 05/add-to-EAX 4/imm32 + 404 50/push-EAX + 405 # . . call + 406 e8/call clear-stream/disp32 + 407 # . . discard args + 408 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 409 # . clear-stream(_test-output-stream) + 410 # . . push args + 411 68/push _test-output-stream/imm32 412 # . . call - 413 e8/call write/disp32 + 413 e8/call clear-stream/disp32 414 # . . discard args - 415 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 416 # . write(_test-input-stream, "2 3 # comment 4 inline with other contents\n") + 415 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 416 # . clear-stream(_test-output-buffered-file+4) 417 # . . push args - 418 68/push "2 3 # comment 4 inline with other contents\n"/imm32 - 419 68/push _test-input-stream/imm32 - 420 # . . call - 421 e8/call write/disp32 - 422 # . . discard args - 423 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 424 # . write(_test-input-stream, "== data\n") - 425 # . . push args - 426 68/push "== data\n"/imm32 - 427 68/push _test-input-stream/imm32 - 428 # . . call - 429 e8/call write/disp32 - 430 # . . discard args - 431 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 432 # . write(_test-input-stream, "4 5/imm32\n") - 433 # . . push args - 434 68/push "4 5/imm32\n"/imm32 - 435 68/push _test-input-stream/imm32 - 436 # . . call - 437 e8/call write/disp32 - 438 # . . discard args - 439 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 440 # convert(_test-input-buffered-file, _test-output-buffered-file) - 441 # . . push args - 442 68/push _test-output-buffered-file/imm32 - 443 68/push _test-input-buffered-file/imm32 - 444 # . . call - 445 e8/call convert/disp32 - 446 # . . discard args - 447 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 448 # . flush(_test-output-buffered-file) - 449 # . . push args - 450 68/push _test-output-buffered-file/imm32 - 451 # . . call - 452 e8/call flush/disp32 - 453 # . . discard args - 454 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 455 # check output - 456 # (comment dropped for now) - 457 # (comment dropped for now) - 458 # == code - 459 # (comment dropped for now) - 460 # 1 - 461 # (comment dropped for now) - 462 # 2 3 - 463 # == data - 464 # 4 5/imm32 - 465 # We don't care right now what exactly happens to comments. Trailing spaces are also minor details. - 466 +-- 26 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- - 492 # . check-next-stream-line-equal(_test-output-stream, "", msg) - 493 # . . push args - 494 68/push "F - test-convert/0"/imm32 - 495 68/push ""/imm32 - 496 68/push _test-output-stream/imm32 - 497 # . . call - 498 e8/call check-next-stream-line-equal/disp32 - 499 # . . discard args - 500 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 501 # . check-next-stream-line-equal(_test-output-stream, "", msg) - 502 # . . push args - 503 68/push "F - test-convert/1"/imm32 - 504 68/push ""/imm32 - 505 68/push _test-output-stream/imm32 - 506 # . . call - 507 e8/call check-next-stream-line-equal/disp32 - 508 # . . discard args - 509 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 510 # . check-next-stream-line-equal(_test-output-stream, "== code ", msg) - 511 # . . push args - 512 68/push "F - test-convert/2"/imm32 - 513 68/push "== code "/imm32 - 514 68/push _test-output-stream/imm32 - 515 # . . call - 516 e8/call check-next-stream-line-equal/disp32 - 517 # . . discard args - 518 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 519 # . check-next-stream-line-equal(_test-output-stream, "", msg) - 520 # . . push args - 521 68/push "F - test-convert/3"/imm32 - 522 68/push ""/imm32 - 523 68/push _test-output-stream/imm32 - 524 # . . call - 525 e8/call check-next-stream-line-equal/disp32 - 526 # . . discard args - 527 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 528 # . check-next-stream-line-equal(_test-output-stream, "1 ", msg) - 529 # . . push args - 530 68/push "F - test-convert/4"/imm32 - 531 68/push "1 "/imm32 - 532 68/push _test-output-stream/imm32 - 533 # . . call - 534 e8/call check-next-stream-line-equal/disp32 - 535 # . . discard args - 536 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 537 # . check-next-stream-line-equal(_test-output-stream, "", msg) - 538 # . . push args - 539 68/push "F - test-convert/5"/imm32 - 540 68/push ""/imm32 - 541 68/push _test-output-stream/imm32 - 542 # . . call - 543 e8/call check-next-stream-line-equal/disp32 - 544 # . . discard args - 545 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 546 # . check-next-stream-line-equal(_test-output-stream, "2 3 ", msg) - 547 # . . push args - 548 68/push "F - test-convert/6"/imm32 - 549 68/push "2 3 "/imm32 - 550 68/push _test-output-stream/imm32 - 551 # . . call - 552 e8/call check-next-stream-line-equal/disp32 - 553 # . . discard args - 554 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 555 # . check-next-stream-line-equal(_test-output-stream, "== data ", msg) - 556 # . . push args - 557 68/push "F - test-convert/7"/imm32 - 558 68/push "== data "/imm32 - 559 68/push _test-output-stream/imm32 - 560 # . . call - 561 e8/call check-next-stream-line-equal/disp32 - 562 # . . discard args - 563 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 564 # . check-next-stream-line-equal(_test-output-stream, "4 5/imm32 ", msg) - 565 # . . push args - 566 68/push "F - test-convert/8"/imm32 - 567 68/push "4 5/imm32 "/imm32 - 568 68/push _test-output-stream/imm32 - 569 # . . call - 570 e8/call check-next-stream-line-equal/disp32 - 571 # . . discard args - 572 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 573 # . epilog - 574 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP - 575 5d/pop-to-EBP - 576 c3/return - 577 - 578 # (re)compute the bounds of the next word in the line - 579 # return empty string on reaching end of file - 580 next-word: # line : (address stream byte), out : (address slice) - 581 # . prolog - 582 55/push-EBP - 583 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP - 584 # . save registers - 585 50/push-EAX - 586 51/push-ECX - 587 56/push-ESI - 588 57/push-EDI - 589 # ESI = line - 590 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 6/r32/ESI 8/disp8 . # copy *(EBP+8) to ESI - 591 # EDI = out - 592 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 7/r32/EDI 0xc/disp8 . # copy *(EBP+12) to EDI - 593 # skip-chars-matching(line, ' ') - 594 # . . push args - 595 68/push 0x20/imm32/space - 596 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) - 597 # . . call - 598 e8/call skip-chars-matching/disp32 - 599 # . . discard args - 600 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 601 $next-word:check0: - 602 # if (line->read >= line->write) clear out and return - 603 # . EAX = line->read - 604 8b/copy 1/mod/*+disp8 6/rm32/ESI . . . 0/r32/EAX 4/disp8 . # copy *(ESI+4) to EAX - 605 # . if (EAX < line->write) goto next check - 606 3b/compare 0/mod/indirect 6/rm32/ESI . . . 0/r32/EAX . . # compare EAX with *ESI - 607 7c/jump-if-lesser $next-word:check-for-comment/disp8 - 608 # . return out = {0, 0} - 609 c7 0/subop/copy 0/mod/direct 7/rm32/EDI . . . . . 0/imm32 # copy to *EDI - 610 c7 0/subop/copy 1/mod/*+disp8 7/rm32/EDI . . . . 4/disp8 0/imm32 # copy to *(EDI+4) - 611 eb/jump $next-word:end/disp8 - 612 $next-word:check-for-comment: - 613 # out->start = &line->data[line->read] - 614 8b/copy 1/mod/*+disp8 6/rm32/ESI . . . 1/r32/ECX 4/disp8 . # copy *(ESI+4) to ECX - 615 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 - 616 89/copy 0/mod/indirect 7/rm32/EDI . . . 0/r32/EAX . . # copy EAX to *EDI - 617 # if line->data[line->read] == '#' - 618 # . EAX = line->data[line->read] - 619 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX - 620 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 - 621 # . compare - 622 3d/compare-EAX-and 0x23/imm32/pound - 623 75/jump-if-not-equal $next-word:check-for-string-literal/disp8 - 624 $next-word:comment: - 625 # out->end = &line->data[line->write] - 626 8b/copy 0/mod/indirect 6/rm32/ESI . . . 0/r32/EAX . . # copy *ESI to EAX - 627 8d/copy-address 1/mod/*+disp8 4/rm32/sib 6/base/ESI 0/index/EAX . 0/r32/EAX 0xc/disp8 . # copy ESI+EAX+12 to EAX - 628 89/copy 1/mod/*+disp8 7/rm32/EDI . . . 0/r32/EAX 4/disp8 . # copy EAX to *(EDI+4) - 629 # line->read = line->write # skip rest of line - 630 89/copy 1/mod/*+disp8 6/rm32/ESI . . . 0/r32/EAX 4/disp8 . # copy EAX to *(ESI+4) - 631 # return - 632 eb/jump $next-word:end/disp8 - 633 $next-word:check-for-string-literal: - 634 # if line->data[line->read] == '"' - 635 # . EAX = line->data[line->read] - 636 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX - 637 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 - 638 # . compare - 639 3d/compare-EAX-and 0x22/imm32/dquote - 640 75/jump-if-not-equal $next-word:regular-word/disp8 - 641 $next-word:string-literal: - 642 # ++line->read # skip '"' - 643 # . persist line->read - 644 89/copy 1/mod/*+disp8 6/rm32/ESI . . . 1/r32/ECX 4/disp8 . # copy ECX to *(ESI+4) - 645 # . ++line->read - 646 ff 0/subop/increment 1/mod/*+disp8 6/rm32/ESI . . . . 4/disp8 . # increment *(ESI+4) - 647 # parse-string(line, out) - 648 # . . push args - 649 57/push-EDI - 650 56/push-ESI - 651 # . . call - 652 e8/call parse-string/disp32 - 653 # . . discard args - 654 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 655 # fall through - 656 $next-word:regular-word: - 657 # otherwise skip-chars-not-matching-whitespace(line) # including trailing newline + 418 b8/copy-to-EAX _test-output-buffered-file/imm32 + 419 05/add-to-EAX 4/imm32 + 420 50/push-EAX + 421 # . . call + 422 e8/call clear-stream/disp32 + 423 # . . discard args + 424 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 425 # initialize input (meta comments in parens) + 426 # # comment 1 + 427 # # comment 2 indented + 428 # == code 0x1 (new segment) + 429 # # comment 3 inside a segment + 430 # 1 + 431 # (empty line) + 432 # 2 3 # comment 4 inline with other contents + 433 # == data 0x2 (new segment) + 434 # 4 5/imm32 + 435 # . write(_test-input-stream, "# comment 1\n") + 436 # . . push args + 437 68/push "# comment 1\n"/imm32 + 438 68/push _test-input-stream/imm32 + 439 # . . call + 440 e8/call write/disp32 + 441 # . . discard args + 442 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 443 # . write(_test-input-stream, " # comment 2 indented\n") + 444 # . . push args + 445 68/push " # comment 2 indented\n"/imm32 + 446 68/push _test-input-stream/imm32 + 447 # . . call + 448 e8/call write/disp32 + 449 # . . discard args + 450 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 451 # . write(_test-input-stream, "== code 0x1\n") + 452 # . . push args + 453 68/push "== code 0x1\n"/imm32 + 454 68/push _test-input-stream/imm32 + 455 # . . call + 456 e8/call write/disp32 + 457 # . . discard args + 458 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 459 # . write(_test-input-stream, "# comment 3 inside a segment\n") + 460 # . . push args + 461 68/push "# comment 3 inside a segment\n"/imm32 + 462 68/push _test-input-stream/imm32 + 463 # . . call + 464 e8/call write/disp32 + 465 # . . discard args + 466 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 467 # . write(_test-input-stream, "1\n") + 468 # . . push args + 469 68/push "1\n"/imm32 + 470 68/push _test-input-stream/imm32 + 471 # . . call + 472 e8/call write/disp32 + 473 # . . discard args + 474 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 475 # . write(_test-input-stream, "\n") # empty line + 476 # . . push args + 477 68/push "\n"/imm32 + 478 68/push _test-input-stream/imm32 + 479 # . . call + 480 e8/call write/disp32 + 481 # . . discard args + 482 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 483 # . write(_test-input-stream, "2 3 # comment 4 inline with other contents\n") + 484 # . . push args + 485 68/push "2 3 # comment 4 inline with other contents\n"/imm32 + 486 68/push _test-input-stream/imm32 + 487 # . . call + 488 e8/call write/disp32 + 489 # . . discard args + 490 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 491 # . write(_test-input-stream, "== data 0x2\n") + 492 # . . push args + 493 68/push "== data 0x2\n"/imm32 + 494 68/push _test-input-stream/imm32 + 495 # . . call + 496 e8/call write/disp32 + 497 # . . discard args + 498 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 499 # . write(_test-input-stream, "4 5/imm32\n") + 500 # . . push args + 501 68/push "4 5/imm32\n"/imm32 + 502 68/push _test-input-stream/imm32 + 503 # . . call + 504 e8/call write/disp32 + 505 # . . discard args + 506 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 507 # convert(_test-input-buffered-file, _test-output-buffered-file) + 508 # . . push args + 509 68/push _test-output-buffered-file/imm32 + 510 68/push _test-input-buffered-file/imm32 + 511 # . . call + 512 e8/call convert/disp32 + 513 # . . discard args + 514 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 515 # . flush(_test-output-buffered-file) + 516 # . . push args + 517 68/push _test-output-buffered-file/imm32 + 518 # . . call + 519 e8/call flush/disp32 + 520 # . . discard args + 521 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 522 # check output + 523 # (comment dropped for now) + 524 # (comment dropped for now) + 525 # == code 0x1 + 526 # (comment dropped for now) + 527 # 1 + 528 # (comment dropped for now) + 529 # 2 3 + 530 # == data 0x2 + 531 # 4 5/imm32 + 532 # We don't care right now what exactly happens to comments. Trailing spaces are also minor details. + 533 +-- 26 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- + 559 # . check-next-stream-line-equal(_test-output-stream, "", msg) + 560 # . . push args + 561 68/push "F - test-convert-is-idempotent-by-default/0"/imm32 + 562 68/push ""/imm32 + 563 68/push _test-output-stream/imm32 + 564 # . . call + 565 e8/call check-next-stream-line-equal/disp32 + 566 # . . discard args + 567 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 568 # . check-next-stream-line-equal(_test-output-stream, "", msg) + 569 # . . push args + 570 68/push "F - test-convert-is-idempotent-by-default/1"/imm32 + 571 68/push ""/imm32 + 572 68/push _test-output-stream/imm32 + 573 # . . call + 574 e8/call check-next-stream-line-equal/disp32 + 575 # . . discard args + 576 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 577 # . check-next-stream-line-equal(_test-output-stream, "== code 0x1 ", msg) + 578 # . . push args + 579 68/push "F - test-convert-is-idempotent-by-default/2"/imm32 + 580 68/push "== code 0x1 "/imm32 + 581 68/push _test-output-stream/imm32 + 582 # . . call + 583 e8/call check-next-stream-line-equal/disp32 + 584 # . . discard args + 585 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 586 # . check-next-stream-line-equal(_test-output-stream, "", msg) + 587 # . . push args + 588 68/push "F - test-convert-is-idempotent-by-default/3"/imm32 + 589 68/push ""/imm32 + 590 68/push _test-output-stream/imm32 + 591 # . . call + 592 e8/call check-next-stream-line-equal/disp32 + 593 # . . discard args + 594 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 595 # . check-next-stream-line-equal(_test-output-stream, "1 ", msg) + 596 # . . push args + 597 68/push "F - test-convert-is-idempotent-by-default/4"/imm32 + 598 68/push "1 "/imm32 + 599 68/push _test-output-stream/imm32 + 600 # . . call + 601 e8/call check-next-stream-line-equal/disp32 + 602 # . . discard args + 603 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 604 # . check-next-stream-line-equal(_test-output-stream, "", msg) + 605 # . . push args + 606 68/push "F - test-convert-is-idempotent-by-default/5"/imm32 + 607 68/push ""/imm32 + 608 68/push _test-output-stream/imm32 + 609 # . . call + 610 e8/call check-next-stream-line-equal/disp32 + 611 # . . discard args + 612 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 613 # . check-next-stream-line-equal(_test-output-stream, "2 3 ", msg) + 614 # . . push args + 615 68/push "F - test-convert-is-idempotent-by-default/6"/imm32 + 616 68/push "2 3 "/imm32 + 617 68/push _test-output-stream/imm32 + 618 # . . call + 619 e8/call check-next-stream-line-equal/disp32 + 620 # . . discard args + 621 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 622 # . check-next-stream-line-equal(_test-output-stream, "== data 0x2 ", msg) + 623 # . . push args + 624 68/push "F - test-convert-is-idempotent-by-default/7"/imm32 + 625 68/push "== data 0x2 "/imm32 + 626 68/push _test-output-stream/imm32 + 627 # . . call + 628 e8/call check-next-stream-line-equal/disp32 + 629 # . . discard args + 630 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 631 # . check-next-stream-line-equal(_test-output-stream, "4 5/imm32 ", msg) + 632 # . . push args + 633 68/push "F - test-convert-is-idempotent-by-default/8"/imm32 + 634 68/push "4 5/imm32 "/imm32 + 635 68/push _test-output-stream/imm32 + 636 # . . call + 637 e8/call check-next-stream-line-equal/disp32 + 638 # . . discard args + 639 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 640 # . epilog + 641 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP + 642 5d/pop-to-EBP + 643 c3/return + 644 + 645 test-convert-processes-string-literals: + 646 # . prolog + 647 55/push-EBP + 648 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + 649 # setup + 650 # . clear-stream(_test-input-stream) + 651 # . . push args + 652 68/push _test-input-stream/imm32 + 653 # . . call + 654 e8/call clear-stream/disp32 + 655 # . . discard args + 656 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 657 # . clear-stream(_test-input-buffered-file+4) 658 # . . push args - 659 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) - 660 # . . call - 661 e8/call skip-chars-not-matching-whitespace/disp32 - 662 # . . discard args - 663 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 664 # out->end = &line->data[line->read] - 665 8b/copy 1/mod/*+disp8 6/rm32/ESI . . . 1/r32/ECX 4/disp8 . # copy *(ESI+4) to ECX - 666 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 - 667 89/copy 1/mod/*+disp8 7/rm32/EDI . . . 0/r32/EAX 4/disp8 . # copy EAX to *(EDI+4) - 668 $next-word:end: - 669 # . restore registers - 670 5f/pop-to-EDI - 671 5e/pop-to-ESI - 672 59/pop-to-ECX - 673 58/pop-to-EAX - 674 # . epilog - 675 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP - 676 5d/pop-to-EBP - 677 c3/return - 678 - 679 parse-string: # line : (address stream byte), out : (address slice) - 680 # pseudocode: - 681 # ESI = line - 682 # curr/ECX = line->data[line->read] - 683 # max/EDX = line->data[line->write] - 684 # while curr >= max - 685 # if (*curr == '"') ++curr, break - 686 # if (*curr == '\\') curr+=2, continue - 687 # ++curr - 688 # line->read = curr - line->data - 689 # out->end = curr - 690 # - 691 # . prolog - 692 55/push-EBP - 693 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP - 694 # . save registers - 695 50/push-EAX - 696 51/push-ECX - 697 52/push-EDX - 698 56/push-ESI - 699 # ESI = line - 700 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 6/r32/ESI 8/disp8 . # copy *(EBP+8) to ESI - 701 # curr/ECX = &table->data[table->read] - 702 # . ECX = table->read - 703 8b/copy 1/mod/*+disp8 6/rm32/ESI . . . 1/r32/ECX 4/disp8 . # copy *(ESI+4) to ECX - 704 # . ECX = table->data + ECX - 705 8d/copy-address 1/mod/*+disp8 4/rm32/sib 6/base/ESI 1/index/ECX . 1/r32/ECX 0xc/disp8 . # copy ESI+ECX+12 to ECX - 706 # max/EDX = &table->data[table->write] - 707 # . EDX = table->write - 708 8b/copy 0/mod/indirect 6/rm32/ESI . . . 2/r32/EDX . . # copy *ESI to EDX - 709 # . EDX = table->data + EDX - 710 8d/copy-address 1/mod/*+disp8 4/rm32/sib 6/base/ESI 2/index/EDX . 2/r32/EDX 0xc/disp8 . # copy ESI+EDX+12 to EDX - 711 # clear EAX - 712 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX - 713 $parse-string:loop: - 714 # if (curr >= max) break - 715 39/compare 3/mod/direct 1/rm32/ECX . . . 2/r32/EDX . . # compare ECX with EDX - 716 7d/jump-if-greater-or-equal $parse-string:break/disp8 - 717 # c/EAX = *curr - 718 8a/copy-byte 0/mod/indirect 1/rm32/ECX . . . 0/r32/AL . . # copy byte at *ECX to AL - 719 $parse-string:check1: - 720 # if (c == '"') break # rely on caller to skip trailing non-whitespace - 721 3d/compare-EAX-and 0x22/imm32/dquote - 722 74/jump-if-equal $parse-string:break/disp8 - 723 $parse-string:check2: - 724 # if (c == '\\') ++curr - 725 3d/compare-EAX-and 0x5c/imm32/backslash - 726 75/jump-if-not-equal $parse-string:continue/disp8 - 727 # . ++curr - 728 41/increment-ECX - 729 $parse-string:continue: - 730 # ++curr - 731 41/increment-ECX - 732 # loop - 733 eb/jump $parse-string:loop/disp8 - 734 $parse-string:break: - 735 # out->end = curr - 736 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 0/r32/EAX 0xc/disp8 . # copy *(EBP+12) to EDI - 737 89/copy 1/mod/*+disp8 0/rm32/EAX . . . 1/r32/ECX 4/disp8 . # copy ECX to *(EAX+4) - 738 # line->read = curr - line - 12 - 739 29/subtract 3/mod/direct 1/rm32/ECX . . . 6/r32/ESI . . # subtract ESI from ECX - 740 81 5/subop/subtract 3/mod/direct 1/rm32/ECX . . . . . 0xc/imm32 # subtract from ECX - 741 89/copy 1/mod/*+disp8 6/rm32/ESI . . . 1/r32/ECX 4/disp8 . # copy ECX to *(ESI+4) - 742 $parse-string:end: - 743 # . restore registers - 744 5e/pop-to-ESI - 745 5a/pop-to-EDX - 746 59/pop-to-ECX - 747 58/pop-to-EAX - 748 # . epilog - 749 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP - 750 5d/pop-to-EBP - 751 c3/return - 752 - 753 test-next-word: - 754 # . prolog - 755 55/push-EBP - 756 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP - 757 # setup - 758 # . clear-stream(_test-input-stream) - 759 # . . push args - 760 68/push _test-input-stream/imm32 - 761 # . . call - 762 e8/call clear-stream/disp32 - 763 # . . discard args - 764 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 765 # var slice/ECX = {0, 0} - 766 68/push 0/imm32/end - 767 68/push 0/imm32/start - 768 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX - 769 # write(_test-input-stream, " ab") - 770 # . . push args - 771 68/push " ab"/imm32 - 772 68/push _test-input-stream/imm32 - 773 # . . call - 774 e8/call write/disp32 - 775 # . . discard args - 776 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 777 # next-word(_test-input-stream, slice) - 778 # . . push args - 779 51/push-ECX - 780 68/push _test-input-stream/imm32 - 781 # . . call - 782 e8/call next-word/disp32 - 783 # . . discard args - 784 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 785 # check-ints-equal(slice->start - _test-input-stream->data, 2, msg) - 786 # . check-ints-equal(slice->start - _test-input-stream, 14, msg) - 787 # . . push args - 788 68/push "F - test-next-word: start"/imm32 - 789 68/push 0xe/imm32 - 790 # . . push slice->start - _test-input-stream - 791 8b/copy 0/mod/indirect 1/rm32/ECX . . . 0/r32/EAX . . # copy *ECX to EAX - 792 81 5/subop/subtract 3/mod/direct 0/rm32/EAX . . . . . _test-input-stream/imm32 # subtract from EAX - 793 50/push-EAX - 794 # . . call - 795 e8/call check-ints-equal/disp32 - 796 # . . discard args - 797 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 798 # check-ints-equal(slice->end - _test-input-stream->data, 4, msg) - 799 # . check-ints-equal(slice->end - _test-input-stream, 16, msg) + 659 b8/copy-to-EAX _test-input-buffered-file/imm32 + 660 05/add-to-EAX 4/imm32 + 661 50/push-EAX + 662 # . . call + 663 e8/call clear-stream/disp32 + 664 # . . discard args + 665 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 666 # . clear-stream(_test-output-stream) + 667 # . . push args + 668 68/push _test-output-stream/imm32 + 669 # . . call + 670 e8/call clear-stream/disp32 + 671 # . . discard args + 672 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 673 # . clear-stream(_test-output-buffered-file+4) + 674 # . . push args + 675 b8/copy-to-EAX _test-output-buffered-file/imm32 + 676 05/add-to-EAX 4/imm32 + 677 50/push-EAX + 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 # initialize input (meta comments in parens) + 683 # == code (new segment) + 684 # 1 "a"/x + 685 # 2 "bc"/y + 686 68/push "== code 0x1\n"/imm32 + 687 68/push _test-input-stream/imm32 + 688 # . . call + 689 e8/call write/disp32 + 690 # . . discard args + 691 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 692 # . write(_test-input-stream, "1 \"a\"/x\n") + 693 # . . push args + 694 68/push "1 \"a\"/x\n"/imm32 + 695 68/push _test-input-stream/imm32 + 696 # . . call + 697 e8/call write/disp32 + 698 # . . discard args + 699 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 700 # . write(_test-input-stream, "2 \"bc\"/y\n") + 701 # . . push args + 702 68/push "2 \"bc\"/y\n"/imm32 + 703 68/push _test-input-stream/imm32 + 704 # . . call + 705 e8/call write/disp32 + 706 # . . discard args + 707 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 708 # convert(_test-input-buffered-file, _test-output-buffered-file) + 709 # . . push args + 710 68/push _test-output-buffered-file/imm32 + 711 68/push _test-input-buffered-file/imm32 + 712 # . . call + 713 e8/call convert/disp32 + 714 # . . discard args + 715 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 716 # . flush(_test-output-buffered-file) + 717 # . . push args + 718 68/push _test-output-buffered-file/imm32 + 719 # . . call + 720 e8/call flush/disp32 + 721 # . . discard args + 722 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 723 # check output + 724 # == code 0x1 + 725 # 1 _string1/x + 726 # 2 _string2/y + 727 # == data + 728 # _string1: + 729 # 1/imm32 61/a + 730 # _string2: + 731 # 2/imm32 62/b 63/c + 732 # We don't care right now what exactly happens to comments. Trailing spaces are also minor details. + 733 # + 734 # Open question: how to make this check more robust. + 735 # We don't actually care what the auto-generated string variables are + 736 # called. We just want to make sure instructions using string literals + 737 # switch to a string variable with the right value. + 738 # (Modifying string literals completely off the radar for now.) + 739 +-- 33 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- + 772 # . check-next-stream-line-equal(_test-output-stream, "== code 0x1 ", msg) + 773 # . . push args + 774 68/push "F - test-convert-processes-string-literals/0"/imm32 + 775 68/push "== code 0x1 "/imm32 + 776 68/push _test-output-stream/imm32 + 777 # . . call + 778 e8/call check-next-stream-line-equal/disp32 + 779 # . . discard args + 780 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 781 # . check-next-stream-line-equal(_test-output-stream, "1 _string1/x ", msg) + 782 # . . push args + 783 68/push "F - test-convert-processes-string-literals/1"/imm32 + 784 68/push "1 _string1/x "/imm32 + 785 68/push _test-output-stream/imm32 + 786 # . . call + 787 e8/call check-next-stream-line-equal/disp32 + 788 # . . discard args + 789 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 790 # . check-next-stream-line-equal(_test-output-stream, "2 _string2/y ", msg) + 791 # . . push args + 792 68/push "F - test-convert-processes-string-literals/2"/imm32 + 793 68/push "2 _string2/y "/imm32 + 794 68/push _test-output-stream/imm32 + 795 # . . call + 796 e8/call check-next-stream-line-equal/disp32 + 797 # . . discard args + 798 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 799 # . check-next-stream-line-equal(_test-output-stream, "== data ", msg) 800 # . . push args - 801 68/push "F - test-next-word: end"/imm32 - 802 68/push 0x10/imm32 - 803 # . . push slice->end - _test-input-stream - 804 8b/copy 1/mod/*+disp8 1/rm32/ECX . . . 0/r32/EAX 4/disp8 . # copy *(ECX+4) to EAX - 805 81 5/subop/subtract 3/mod/direct 0/rm32/EAX . . . . . _test-input-stream/imm32 # subtract from EAX - 806 50/push-EAX - 807 # . . call - 808 e8/call check-ints-equal/disp32 - 809 # . . discard args - 810 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 811 # . epilog - 812 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP - 813 5d/pop-to-EBP - 814 c3/return - 815 - 816 test-next-word-returns-whole-comment: - 817 # . prolog - 818 55/push-EBP - 819 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP - 820 # setup - 821 # . clear-stream(_test-input-stream) - 822 # . . push args - 823 68/push _test-input-stream/imm32 - 824 # . . call - 825 e8/call clear-stream/disp32 - 826 # . . discard args - 827 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 828 # var slice/ECX = {0, 0} - 829 68/push 0/imm32/end - 830 68/push 0/imm32/start - 831 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX - 832 # write(_test-input-stream, " # a") - 833 # . . push args - 834 68/push " # a"/imm32 - 835 68/push _test-input-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 # next-word(_test-input-stream, slice) - 841 # . . push args - 842 51/push-ECX - 843 68/push _test-input-stream/imm32 - 844 # . . call - 845 e8/call next-word/disp32 - 846 # . . discard args - 847 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 848 # check-ints-equal(slice->start - _test-input-stream->data, 2, msg) - 849 # . check-ints-equal(slice->start - _test-input-stream, 14, msg) - 850 # . . push args - 851 68/push "F - test-next-word-returns-whole-comment: start"/imm32 - 852 68/push 0xe/imm32 - 853 # . . push slice->start - _test-input-stream - 854 8b/copy 0/mod/indirect 1/rm32/ECX . . . 0/r32/EAX . . # copy *ECX to EAX - 855 81 5/subop/subtract 3/mod/direct 0/rm32/EAX . . . . . _test-input-stream/imm32 # subtract from EAX - 856 50/push-EAX - 857 # . . call - 858 e8/call check-ints-equal/disp32 - 859 # . . discard args - 860 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 861 # check-ints-equal(slice->end - _test-input-stream->data, 5, msg) - 862 # . check-ints-equal(slice->end - _test-input-stream, 17, msg) - 863 # . . push args - 864 68/push "F - test-next-word-returns-whole-comment: end"/imm32 - 865 68/push 0x11/imm32 - 866 # . . push slice->end - _test-input-stream - 867 8b/copy 1/mod/*+disp8 1/rm32/ECX . . . 0/r32/EAX 4/disp8 . # copy *(ECX+4) to EAX - 868 81 5/subop/subtract 3/mod/direct 0/rm32/EAX . . . . . _test-input-stream/imm32 # subtract from EAX - 869 50/push-EAX - 870 # . . call - 871 e8/call check-ints-equal/disp32 - 872 # . . discard args - 873 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 874 # . epilog - 875 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP - 876 5d/pop-to-EBP - 877 c3/return - 878 - 879 test-next-word-returns-empty-string-on-eof: - 880 # . prolog - 881 55/push-EBP - 882 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP - 883 # setup - 884 # . clear-stream(_test-input-stream) - 885 # . . push args - 886 68/push _test-input-stream/imm32 + 801 68/push "F - test-convert-processes-string-literals/3"/imm32 + 802 68/push "== data"/imm32 + 803 68/push _test-output-stream/imm32 + 804 # . . call + 805 e8/call check-next-stream-line-equal/disp32 + 806 # . . discard args + 807 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 808 # . check-next-stream-line-equal(_test-output-stream, "_string1: ", msg) + 809 # . . push args + 810 68/push "F - test-convert-processes-string-literals/4"/imm32 + 811 68/push "_string1:"/imm32 + 812 68/push _test-output-stream/imm32 + 813 # . . call + 814 e8/call check-next-stream-line-equal/disp32 + 815 # . . discard args + 816 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 817 # . check-next-stream-line-equal(_test-output-stream, "1/imm32 61/a ", msg) + 818 # . . push args + 819 68/push "F - test-convert-processes-string-literals/5"/imm32 + 820 68/push "0x00000001/imm32 61/a "/imm32 + 821 68/push _test-output-stream/imm32 + 822 # . . call + 823 e8/call check-next-stream-line-equal/disp32 + 824 # . . discard args + 825 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 826 # . check-next-stream-line-equal(_test-output-stream, "_string2: ", msg) + 827 # . . push args + 828 68/push "F - test-convert-processes-string-literals/6"/imm32 + 829 68/push "_string2:"/imm32 + 830 68/push _test-output-stream/imm32 + 831 # . . call + 832 e8/call check-next-stream-line-equal/disp32 + 833 # . . discard args + 834 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 835 # . check-next-stream-line-equal(_test-output-stream, "2/imm32 62/b 63/c ", msg) + 836 # . . push args + 837 68/push "F - test-convert-processes-string-literals/7"/imm32 + 838 68/push "0x00000002/imm32 62/b 63/c "/imm32 + 839 68/push _test-output-stream/imm32 + 840 # . . call + 841 e8/call check-next-stream-line-equal/disp32 + 842 # . . discard args + 843 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 844 # . epilog + 845 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP + 846 5d/pop-to-EBP + 847 c3/return + 848 + 849 # generate the data segment contents byte by byte for a given slice + 850 emit-string-literal-data: # out : (address stream), word : (address slice) + 851 # pseudocode + 852 # len = string-length-at-start-of-slice(word->start, word->end) + 853 # print(out, "#{len}/imm32 ") + 854 # curr = word->start + 855 # ++curr # skip '"' + 856 # while true + 857 # if (curr >= word->end) break + 858 # c = *curr + 859 # if (c == '"') break + 860 # if (c == '\') ++curr, c = *curr + 861 # append-byte-hex(out, c) + 862 # if c is alphanumeric: + 863 # write(out, "/") + 864 # append-byte(out, c) + 865 # write(out, " ") + 866 # ++curr + 867 # + 868 # . prolog + 869 55/push-EBP + 870 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + 871 # . save registers + 872 50/push-EAX + 873 51/push-ECX + 874 52/push-EDX + 875 56/push-ESI + 876 # ESI = word + 877 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 6/r32/ESI 0xc/disp8 . # copy *(EBP+12) to ESI + 878 # curr/EDX = word->start + 879 8b/copy 0/mod/indirect 6/rm32/ESI . . . 2/r32/EDX . . # copy *ESI to EDX + 880 # max/ESI = word->end + 881 8b/copy 1/mod/*+disp8 6/rm32/ESI . . . 6/r32/ESI 4/disp8 . # copy *(ESI+4) to ESI + 882 $emit-string-literal-data:emit-length: + 883 # len/EAX = string-length-at-start-of-slice(word->start, word->end) + 884 # . . push args + 885 56/push-ESI + 886 52/push-EDX 887 # . . call - 888 e8/call clear-stream/disp32 + 888 e8/call string-length-at-start-of-slice/disp32 889 # . . discard args - 890 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 891 # var slice/ECX = {0, 0} - 892 68/push 0/imm32/end - 893 68/push 0/imm32/start - 894 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX - 895 # write nothing to _test-input-stream - 896 # next-word(_test-input-stream, slice) - 897 # . . push args - 898 51/push-ECX - 899 68/push _test-input-stream/imm32 - 900 # . . call - 901 e8/call next-word/disp32 - 902 # . . discard args - 903 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 904 # check-ints-equal(slice->end - slice->start, 0, msg) - 905 # . . push args - 906 68/push "F - test-next-word-returns-empty-string-on-eof"/imm32 - 907 68/push 0/imm32 - 908 # . . push slice->end - slice->start - 909 8b/copy 1/mod/*+disp8 1/rm32/ECX . . . 0/r32/EAX 4/disp8 . # copy *(ECX+4) to EAX - 910 2b/subtract 0/mod/indirect 1/rm32/ECX . . . 0/r32/EAX . . # subtract *ECX from EAX - 911 50/push-EAX - 912 # . . call - 913 e8/call check-ints-equal/disp32 - 914 # . . discard args - 915 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 916 # . epilog - 917 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP - 918 5d/pop-to-EBP - 919 c3/return - 920 - 921 test-next-word-returns-whole-string: - 922 # . prolog - 923 55/push-EBP - 924 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP - 925 # setup - 926 # . clear-stream(_test-input-stream) - 927 # . . push args - 928 68/push _test-input-stream/imm32 - 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 # var slice/ECX = {0, 0} - 934 68/push 0/imm32/end - 935 68/push 0/imm32/start - 936 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX - 937 # write(_test-input-stream, " \"a b\"/imm32 ") - 938 # . . push args - 939 68/push " \"a b\"/imm32 "/imm32 - 940 68/push _test-input-stream/imm32 - 941 # . . call - 942 e8/call write/disp32 - 943 # . . discard args - 944 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 945 # next-word(_test-input-stream, slice) - 946 # . . push args - 947 51/push-ECX - 948 68/push _test-input-stream/imm32 - 949 # . . call - 950 e8/call next-word/disp32 - 951 # . . discard args - 952 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 953 # check-ints-equal(slice->start - _test-input-stream->data, 1, msg) - 954 # . check-ints-equal(slice->start - _test-input-stream, 13, msg) - 955 # . . push args - 956 68/push "F - test-next-word-returns-whole-string: start"/imm32 - 957 68/push 0xd/imm32 - 958 # . . push slice->start - _test-input-stream - 959 8b/copy 0/mod/indirect 1/rm32/ECX . . . 0/r32/EAX . . # copy *ECX to EAX - 960 81 5/subop/subtract 3/mod/direct 0/rm32/EAX . . . . . _test-input-stream/imm32 # subtract from EAX - 961 50/push-EAX - 962 # . . call - 963 e8/call check-ints-equal/disp32 - 964 # . . discard args - 965 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 966 # check-ints-equal(slice->end - _test-input-stream->data, 12, msg) - 967 # . check-ints-equal(slice->end - _test-input-stream, 24, msg) - 968 # . . push args - 969 68/push "F - test-next-word-returns-whole-string: end"/imm32 - 970 68/push 0x18/imm32 - 971 # . . push slice->end - _test-input-stream - 972 8b/copy 1/mod/*+disp8 1/rm32/ECX . . . 0/r32/EAX 4/disp8 . # copy *(ECX+4) to EAX - 973 81 5/subop/subtract 3/mod/direct 0/rm32/EAX . . . . . _test-input-stream/imm32 # subtract from EAX - 974 50/push-EAX - 975 # . . call - 976 e8/call check-ints-equal/disp32 - 977 # . . discard args - 978 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 979 # . epilog - 980 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP - 981 5d/pop-to-EBP - 982 c3/return - 983 - 984 test-next-word-returns-string-with-escapes: - 985 # . prolog - 986 55/push-EBP - 987 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP - 988 # setup - 989 # . clear-stream(_test-input-stream) - 990 # . . push args - 991 68/push _test-input-stream/imm32 - 992 # . . call - 993 e8/call clear-stream/disp32 - 994 # . . discard args - 995 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 996 # var slice/ECX = {0, 0} - 997 68/push 0/imm32/end - 998 68/push 0/imm32/start - 999 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX -1000 # write(_test-input-stream, " \"a\\\"b\"/x") -1001 # . . push args -1002 68/push " \"a\\\"b\"/x"/imm32 -1003 68/push _test-input-stream/imm32 -1004 # . . call -1005 e8/call write/disp32 -1006 # . . discard args -1007 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1008 # next-word(_test-input-stream, slice) -1009 # . . push args -1010 51/push-ECX -1011 68/push _test-input-stream/imm32 -1012 # . . call -1013 e8/call next-word/disp32 -1014 # . . discard args -1015 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1016 # check-ints-equal(slice->start - _test-input-stream->data, 1, msg) -1017 # . check-ints-equal(slice->start - _test-input-stream, 13, msg) -1018 # . . push args -1019 68/push "F - test-next-word-returns-string-with-escapes: start"/imm32 -1020 68/push 0xd/imm32 -1021 # . . push slice->start - _test-input-stream -1022 8b/copy 0/mod/indirect 1/rm32/ECX . . . 0/r32/EAX . . # copy *ECX to EAX -1023 81 5/subop/subtract 3/mod/direct 0/rm32/EAX . . . . . _test-input-stream/imm32 # subtract from EAX -1024 50/push-EAX -1025 # . . call -1026 e8/call check-ints-equal/disp32 -1027 # . . discard args -1028 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1029 # check-ints-equal(slice->end - _test-input-stream->data, 9, msg) -1030 # . check-ints-equal(slice->end - _test-input-stream, 21, msg) -1031 # . . push args -1032 68/push "F - test-next-word-returns-string-with-escapes: end"/imm32 -1033 68/push 0x15/imm32 -1034 # . . push slice->end - _test-input-stream -1035 8b/copy 1/mod/*+disp8 1/rm32/ECX . . . 0/r32/EAX 4/disp8 . # copy *(ECX+4) to EAX -1036 81 5/subop/subtract 3/mod/direct 0/rm32/EAX . . . . . _test-input-stream/imm32 # subtract from EAX -1037 50/push-EAX -1038 # . . call -1039 e8/call check-ints-equal/disp32 -1040 # . . discard args -1041 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1042 # . epilog -1043 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -1044 5d/pop-to-EBP -1045 c3/return -1046 -1047 == data -1048 -1049 Segment-size: -1050 # TODO: there's currently a tight size limit on segments because we aren't growing the heap -1051 0x100/imm32 -1052 #? 0x1000/imm32/4KB -1053 -1054 Next-string-literal: -1055 1/imm32 -1056 -1057 # . . vim:nowrap:textwidth=0 + 890 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 891 # print(out, "#{len}/imm32 ") + 892 # . print-int32(out, len) + 893 # . . push args + 894 50/push-EAX + 895 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) + 896 # . . call + 897 e8/call print-int32/disp32 + 898 # . . discard args + 899 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 900 # . write(out, "/imm32 ") + 901 # . . push args + 902 68/push "/imm32 "/imm32 + 903 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) + 904 # . . call + 905 e8/call write/disp32 + 906 # . . discard args + 907 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 908 $emit-string-literal-data:loop-init: + 909 # ++curr # skip initial '"' + 910 42/increment-EDX + 911 # c/ECX = 0 + 912 31/xor 3/mod/direct 1/rm32/ECX . . . 1/r32/ECX . . # clear ECX + 913 $emit-string-literal-data:loop: + 914 # if (curr >= max) break + 915 39/compare 3/mod/direct 2/rm32/EDX . . . 6/r32/ESI . . # compare EDX with ESI + 916 7d/jump-if-greater-or-equal $emit-string-literal-data:end/disp8 + 917 # CL = *curr + 918 8a/copy-byte 0/mod/indirect 2/rm32/EDX . . . 1/r32/CL . . # copy byte at *EDX to CL + 919 # if (ECX == '"') break + 920 81 7/subop/compare 3/mod/direct 1/rm32/ECX . . . . . 0x22/imm32/dquote # compare ECX + 921 74/jump-if-equal $emit-string-literal-data:end/disp8 + 922 # if (ECX == '\') ++curr, ECX = *curr + 923 81 7/subop/compare 3/mod/direct 1/rm32/ECX . . . . . 0x5c/imm32/backslash # compare ECX + 924 75/jump-if-not-equal $emit-string-literal-data:emit/disp8 + 925 # . ++curr + 926 42/increment-EDX + 927 # . if (curr >= max) break + 928 39/compare 3/mod/direct 2/rm32/EDX . . . 6/r32/ESI . . # compare EDX with ESI + 929 7d/jump-if-greater-or-equal $emit-string-literal-data:end/disp8 + 930 # . CL = *curr + 931 8a/copy-byte 0/mod/indirect 2/rm32/EDX . . . 1/r32/CL . . # copy byte at *EDX to CL + 932 $emit-string-literal-data:emit: + 933 # append-byte-hex(out, CL) + 934 # . . push args + 935 51/push-ECX + 936 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) + 937 # . . call + 938 e8/call append-byte-hex/disp32 + 939 # . . discard args + 940 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 941 # if (is-alphanumeric?(*curr)) print(out, "/#{*curr}") + 942 # . EAX = is-alphanumeric?(CL) + 943 # . . push args + 944 51/push-ECX + 945 # . . call + 946 e8/call is-alphanumeric?/disp32 + 947 # . . discard args + 948 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 949 # . if (EAX == 0) goto char-done + 950 3d/compare-EAX-and 0/imm32 + 951 74/jump-if-equal $emit-string-literal-data:char-done/disp8 + 952 # . write(out, "/") + 953 # . . push args + 954 68/push Slash/imm32 + 955 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) + 956 # . . call + 957 e8/call write/disp32 + 958 # . . discard args + 959 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 960 # . append-byte(out, *curr) + 961 # . . push args + 962 51/push-ECX + 963 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) + 964 # . . call + 965 e8/call append-byte/disp32 + 966 # . . discard args + 967 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 968 $emit-string-literal-data:char-done: + 969 # write(out, " ") + 970 # . . push args + 971 68/push Space/imm32 + 972 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) + 973 # . . call + 974 e8/call write/disp32 + 975 # . . discard args + 976 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 977 # ++curr + 978 42/increment-EDX + 979 eb/jump $emit-string-literal-data:loop/disp8 + 980 $emit-string-literal-data:end: + 981 # . restore registers + 982 5e/pop-to-ESI + 983 5a/pop-to-EDX + 984 59/pop-to-ECX + 985 58/pop-to-EAX + 986 # . epilog + 987 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP + 988 5d/pop-to-EBP + 989 c3/return + 990 + 991 is-alphanumeric?: # c : int -> EAX : boolean + 992 # . prolog + 993 55/push-EBP + 994 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + 995 # EAX = c + 996 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 0/r32/EAX 8/disp8 . # copy *(EBP+8) to EAX + 997 # if (EAX < '0') return false + 998 3d/compare-EAX-with 0x30/imm32/0 + 999 7c/jump-if-lesser $is-alphanumeric?:false/disp8 +1000 # if (EAX <= '9') return true +1001 3d/compare-EAX-with 0x39/imm32/9 +1002 7e/jump-if-lesser-or-equal $is-alphanumeric?:true/disp8 +1003 # if (EAX < 'A') return false +1004 3d/compare-EAX-with 0x41/imm32/A +1005 7c/jump-if-lesser $is-alphanumeric?:false/disp8 +1006 # if (EAX <= 'Z') return true +1007 3d/compare-EAX-with 0x5a/imm32/Z +1008 7e/jump-if-lesser-or-equal $is-alphanumeric?:true/disp8 +1009 # if (EAX < 'a') return false +1010 3d/compare-EAX-with 0x61/imm32/a +1011 7c/jump-if-lesser $is-alphanumeric?:false/disp8 +1012 # if (EAX <= 'z') return true +1013 3d/compare-EAX-with 0x7a/imm32/z +1014 7e/jump-if-lesser-or-equal $is-alphanumeric?:true/disp8 +1015 # return false +1016 $is-alphanumeric?:false: +1017 b8/copy-to-EAX 0/imm32/false +1018 eb/jump $is-alphanumeric?:end/disp8 +1019 $is-alphanumeric?:true: +1020 b8/copy-to-EAX 1/imm32/true +1021 $is-alphanumeric?:end: +1022 # . epilog +1023 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +1024 5d/pop-to-EBP +1025 c3/return +1026 +1027 test-emit-string-literal-data: +1028 # . prolog +1029 55/push-EBP +1030 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +1031 # setup +1032 # . clear-stream(_test-output-stream) +1033 # . . push args +1034 68/push _test-output-stream/imm32 +1035 # . . call +1036 e8/call clear-stream/disp32 +1037 # . . discard args +1038 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1039 # var slice/ECX = '"abc"/d' +1040 68/push _test-slice-abc-metadata-end/imm32 +1041 68/push _test-slice-abc/imm32 +1042 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +1043 # emit-string-literal-data(_test-output-stream, slice) +1044 # . . push args +1045 51/push-ECX +1046 68/push _test-output-stream/imm32 +1047 # . . call +1048 e8/call emit-string-literal-data/disp32 +1049 # . . discard args +1050 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1051 +-- 26 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- +1077 # . check-stream-equal(_test-output-stream, "3/imm32 61/a 62/b 63/c ", msg) +1078 # . . push args +1079 68/push "F - test-emit-string-literal-data"/imm32 +1080 68/push "0x00000003/imm32 61/a 62/b 63/c "/imm32 +1081 68/push _test-output-stream/imm32 +1082 # . . call +1083 e8/call check-stream-equal/disp32 +1084 # . . discard args +1085 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1086 # . epilog +1087 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +1088 5d/pop-to-EBP +1089 c3/return +1090 +1091 test-emit-string-literal-data-empty: +1092 # . prolog +1093 55/push-EBP +1094 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +1095 # setup +1096 # . clear-stream(_test-output-stream) +1097 # . . push args +1098 68/push _test-output-stream/imm32 +1099 # . . call +1100 e8/call clear-stream/disp32 +1101 # . . discard args +1102 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1103 # var slice/ECX = '""' +1104 68/push _test-slice-empty-string-literal-end/imm32 +1105 68/push _test-slice-empty-string-literal/imm32 +1106 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +1107 # emit-string-literal-data(_test-output-stream, slice) +1108 # . . push args +1109 51/push-ECX +1110 68/push _test-output-stream/imm32 +1111 # . . call +1112 e8/call emit-string-literal-data/disp32 +1113 # . . discard args +1114 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1115 +-- 26 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- +1141 # . check-stream-equal(_test-output-stream, "0/imm32 ", msg) +1142 # . . push args +1143 68/push "F - test-emit-string-literal-data-empty"/imm32 +1144 68/push "0x00000000/imm32 "/imm32 +1145 68/push _test-output-stream/imm32 +1146 # . . call +1147 e8/call check-stream-equal/disp32 +1148 # . . discard args +1149 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1150 # . epilog +1151 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +1152 5d/pop-to-EBP +1153 c3/return +1154 +1155 # just to keep things simple +1156 test-emit-string-literal-data-no-metadata-for-non-alphanumerics: +1157 # . prolog +1158 55/push-EBP +1159 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +1160 # setup +1161 # . clear-stream(_test-output-stream) +1162 # . . push args +1163 68/push _test-output-stream/imm32 +1164 # . . call +1165 e8/call clear-stream/disp32 +1166 # . . discard args +1167 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1168 # var slice/ECX = '"a b"' +1169 68/push _test-slice-a-space-b-end/imm32 +1170 68/push _test-slice-a-space-b/imm32 +1171 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +1172 # emit-string-literal-data(_test-output-stream, slice) +1173 # . . push args +1174 51/push-ECX +1175 68/push _test-output-stream/imm32 +1176 # . . call +1177 e8/call emit-string-literal-data/disp32 +1178 # . . discard args +1179 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1180 +-- 26 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- +1206 # . check-stream-equal(_test-output-stream, "3/imm32 61/a 20 62/b ", msg) # ideally we'd like to say '20/space' but that requires managing names for codepoints +1207 # . . push args +1208 68/push "F - test-emit-string-literal-data-no-metadata-for-non-alphanumerics"/imm32 +1209 68/push "0x00000003/imm32 61/a 20 62/b "/imm32 +1210 68/push _test-output-stream/imm32 +1211 # . . call +1212 e8/call check-stream-equal/disp32 +1213 # . . discard args +1214 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1215 # . epilog +1216 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +1217 5d/pop-to-EBP +1218 c3/return +1219 +1220 test-emit-string-literal-data-handles-escape-sequences: +1221 # . prolog +1222 55/push-EBP +1223 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +1224 # setup +1225 # . clear-stream(_test-output-stream) +1226 # . . push args +1227 68/push _test-output-stream/imm32 +1228 # . . call +1229 e8/call clear-stream/disp32 +1230 # . . discard args +1231 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1232 # var slice/ECX = '"a\"b"' +1233 68/push _test-slice-a-dquote-b-end/imm32 +1234 68/push _test-slice-a-dquote-b/imm32 +1235 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +1236 # emit-string-literal-data(_test-output-stream, slice) +1237 # . . push args +1238 51/push-ECX +1239 68/push _test-output-stream/imm32 +1240 # . . call +1241 e8/call emit-string-literal-data/disp32 +1242 # . . discard args +1243 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1244 +-- 26 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- +1270 # . check-stream-equal(_test-output-stream, "3/imm32 61/a 22 62/b ", msg) +1271 # . . push args +1272 68/push "F - test-emit-string-literal-data-handles-escape-sequences"/imm32 +1273 68/push "0x00000003/imm32 61/a 22 62/b "/imm32 +1274 68/push _test-output-stream/imm32 +1275 # . . call +1276 e8/call check-stream-equal/disp32 +1277 # . . discard args +1278 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1279 # . epilog +1280 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +1281 5d/pop-to-EBP +1282 c3/return +1283 +1284 # emit everything from a word except the initial datum +1285 emit-metadata: # out : (address buffered-file), word : (address slice) +1286 # pseudocode +1287 # var slice = {0, word->end} +1288 # curr = word->start +1289 # if *curr == '"' +1290 # curr = skip-string-in-slice(curr, word->end) +1291 # else +1292 # while true +1293 # if curr == word->end +1294 # return +1295 # if *curr == '/' +1296 # break +1297 # ++curr +1298 # slice->curr = curr +1299 # write-slice-buffered(out, slice) +1300 # +1301 # . prolog +1302 55/push-EBP +1303 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +1304 # . save registers +1305 50/push-EAX +1306 51/push-ECX +1307 52/push-EDX +1308 53/push-EBX +1309 56/push-ESI +1310 # ESI = word +1311 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 6/r32/ESI 0xc/disp8 . # copy *(EBP+12) to ESI +1312 # curr/ECX = word->start +1313 8b/copy 0/mod/indirect 6/rm32/ESI . . . 1/r32/ECX . . # copy *ESI to ECX +1314 # end/EDX = word->end +1315 8b/copy 1/mod/*+disp8 6/rm32/ESI . . . 2/r32/EDX 4/disp8 . # copy *(ESI+4) to EDX +1316 # var slice/EBX = {0, end} +1317 52/push-EDX +1318 68/push 0/imm32 +1319 89/copy 3/mod/direct 3/rm32/EBX . . . 4/r32/ESP . . # copy ESP to EBX +1320 # EAX = 0 +1321 b8/copy-to-EAX 0/imm32 +1322 $emit-metadata:check-for-string-literal: +1323 # - if (*curr == '"') curr = skip-string-in-slice(curr, end) +1324 8a/copy-byte 0/mod/indirect 1/rm32/ECX . . . 0/r32/AL . . # copy byte at *ECX to AL +1325 3d/compare-EAX-and 0x22/imm32/dquote +1326 75/jump-if-not-equal $emit-metadata:skip-datum-loop/disp8 +1327 $emit-metadata:skip-string-literal: +1328 # . EAX = skip-string-in-slice(curr, end) +1329 # . . push args +1330 52/push-EDX +1331 51/push-ECX +1332 # . . call +1333 e8/call skip-string-in-slice/disp32 +1334 # . . discard args +1335 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1336 # . curr = EAX +1337 89/copy 3/mod/direct 1/rm32/ECX . . . 0/r32/EAX . . # copy EAX to ECX +1338 eb/jump $emit-metadata:emit/disp8 +1339 $emit-metadata:skip-datum-loop: +1340 # - otherwise scan for '/' +1341 # if (curr == end) return +1342 39/compare 3/mod/direct 1/rm32/ECX . . . 2/r32/EDX . . # compare ECX and EDX +1343 74/jump-if-equal $emit-metadata:end/disp8 +1344 # if (*curr == '/') break +1345 8a/copy-byte 0/mod/indirect 1/rm32/ECX . . . 0/r32/AL . . # copy byte at *ECX to AL +1346 3d/compare-EAX-and 0x2f/imm32/slash +1347 74/jump-if-equal $emit-metadata:emit/disp8 +1348 # ++curr +1349 41/increment-ECX +1350 eb/jump $emit-metadata:skip-datum-loop/disp8 +1351 $emit-metadata:emit: +1352 # slice->curr = ECX +1353 89/copy 0/mod/indirect 3/rm32/EBX . . . 1/r32/ECX . . # copy ECX to *EBX +1354 # write-slice-buffered(out, slice) +1355 # . . push args +1356 53/push-EBX +1357 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) +1358 # . . call +1359 e8/call write-slice-buffered/disp32 +1360 # . . discard args +1361 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . 8/imm32 . # add to ESP +1362 $emit-metadata:end: +1363 # . reclaim locals +1364 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . 8/imm32 . # add to ESP +1365 # . restore registers +1366 5e/pop-to-ESI +1367 5b/pop-to-EBX +1368 5a/pop-to-EDX +1369 59/pop-to-ECX +1370 58/pop-to-EAX +1371 # . epilog +1372 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +1373 5d/pop-to-EBP +1374 c3/return +1375 +1376 test-emit-metadata: +1377 # . prolog +1378 55/push-EBP +1379 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +1380 # setup +1381 # . clear-stream(_test-output-stream) +1382 # . . push args +1383 68/push _test-output-stream/imm32 +1384 # . . call +1385 e8/call clear-stream/disp32 +1386 # . . discard args +1387 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1388 # . clear-stream(_test-output-buffered-file+4) +1389 # . . push args +1390 b8/copy-to-EAX _test-output-buffered-file/imm32 +1391 05/add-to-EAX 4/imm32 +1392 50/push-EAX +1393 # . . call +1394 e8/call clear-stream/disp32 +1395 # . . discard args +1396 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1397 # var slice/ECX = "abc/def" +1398 68/push _test-slice-word-end/imm32 +1399 68/push _test-slice-word/imm32/start +1400 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +1401 # emit-metadata(_test-output-buffered-file, slice) +1402 # . . push args +1403 51/push-ECX +1404 68/push _test-output-buffered-file/imm32 +1405 # . . call +1406 e8/call emit-metadata/disp32 +1407 # . . discard args +1408 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1409 # flush(_test-output-buffered-file) +1410 # . . push args +1411 68/push _test-output-buffered-file/imm32 +1412 # . . call +1413 e8/call flush/disp32 +1414 # . . discard args +1415 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1416 # check-stream-equal(_test-output-stream, "/def", msg) # important that there's no leading space +1417 # . . push args +1418 68/push "F - test-emit-metadata"/imm32 +1419 68/push "/def"/imm32 +1420 68/push _test-output-stream/imm32 +1421 # . . call +1422 e8/call check-stream-equal/disp32 +1423 # . . discard args +1424 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1425 # . epilog +1426 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +1427 5d/pop-to-EBP +1428 c3/return +1429 +1430 test-emit-metadata-none: +1431 # . prolog +1432 55/push-EBP +1433 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +1434 # setup +1435 # . clear-stream(_test-output-stream) +1436 # . . push args +1437 68/push _test-output-stream/imm32 +1438 # . . call +1439 e8/call clear-stream/disp32 +1440 # . . discard args +1441 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1442 # . clear-stream(_test-output-buffered-file+4) +1443 # . . push args +1444 b8/copy-to-EAX _test-output-buffered-file/imm32 +1445 05/add-to-EAX 4/imm32 +1446 50/push-EAX +1447 # . . call +1448 e8/call clear-stream/disp32 +1449 # . . discard args +1450 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1451 # var slice/ECX = "abc" +1452 68/push _test-slice-word-datum-end/imm32 +1453 68/push _test-slice-word/imm32/start +1454 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +1455 # emit-metadata(_test-output-buffered-file, slice) +1456 # . . push args +1457 51/push-ECX +1458 68/push _test-output-buffered-file/imm32 +1459 # . . call +1460 e8/call emit-metadata/disp32 +1461 # . . discard args +1462 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1463 # flush(_test-output-buffered-file) +1464 # . . push args +1465 68/push _test-output-buffered-file/imm32 +1466 # . . call +1467 e8/call flush/disp32 +1468 # . . discard args +1469 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1470 # check-stream-equal(_test-output-stream, "", msg) +1471 # . . push args +1472 68/push "F - test-emit-metadata-none"/imm32 +1473 68/push ""/imm32 +1474 68/push _test-output-stream/imm32 +1475 # . . call +1476 e8/call check-stream-equal/disp32 +1477 # . . discard args +1478 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1479 # . epilog +1480 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +1481 5d/pop-to-EBP +1482 c3/return +1483 +1484 test-emit-metadata-multiple: +1485 # . prolog +1486 55/push-EBP +1487 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +1488 # setup +1489 # . clear-stream(_test-output-stream) +1490 # . . push args +1491 68/push _test-output-stream/imm32 +1492 # . . call +1493 e8/call clear-stream/disp32 +1494 # . . discard args +1495 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1496 # . clear-stream(_test-output-buffered-file+4) +1497 # . . push args +1498 b8/copy-to-EAX _test-output-buffered-file/imm32 +1499 05/add-to-EAX 4/imm32 +1500 50/push-EAX +1501 # . . call +1502 e8/call clear-stream/disp32 +1503 # . . discard args +1504 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1505 # var slice/ECX = "abc/def/ghi" +1506 68/push _test-slice-word-end2/imm32 +1507 68/push _test-slice-word/imm32/start +1508 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +1509 # emit-metadata(_test-output-buffered-file, slice) +1510 # . . push args +1511 51/push-ECX +1512 68/push _test-output-buffered-file/imm32 +1513 # . . call +1514 e8/call emit-metadata/disp32 +1515 # . . discard args +1516 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1517 # flush(_test-output-buffered-file) +1518 # . . push args +1519 68/push _test-output-buffered-file/imm32 +1520 # . . call +1521 e8/call flush/disp32 +1522 # . . discard args +1523 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1524 # check-stream-equal(_test-output-stream, "/def/ghi", msg) # important that there's no leading space +1525 # . . push args +1526 68/push "F - test-emit-metadata-multiple"/imm32 +1527 68/push "/def/ghi"/imm32 +1528 68/push _test-output-stream/imm32 +1529 # . . call +1530 e8/call check-stream-equal/disp32 +1531 # . . discard args +1532 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1533 # . epilog +1534 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +1535 5d/pop-to-EBP +1536 c3/return +1537 +1538 test-emit-metadata-when-no-datum: +1539 # . prolog +1540 55/push-EBP +1541 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +1542 # setup +1543 # . clear-stream(_test-output-stream) +1544 # . . push args +1545 68/push _test-output-stream/imm32 +1546 # . . call +1547 e8/call clear-stream/disp32 +1548 # . . discard args +1549 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1550 # . clear-stream(_test-output-buffered-file+4) +1551 # . . push args +1552 b8/copy-to-EAX _test-output-buffered-file/imm32 +1553 05/add-to-EAX 4/imm32 +1554 50/push-EAX +1555 # . . call +1556 e8/call clear-stream/disp32 +1557 # . . discard args +1558 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1559 # var slice/ECX = "/abc" +1560 b8/copy-to-EAX "/abc"/imm32 +1561 # . push end/ECX +1562 8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX +1563 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/EAX 1/index/ECX . 1/r32/ECX 4/disp8 . # copy EAX+ECX+4 to ECX +1564 51/push-ECX +1565 # . push curr/EAX +1566 05/add-to-EAX 4/imm32 +1567 50/push-EAX +1568 # . save stack pointer +1569 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +1570 # emit-metadata(_test-output-buffered-file, slice) +1571 # . . push args +1572 51/push-ECX +1573 68/push _test-output-buffered-file/imm32 +1574 # . . call +1575 e8/call emit-metadata/disp32 +1576 # . . discard args +1577 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1578 # flush(_test-output-buffered-file) +1579 # . . push args +1580 68/push _test-output-buffered-file/imm32 +1581 # . . call +1582 e8/call flush/disp32 +1583 # . . discard args +1584 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1585 # check-stream-equal(_test-output-stream, "/abc", msg) # nothing skipped +1586 # . . push args +1587 68/push "F - test-emit-metadata-when-no-datum"/imm32 +1588 68/push "/abc"/imm32 +1589 68/push _test-output-stream/imm32 +1590 # . . call +1591 e8/call check-stream-equal/disp32 +1592 # . . discard args +1593 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1594 # . epilog +1595 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +1596 5d/pop-to-EBP +1597 c3/return +1598 +1599 test-emit-metadata-in-string-literal: +1600 # . prolog +1601 55/push-EBP +1602 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +1603 # setup +1604 # . clear-stream(_test-output-stream) +1605 # . . push args +1606 68/push _test-output-stream/imm32 +1607 # . . call +1608 e8/call clear-stream/disp32 +1609 # . . discard args +1610 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1611 # . clear-stream(_test-output-buffered-file+4) +1612 # . . push args +1613 b8/copy-to-EAX _test-output-buffered-file/imm32 +1614 05/add-to-EAX 4/imm32 +1615 50/push-EAX +1616 # . . call +1617 e8/call clear-stream/disp32 +1618 # . . discard args +1619 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1620 # var slice/ECX = "\"abc/def\"/ghi" +1621 68/push _test-slice-literal-string-with-metadata-end/imm32 +1622 68/push _test-slice-literal-string/imm32/start +1623 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +1624 # emit-metadata(_test-output-buffered-file, slice) +1625 # . . push args +1626 51/push-ECX +1627 68/push _test-output-buffered-file/imm32 +1628 # . . call +1629 e8/call emit-metadata/disp32 +1630 # . . discard args +1631 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1632 # flush(_test-output-buffered-file) +1633 # . . push args +1634 68/push _test-output-buffered-file/imm32 +1635 # . . call +1636 e8/call flush/disp32 +1637 # . . discard args +1638 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1639 +-- 26 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- +1665 # check-stream-equal(_test-output-stream, "/ghi", msg) # important that there's no leading space +1666 # . . push args +1667 68/push "F - test-emit-metadata-in-string-literal"/imm32 +1668 68/push "/ghi"/imm32 +1669 68/push _test-output-stream/imm32 +1670 # . . call +1671 e8/call check-stream-equal/disp32 +1672 # . . discard args +1673 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1674 # . epilog +1675 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +1676 5d/pop-to-EBP +1677 c3/return +1678 +1679 # (re)compute the bounds of the next word in the line +1680 # return empty string on reaching end of file +1681 next-word: # line : (address stream byte), out : (address slice) +1682 # . prolog +1683 55/push-EBP +1684 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +1685 # . save registers +1686 50/push-EAX +1687 51/push-ECX +1688 56/push-ESI +1689 57/push-EDI +1690 # ESI = line +1691 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 6/r32/ESI 8/disp8 . # copy *(EBP+8) to ESI +1692 # EDI = out +1693 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 7/r32/EDI 0xc/disp8 . # copy *(EBP+12) to EDI +1694 # skip-chars-matching(line, ' ') +1695 # . . push args +1696 68/push 0x20/imm32/space +1697 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) +1698 # . . call +1699 e8/call skip-chars-matching/disp32 +1700 # . . discard args +1701 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1702 $next-word:check0: +1703 # if (line->read >= line->write) clear out and return +1704 # . EAX = line->read +1705 8b/copy 1/mod/*+disp8 6/rm32/ESI . . . 0/r32/EAX 4/disp8 . # copy *(ESI+4) to EAX +1706 # . if (EAX < line->write) goto next check +1707 3b/compare 0/mod/indirect 6/rm32/ESI . . . 0/r32/EAX . . # compare EAX with *ESI +1708 7c/jump-if-lesser $next-word:check-for-comment/disp8 +1709 # . return out = {0, 0} +1710 c7 0/subop/copy 0/mod/direct 7/rm32/EDI . . . . . 0/imm32 # copy to *EDI +1711 c7 0/subop/copy 1/mod/*+disp8 7/rm32/EDI . . . . 4/disp8 0/imm32 # copy to *(EDI+4) +1712 eb/jump $next-word:end/disp8 +1713 $next-word:check-for-comment: +1714 # out->start = &line->data[line->read] +1715 8b/copy 1/mod/*+disp8 6/rm32/ESI . . . 1/r32/ECX 4/disp8 . # copy *(ESI+4) to ECX +1716 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 +1717 89/copy 0/mod/indirect 7/rm32/EDI . . . 0/r32/EAX . . # copy EAX to *EDI +1718 # if line->data[line->read] == '#' +1719 # . EAX = line->data[line->read] +1720 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX +1721 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 +1722 # . compare +1723 3d/compare-EAX-and 0x23/imm32/pound +1724 75/jump-if-not-equal $next-word:check-for-string-literal/disp8 +1725 $next-word:comment: +1726 # out->end = &line->data[line->write] +1727 8b/copy 0/mod/indirect 6/rm32/ESI . . . 0/r32/EAX . . # copy *ESI to EAX +1728 8d/copy-address 1/mod/*+disp8 4/rm32/sib 6/base/ESI 0/index/EAX . 0/r32/EAX 0xc/disp8 . # copy ESI+EAX+12 to EAX +1729 89/copy 1/mod/*+disp8 7/rm32/EDI . . . 0/r32/EAX 4/disp8 . # copy EAX to *(EDI+4) +1730 # line->read = line->write # skip rest of line +1731 8b/copy 0/mod/indirect 6/rm32/ESI . . . 0/r32/EAX . . # copy *ESI to EAX +1732 89/copy 1/mod/*+disp8 6/rm32/ESI . . . 0/r32/EAX 4/disp8 . # copy EAX to *(ESI+4) +1733 # return +1734 eb/jump $next-word:end/disp8 +1735 $next-word:check-for-string-literal: +1736 # if line->data[line->read] == '"' +1737 # . EAX = line->data[line->read] +1738 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX +1739 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 +1740 # . compare +1741 3d/compare-EAX-and 0x22/imm32/dquote +1742 75/jump-if-not-equal $next-word:regular-word/disp8 +1743 $next-word:string-literal: +1744 # skip-string(line) +1745 # . . push args +1746 56/push-ESI +1747 # . . call +1748 e8/call skip-string/disp32 +1749 # . . discard args +1750 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1751 # fall through +1752 $next-word:regular-word: +1753 # skip-chars-not-matching-whitespace(line) # including trailing newline +1754 # . . push args +1755 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) +1756 # . . call +1757 e8/call skip-chars-not-matching-whitespace/disp32 +1758 # . . discard args +1759 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1760 # out->end = &line->data[line->read] +1761 8b/copy 1/mod/*+disp8 6/rm32/ESI . . . 1/r32/ECX 4/disp8 . # copy *(ESI+4) to ECX +1762 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 +1763 89/copy 1/mod/*+disp8 7/rm32/EDI . . . 0/r32/EAX 4/disp8 . # copy EAX to *(EDI+4) +1764 $next-word:end: +1765 # . restore registers +1766 5f/pop-to-EDI +1767 5e/pop-to-ESI +1768 59/pop-to-ECX +1769 58/pop-to-EAX +1770 # . epilog +1771 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +1772 5d/pop-to-EBP +1773 c3/return +1774 +1775 test-next-word: +1776 # . prolog +1777 55/push-EBP +1778 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +1779 # setup +1780 # . clear-stream(_test-input-stream) +1781 # . . push args +1782 68/push _test-input-stream/imm32 +1783 # . . call +1784 e8/call clear-stream/disp32 +1785 # . . discard args +1786 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1787 # var slice/ECX = {0, 0} +1788 68/push 0/imm32/end +1789 68/push 0/imm32/start +1790 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +1791 # write(_test-input-stream, " ab") +1792 # . . push args +1793 68/push " ab"/imm32 +1794 68/push _test-input-stream/imm32 +1795 # . . call +1796 e8/call write/disp32 +1797 # . . discard args +1798 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1799 # next-word(_test-input-stream, slice) +1800 # . . push args +1801 51/push-ECX +1802 68/push _test-input-stream/imm32 +1803 # . . call +1804 e8/call next-word/disp32 +1805 # . . discard args +1806 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1807 # check-ints-equal(_test-input-stream->read, 4, msg) +1808 # . . push args +1809 68/push "F - test-next-word/updates-stream-read-correctly"/imm32 +1810 68/push 4/imm32 +1811 b8/copy-to-EAX _test-input-stream/imm32 +1812 ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 4/disp8 . # push *(EAX+4) +1813 # . . call +1814 e8/call check-ints-equal/disp32 +1815 # . . discard args +1816 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1817 # check-ints-equal(slice->start - _test-input-stream->data, 2, msg) +1818 # . check-ints-equal(slice->start - _test-input-stream, 14, msg) +1819 # . . push args +1820 68/push "F - test-next-word: start"/imm32 +1821 68/push 0xe/imm32 +1822 # . . push slice->start - _test-input-stream +1823 8b/copy 0/mod/indirect 1/rm32/ECX . . . 0/r32/EAX . . # copy *ECX to EAX +1824 81 5/subop/subtract 3/mod/direct 0/rm32/EAX . . . . . _test-input-stream/imm32 # subtract from EAX +1825 50/push-EAX +1826 # . . call +1827 e8/call check-ints-equal/disp32 +1828 # . . discard args +1829 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1830 # check-ints-equal(slice->end - _test-input-stream->data, 4, msg) +1831 # . check-ints-equal(slice->end - _test-input-stream, 16, msg) +1832 # . . push args +1833 68/push "F - test-next-word: end"/imm32 +1834 68/push 0x10/imm32 +1835 # . . push slice->end - _test-input-stream +1836 8b/copy 1/mod/*+disp8 1/rm32/ECX . . . 0/r32/EAX 4/disp8 . # copy *(ECX+4) to EAX +1837 81 5/subop/subtract 3/mod/direct 0/rm32/EAX . . . . . _test-input-stream/imm32 # subtract from EAX +1838 50/push-EAX +1839 # . . call +1840 e8/call check-ints-equal/disp32 +1841 # . . discard args +1842 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1843 # . epilog +1844 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +1845 5d/pop-to-EBP +1846 c3/return +1847 +1848 test-next-word-returns-whole-comment: +1849 # . prolog +1850 55/push-EBP +1851 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +1852 # setup +1853 # . clear-stream(_test-input-stream) +1854 # . . push args +1855 68/push _test-input-stream/imm32 +1856 # . . call +1857 e8/call clear-stream/disp32 +1858 # . . discard args +1859 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1860 # var slice/ECX = {0, 0} +1861 68/push 0/imm32/end +1862 68/push 0/imm32/start +1863 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +1864 # write(_test-input-stream, " # a") +1865 # . . push args +1866 68/push " # a"/imm32 +1867 68/push _test-input-stream/imm32 +1868 # . . call +1869 e8/call write/disp32 +1870 # . . discard args +1871 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1872 # next-word(_test-input-stream, slice) +1873 # . . push args +1874 51/push-ECX +1875 68/push _test-input-stream/imm32 +1876 # . . call +1877 e8/call next-word/disp32 +1878 # . . discard args +1879 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1880 # check-ints-equal(_test-input-stream->read, 5, msg) +1881 # . . push args +1882 68/push "F - test-next-word-returns-whole-comment/updates-stream-read-correctly"/imm32 +1883 68/push 5/imm32 +1884 b8/copy-to-EAX _test-input-stream/imm32 +1885 ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 4/disp8 . # push *(EAX+4) +1886 # . . call +1887 e8/call check-ints-equal/disp32 +1888 # . . discard args +1889 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1890 # check-ints-equal(slice->start - _test-input-stream->data, 2, msg) +1891 # . check-ints-equal(slice->start - _test-input-stream, 14, msg) +1892 # . . push args +1893 68/push "F - test-next-word-returns-whole-comment: start"/imm32 +1894 68/push 0xe/imm32 +1895 # . . push slice->start - _test-input-stream +1896 8b/copy 0/mod/indirect 1/rm32/ECX . . . 0/r32/EAX . . # copy *ECX to EAX +1897 81 5/subop/subtract 3/mod/direct 0/rm32/EAX . . . . . _test-input-stream/imm32 # subtract from EAX +1898 50/push-EAX +1899 # . . call +1900 e8/call check-ints-equal/disp32 +1901 # . . discard args +1902 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1903 # check-ints-equal(slice->end - _test-input-stream->data, 5, msg) +1904 # . check-ints-equal(slice->end - _test-input-stream, 17, msg) +1905 # . . push args +1906 68/push "F - test-next-word-returns-whole-comment: end"/imm32 +1907 68/push 0x11/imm32 +1908 # . . push slice->end - _test-input-stream +1909 8b/copy 1/mod/*+disp8 1/rm32/ECX . . . 0/r32/EAX 4/disp8 . # copy *(ECX+4) to EAX +1910 81 5/subop/subtract 3/mod/direct 0/rm32/EAX . . . . . _test-input-stream/imm32 # subtract from EAX +1911 50/push-EAX +1912 # . . call +1913 e8/call check-ints-equal/disp32 +1914 # . . discard args +1915 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1916 # . epilog +1917 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +1918 5d/pop-to-EBP +1919 c3/return +1920 +1921 test-next-word-returns-empty-string-on-eof: +1922 # . prolog +1923 55/push-EBP +1924 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +1925 # setup +1926 # . clear-stream(_test-input-stream) +1927 # . . push args +1928 68/push _test-input-stream/imm32 +1929 # . . call +1930 e8/call clear-stream/disp32 +1931 # . . discard args +1932 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1933 # var slice/ECX = {0, 0} +1934 68/push 0/imm32/end +1935 68/push 0/imm32/start +1936 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +1937 # write nothing to _test-input-stream +1938 # next-word(_test-input-stream, slice) +1939 # . . push args +1940 51/push-ECX +1941 68/push _test-input-stream/imm32 +1942 # . . call +1943 e8/call next-word/disp32 +1944 # . . discard args +1945 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1946 # check-ints-equal(slice->end - slice->start, 0, msg) +1947 # . . push args +1948 68/push "F - test-next-word-returns-empty-string-on-eof"/imm32 +1949 68/push 0/imm32 +1950 # . . push slice->end - slice->start +1951 8b/copy 1/mod/*+disp8 1/rm32/ECX . . . 0/r32/EAX 4/disp8 . # copy *(ECX+4) to EAX +1952 2b/subtract 0/mod/indirect 1/rm32/ECX . . . 0/r32/EAX . . # subtract *ECX from EAX +1953 50/push-EAX +1954 # . . call +1955 e8/call check-ints-equal/disp32 +1956 # . . discard args +1957 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1958 # . epilog +1959 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +1960 5d/pop-to-EBP +1961 c3/return +1962 +1963 test-next-word-returns-whole-string: +1964 # . prolog +1965 55/push-EBP +1966 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +1967 # setup +1968 # . clear-stream(_test-input-stream) +1969 # . . push args +1970 68/push _test-input-stream/imm32 +1971 # . . call +1972 e8/call clear-stream/disp32 +1973 # . . discard args +1974 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1975 # var slice/ECX = {0, 0} +1976 68/push 0/imm32/end +1977 68/push 0/imm32/start +1978 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +1979 # write(_test-input-stream, " \"a b\"/imm32 ") +1980 # . . push args +1981 68/push " \"a b\"/imm32 "/imm32 +1982 68/push _test-input-stream/imm32 +1983 # . . call +1984 e8/call write/disp32 +1985 # . . discard args +1986 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1987 # next-word(_test-input-stream, slice) +1988 # . . push args +1989 51/push-ECX +1990 68/push _test-input-stream/imm32 +1991 # . . call +1992 e8/call next-word/disp32 +1993 # . . discard args +1994 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1995 # check-ints-equal(slice->start - _test-input-stream->data, 1, msg) +1996 # . check-ints-equal(slice->start - _test-input-stream, 13, msg) +1997 # . . push args +1998 68/push "F - test-next-word-returns-whole-string: start"/imm32 +1999 68/push 0xd/imm32 +2000 # . . push slice->start - _test-input-stream +2001 8b/copy 0/mod/indirect 1/rm32/ECX . . . 0/r32/EAX . . # copy *ECX to EAX +2002 81 5/subop/subtract 3/mod/direct 0/rm32/EAX . . . . . _test-input-stream/imm32 # subtract from EAX +2003 50/push-EAX +2004 # . . call +2005 e8/call check-ints-equal/disp32 +2006 # . . discard args +2007 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +2008 # check-ints-equal(slice->end - _test-input-stream->data, 12, msg) +2009 # . check-ints-equal(slice->end - _test-input-stream, 24, msg) +2010 # . . push args +2011 68/push "F - test-next-word-returns-whole-string: end"/imm32 +2012 68/push 0x18/imm32 +2013 # . . push slice->end - _test-input-stream +2014 8b/copy 1/mod/*+disp8 1/rm32/ECX . . . 0/r32/EAX 4/disp8 . # copy *(ECX+4) to EAX +2015 81 5/subop/subtract 3/mod/direct 0/rm32/EAX . . . . . _test-input-stream/imm32 # subtract from EAX +2016 50/push-EAX +2017 # . . call +2018 e8/call check-ints-equal/disp32 +2019 # . . discard args +2020 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +2021 # . epilog +2022 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +2023 5d/pop-to-EBP +2024 c3/return +2025 +2026 test-next-word-returns-string-with-escapes: +2027 # . prolog +2028 55/push-EBP +2029 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +2030 # setup +2031 # . clear-stream(_test-input-stream) +2032 # . . push args +2033 68/push _test-input-stream/imm32 +2034 # . . call +2035 e8/call clear-stream/disp32 +2036 # . . discard args +2037 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +2038 # var slice/ECX = {0, 0} +2039 68/push 0/imm32/end +2040 68/push 0/imm32/start +2041 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +2042 # write(_test-input-stream, " \"a\\\"b\"/x") +2043 # . . push args +2044 68/push " \"a\\\"b\"/x"/imm32 +2045 68/push _test-input-stream/imm32 +2046 # . . call +2047 e8/call write/disp32 +2048 # . . discard args +2049 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +2050 # next-word(_test-input-stream, slice) +2051 # . . push args +2052 51/push-ECX +2053 68/push _test-input-stream/imm32 +2054 # . . call +2055 e8/call next-word/disp32 +2056 # . . discard args +2057 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +2058 # check-ints-equal(slice->start - _test-input-stream->data, 1, msg) +2059 # . check-ints-equal(slice->start - _test-input-stream, 13, msg) +2060 # . . push args +2061 68/push "F - test-next-word-returns-string-with-escapes: start"/imm32 +2062 68/push 0xd/imm32 +2063 # . . push slice->start - _test-input-stream +2064 8b/copy 0/mod/indirect 1/rm32/ECX . . . 0/r32/EAX . . # copy *ECX to EAX +2065 81 5/subop/subtract 3/mod/direct 0/rm32/EAX . . . . . _test-input-stream/imm32 # subtract from EAX +2066 50/push-EAX +2067 # . . call +2068 e8/call check-ints-equal/disp32 +2069 # . . discard args +2070 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +2071 # check-ints-equal(slice->end - _test-input-stream->data, 9, msg) +2072 # . check-ints-equal(slice->end - _test-input-stream, 21, msg) +2073 # . . push args +2074 68/push "F - test-next-word-returns-string-with-escapes: end"/imm32 +2075 68/push 0x15/imm32 +2076 # . . push slice->end - _test-input-stream +2077 8b/copy 1/mod/*+disp8 1/rm32/ECX . . . 0/r32/EAX 4/disp8 . # copy *(ECX+4) to EAX +2078 81 5/subop/subtract 3/mod/direct 0/rm32/EAX . . . . . _test-input-stream/imm32 # subtract from EAX +2079 50/push-EAX +2080 # . . call +2081 e8/call check-ints-equal/disp32 +2082 # . . discard args +2083 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +2084 # . epilog +2085 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +2086 5d/pop-to-EBP +2087 c3/return +2088 +2089 # update line->read to end of string literal surrounded by double quotes +2090 # line->read must start out at a double-quote +2091 skip-string: # line : (address stream) +2092 # . prolog +2093 55/push-EBP +2094 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +2095 # . save registers +2096 50/push-EAX +2097 51/push-ECX +2098 52/push-EDX +2099 # ECX = line +2100 8b/copy 1/mod/*+disp8 5/rm32/EBP . . 1/r32/ECX 8/disp8 . # copy *(EBP+8) to ECX +2101 # EAX = skip-string-in-slice(&line->data[line->read], &line->data[line->write]) +2102 # . . push &line->data[line->write] +2103 8b/copy 1/mod/*+disp8 1/rm32/ECX . . 2/r32/EDX 8/disp8 . # copy *(ECX+8) to EDX +2104 8d/copy-address 1/mod/*+disp8 4/rm32/sib 1/base/ECX 2/index/EDX . 2/r32/EDX 0xc/disp8 . # copy ECX+EDX+12 to EDX +2105 52/push-EDX +2106 # . . push &line->data[line->read] +2107 8b/copy 1/mod/*+disp8 1/rm32/ECX . . 2/r32/EDX 4/disp8 . # copy *(ECX+4) to EDX +2108 8d/copy-address 1/mod/*+disp8 4/rm32/sib 1/base/ECX 2/index/EDX . 2/r32/EDX 0xc/disp8 . # copy ECX+EDX+12 to EDX +2109 52/push-EDX +2110 # . . call +2111 e8/call skip-string-in-slice/disp32 +2112 # . . discard args +2113 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +2114 # line->read = EAX - line->data +2115 29/subtract 3/mod/direct 0/rm32/EAX . . . 1/r32/ECX . . # subtract ECX from EAX +2116 2d/subtract-from-EAX 0xc/imm32 +2117 89/copy 1/mod/*+disp8 1/rm32/ECX . . 0/r32/EAX 4/disp8 . # copy EAX to *(ECX+4) +2118 $skip-string:end: +2119 # . restore registers +2120 5a/pop-to-EDX +2121 59/pop-to-ECX +2122 58/pop-to-EAX +2123 # . epilog +2124 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +2125 5d/pop-to-EBP +2126 c3/return +2127 +2128 test-skip-string: +2129 # . prolog +2130 55/push-EBP +2131 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +2132 # setup +2133 # . clear-stream(_test-input-stream) +2134 # . . push args +2135 68/push _test-input-stream/imm32 +2136 # . . call +2137 e8/call clear-stream/disp32 +2138 # . . discard args +2139 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +2140 # . write(_test-input-stream, "\"abc\" def") +2141 # . indices: 0123 45 +2142 # . . push args +2143 68/push "\"abc\" def"/imm32 +2144 68/push _test-input-stream/imm32 +2145 # . . call +2146 e8/call write/disp32 +2147 # . . discard args +2148 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +2149 # precondition: line->read == 0 +2150 # . . push args +2151 68/push "F - test-skip-string/precondition"/imm32 +2152 68/push 0/imm32 +2153 b8/copy-to-EAX _test-input-stream/imm32 +2154 ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 4/disp8 . # push *(EAX+4) +2155 # . . call +2156 e8/call check-ints-equal/disp32 +2157 # . . discard args +2158 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +2159 # skip-string(_test-input-stream) +2160 # . . push args +2161 68/push _test-input-stream/imm32 +2162 # . . call +2163 e8/call skip-string/disp32 +2164 # . . discard args +2165 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +2166 # check-ints-equal(line->read, 5, msg) +2167 # . . push args +2168 68/push "F - test-skip-string"/imm32 +2169 68/push 5/imm32 +2170 b8/copy-to-EAX _test-input-stream/imm32 +2171 ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 4/disp8 . # push *(EAX+4) +2172 # . . call +2173 e8/call check-ints-equal/disp32 +2174 # . . discard args +2175 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +2176 # . epilog +2177 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +2178 5d/pop-to-EBP +2179 c3/return +2180 +2181 test-skip-string-ignores-spaces: +2182 # . prolog +2183 55/push-EBP +2184 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +2185 # setup +2186 # . clear-stream(_test-input-stream) +2187 # . . push args +2188 68/push _test-input-stream/imm32 +2189 # . . call +2190 e8/call clear-stream/disp32 +2191 # . . discard args +2192 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +2193 # . write(_test-input-stream, "\"a b\"/yz") +2194 # . indices: 0123 45 +2195 # . . push args +2196 68/push "\"a b\"/yz"/imm32 +2197 68/push _test-input-stream/imm32 +2198 # . . call +2199 e8/call write/disp32 +2200 # . . discard args +2201 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +2202 # precondition: line->read == 0 +2203 # . . push args +2204 68/push "F - test-skip-string-ignores-spaces/precondition"/imm32 +2205 68/push 0/imm32 +2206 b8/copy-to-EAX _test-input-stream/imm32 +2207 ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 4/disp8 . # push *(EAX+4) +2208 # . . call +2209 e8/call check-ints-equal/disp32 +2210 # . . discard args +2211 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +2212 # skip-string(_test-input-stream) +2213 # . . push args +2214 68/push _test-input-stream/imm32 +2215 # . . call +2216 e8/call skip-string/disp32 +2217 # . . discard args +2218 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +2219 # check-ints-equal(line->read, 5, msg) +2220 # . . push args +2221 68/push "F - test-skip-string-ignores-spaces"/imm32 +2222 68/push 5/imm32 +2223 b8/copy-to-EAX _test-input-stream/imm32 +2224 ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 4/disp8 . # push *(EAX+4) +2225 # . . call +2226 e8/call check-ints-equal/disp32 +2227 # . . discard args +2228 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +2229 # . epilog +2230 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +2231 5d/pop-to-EBP +2232 c3/return +2233 +2234 test-skip-string-ignores-escapes: +2235 # . prolog +2236 55/push-EBP +2237 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +2238 # setup +2239 # . clear-stream(_test-input-stream) +2240 # . . push args +2241 68/push _test-input-stream/imm32 +2242 # . . call +2243 e8/call clear-stream/disp32 +2244 # . . discard args +2245 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +2246 # . write(_test-input-stream, "\"a\\\"b\"/yz") +2247 # . indices: 01 2 34 56 +2248 # . . push args +2249 68/push "\"a\\\"b\"/yz"/imm32 +2250 68/push _test-input-stream/imm32 +2251 # . . call +2252 e8/call write/disp32 +2253 # . . discard args +2254 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +2255 # precondition: line->read == 0 +2256 # . . push args +2257 68/push "F - test-skip-string-ignores-escapes/precondition"/imm32 +2258 68/push 0/imm32 +2259 b8/copy-to-EAX _test-input-stream/imm32 +2260 ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 4/disp8 . # push *(EAX+4) +2261 # . . call +2262 e8/call check-ints-equal/disp32 +2263 # . . discard args +2264 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +2265 # skip-string(_test-input-stream) +2266 # . . push args +2267 68/push _test-input-stream/imm32 +2268 # . . call +2269 e8/call skip-string/disp32 +2270 # . . discard args +2271 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +2272 # check-ints-equal(line->read, 6, msg) +2273 # . . push args +2274 68/push "F - test-skip-string-ignores-escapes"/imm32 +2275 68/push 6/imm32 +2276 b8/copy-to-EAX _test-input-stream/imm32 +2277 ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 4/disp8 . # push *(EAX+4) +2278 # . . call +2279 e8/call check-ints-equal/disp32 +2280 # . . discard args +2281 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +2282 # . epilog +2283 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +2284 5d/pop-to-EBP +2285 c3/return +2286 +2287 test-skip-string-works-from-mid-stream: +2288 # . prolog +2289 55/push-EBP +2290 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +2291 # setup +2292 # . clear-stream(_test-input-stream) +2293 # . . push args +2294 68/push _test-input-stream/imm32 +2295 # . . call +2296 e8/call clear-stream/disp32 +2297 # . . discard args +2298 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +2299 # . write(_test-input-stream, "0 \"a\\\"b\"/yz") +2300 # . indices: 01 2 34 56 +2301 # . . push args +2302 68/push "0 \"a\\\"b\"/yz"/imm32 +2303 68/push _test-input-stream/imm32 +2304 # . . call +2305 e8/call write/disp32 +2306 # . . discard args +2307 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +2308 # precondition: line->read == 2 +2309 c7 0/subop/copy 1/mod/*+disp8 0/rm32/EAX . . . . 4/disp8 2/imm32 # copy to *(EAX+4) +2310 # skip-string(_test-input-stream) +2311 # . . push args +2312 68/push _test-input-stream/imm32 +2313 # . . call +2314 e8/call skip-string/disp32 +2315 # . . discard args +2316 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +2317 # check-ints-equal(line->read, 8, msg) +2318 # . . push args +2319 68/push "F - test-skip-string-works-from-mid-stream"/imm32 +2320 68/push 8/imm32 +2321 b8/copy-to-EAX _test-input-stream/imm32 +2322 ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 4/disp8 . # push *(EAX+4) +2323 # . . call +2324 e8/call check-ints-equal/disp32 +2325 # . . discard args +2326 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +2327 # . epilog +2328 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +2329 5d/pop-to-EBP +2330 c3/return +2331 +2332 skip-string-in-slice: # curr : (address byte), end : (address byte) -> new_curr/EAX +2333 # . prolog +2334 55/push-EBP +2335 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +2336 # . save registers +2337 51/push-ECX +2338 52/push-EDX +2339 53/push-EBX +2340 # ECX = curr +2341 8b/copy 1/mod/*+disp8 5/rm32/EBP . . 1/r32/ECX 8/disp8 . # copy *(EBP+8) to ECX +2342 # EDX = end +2343 8b/copy 1/mod/*+disp8 5/rm32/EBP . . 2/r32/EDX 0xc/disp8 . # copy *(EBP+12) to EDX +2344 # EAX = 0 +2345 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX +2346 # skip initial dquote +2347 41/increment-ECX +2348 $skip-string-in-slice:loop: +2349 # if (curr >= end) return curr +2350 39/compare 3/mod/direct 1/rm32/ECX . . . 2/r32/EDX . . # compare ECX with EDX +2351 73/jump-if-greater-unsigned-or-equal $skip-string-in-slice:return-curr/disp8 +2352 # AL = *curr +2353 8a/copy-byte 0/mod/indirect 1/rm32/ECX . . . 0/r32/AL . . # copy byte at *ECX to AL +2354 $skip-string-in-slice:dquote: +2355 # if (EAX == '"') break +2356 3d/compare-EAX-and 0x22/imm32/double-quote +2357 74/jump-if-equal $skip-string-in-slice:break/disp8 +2358 $skip-string-in-slice:check-for-escape: +2359 # if (EAX == '\') escape next char +2360 3d/compare-EAX-and 0x5c/imm32/backslash +2361 75/jump-if-not-equal $skip-string-in-slice:continue/disp8 +2362 $skip-string-in-slice:escape: +2363 41/increment-ECX +2364 $skip-string-in-slice:continue: +2365 # ++curr +2366 41/increment-ECX +2367 eb/jump $skip-string-in-slice:loop/disp8 +2368 $skip-string-in-slice:break: +2369 # skip final dquote +2370 41/increment-ECX +2371 $skip-string-in-slice:return-curr: +2372 # return curr +2373 89/copy 3/mod/direct 0/rm32/EAX . . . 1/r32/ECX . . # copy ECX to EAX +2374 $skip-string-in-slice:end: +2375 # . restore registers +2376 5b/pop-to-EBX +2377 5a/pop-to-EDX +2378 59/pop-to-ECX +2379 # . epilog +2380 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +2381 5d/pop-to-EBP +2382 c3/return +2383 +2384 test-skip-string-in-slice: +2385 # . prolog +2386 55/push-EBP +2387 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +2388 # setup: (EAX..ECX) = "\"abc\" def" +2389 b8/copy-to-EAX "\"abc\" def"/imm32 +2390 8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX +2391 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/EAX 1/index/ECX . 1/r32/ECX 4/disp8 . # copy EAX+ECX+4 to ECX +2392 05/add-to-EAX 4/imm32 +2393 # EAX = skip-string-in-slice(EAX, ECX) +2394 # . . push args +2395 51/push-ECX +2396 50/push-EAX +2397 # . . call +2398 e8/call skip-string-in-slice/disp32 +2399 # . . discard args +2400 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +2401 # check-ints-equal(ECX-EAX, 4, msg) # number of chars remaining after the string literal +2402 # . . push args +2403 68/push "F - test-skip-string-in-slice"/imm32 +2404 68/push 4/imm32 +2405 # . . push ECX-EAX +2406 29/subtract 3/mod/direct 1/rm32/ECX . . . 0/r32/EAX . . # subtract EAX from ECX +2407 51/push-ECX +2408 # . . call +2409 e8/call check-ints-equal/disp32 +2410 # . . discard args +2411 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +2412 # . epilog +2413 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +2414 5d/pop-to-EBP +2415 c3/return +2416 +2417 test-skip-string-in-slice-ignores-spaces: +2418 # . prolog +2419 55/push-EBP +2420 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +2421 # setup: (EAX..ECX) = "\"a b\"/yz" +2422 b8/copy-to-EAX "\"a b\"/yz"/imm32 +2423 8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX +2424 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/EAX 1/index/ECX . 1/r32/ECX 4/disp8 . # copy EAX+ECX+4 to ECX +2425 05/add-to-EAX 4/imm32 +2426 # EAX = skip-string-in-slice(EAX, ECX) +2427 # . . push args +2428 51/push-ECX +2429 50/push-EAX +2430 # . . call +2431 e8/call skip-string-in-slice/disp32 +2432 # . . discard args +2433 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +2434 # check-ints-equal(ECX-EAX, 3, msg) # number of chars remaining after the string literal +2435 # . . push args +2436 68/push "F - test-skip-string-in-slice-ignores-spaces"/imm32 +2437 68/push 3/imm32 +2438 # . . push ECX-EAX +2439 29/subtract 3/mod/direct 1/rm32/ECX . . . 0/r32/EAX . . # subtract EAX from ECX +2440 51/push-ECX +2441 # . . call +2442 e8/call check-ints-equal/disp32 +2443 # . . discard args +2444 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +2445 # . epilog +2446 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +2447 5d/pop-to-EBP +2448 c3/return +2449 +2450 test-skip-string-in-slice-ignores-escapes: +2451 # . prolog +2452 55/push-EBP +2453 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +2454 # setup: (EAX..ECX) = "\"a\\\"b\"/yz" +2455 b8/copy-to-EAX "\"a\\\"b\"/yz"/imm32 +2456 8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX +2457 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/EAX 1/index/ECX . 1/r32/ECX 4/disp8 . # copy EAX+ECX+4 to ECX +2458 05/add-to-EAX 4/imm32 +2459 # EAX = skip-string-in-slice(EAX, ECX) +2460 # . . push args +2461 51/push-ECX +2462 50/push-EAX +2463 # . . call +2464 e8/call skip-string-in-slice/disp32 +2465 # . . discard args +2466 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +2467 # check-ints-equal(ECX-EAX, 3, msg) # number of chars remaining after the string literal +2468 # . . push args +2469 68/push "F - test-skip-string-in-slice-ignores-escapes"/imm32 +2470 68/push 3/imm32 +2471 # . . push ECX-EAX +2472 29/subtract 3/mod/direct 1/rm32/ECX . . . 0/r32/EAX . . # subtract EAX from ECX +2473 51/push-ECX +2474 # . . call +2475 e8/call check-ints-equal/disp32 +2476 # . . discard args +2477 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +2478 # . epilog +2479 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +2480 5d/pop-to-EBP +2481 c3/return +2482 +2483 test-skip-string-in-slice-stops-at-end: +2484 # . prolog +2485 55/push-EBP +2486 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +2487 # setup: (EAX..ECX) = "\"abc" # unbalanced dquote +2488 b8/copy-to-EAX "\"abc"/imm32 +2489 8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX +2490 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/EAX 1/index/ECX . 1/r32/ECX 4/disp8 . # copy EAX+ECX+4 to ECX +2491 05/add-to-EAX 4/imm32 +2492 # EAX = skip-string-in-slice(EAX, ECX) +2493 # . . push args +2494 51/push-ECX +2495 50/push-EAX +2496 # . . call +2497 e8/call skip-string-in-slice/disp32 +2498 # . . discard args +2499 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +2500 # check-ints-equal(ECX-EAX, 0, msg) # skipped to end of slice +2501 # . . push args +2502 68/push "F - test-skip-string-in-slice-stops-at-end"/imm32 +2503 68/push 0/imm32 +2504 # . . push ECX-EAX +2505 29/subtract 3/mod/direct 1/rm32/ECX . . . 0/r32/EAX . . # subtract EAX from ECX +2506 51/push-ECX +2507 # . . call +2508 e8/call check-ints-equal/disp32 +2509 # . . discard args +2510 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +2511 # . epilog +2512 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +2513 5d/pop-to-EBP +2514 c3/return +2515 +2516 string-length-at-start-of-slice: # curr : (address byte), end : (address byte) -> length/EAX +2517 # . prolog +2518 55/push-EBP +2519 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +2520 # . save registers +2521 51/push-ECX +2522 52/push-EDX +2523 53/push-EBX +2524 # ECX = curr +2525 8b/copy 1/mod/*+disp8 5/rm32/EBP . . 1/r32/ECX 8/disp8 . # copy *(EBP+8) to ECX +2526 # EDX = end +2527 8b/copy 1/mod/*+disp8 5/rm32/EBP . . 2/r32/EDX 0xc/disp8 . # copy *(EBP+12) to EDX +2528 # length/EAX = 0 +2529 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX +2530 # EBX = 0 +2531 31/xor 3/mod/direct 3/rm32/EBX . . . 3/r32/EBX . . # clear EBX +2532 # skip initial dquote +2533 41/increment-ECX +2534 $string-length-at-start-of-slice:loop: +2535 # if (curr >= end) return length +2536 39/compare 3/mod/direct 1/rm32/ECX . . . 2/r32/EDX . . # compare ECX with EDX +2537 73/jump-if-greater-unsigned-or-equal $string-length-at-start-of-slice:end/disp8 +2538 # BL = *curr +2539 8a/copy-byte 0/mod/indirect 1/rm32/ECX . . . 3/r32/BL . . # copy byte at *ECX to BL +2540 $string-length-at-start-of-slice:dquote: +2541 # if (EBX == '"') break +2542 81 7/subop/compare 3/mod/direct 3/rm32/EBX . . . . . 0x22/imm32/dquote # compare EBX +2543 74/jump-if-equal $string-length-at-start-of-slice:end/disp8 +2544 $string-length-at-start-of-slice:check-for-escape: +2545 # if (EBX == '\') escape next char +2546 81 7/subop/compare 3/mod/direct 3/rm32/EBX . . . . . 0x5c/imm32/backslash # compare EBX +2547 75/jump-if-not-equal $string-length-at-start-of-slice:continue/disp8 +2548 $string-length-at-start-of-slice:escape: +2549 # increment curr but not result +2550 41/increment-ECX +2551 $string-length-at-start-of-slice:continue: +2552 # ++result +2553 40/increment-EAX +2554 # ++curr +2555 41/increment-ECX +2556 eb/jump $string-length-at-start-of-slice:loop/disp8 +2557 $string-length-at-start-of-slice:end: +2558 # . restore registers +2559 5b/pop-to-EBX +2560 5a/pop-to-EDX +2561 59/pop-to-ECX +2562 # . epilog +2563 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +2564 5d/pop-to-EBP +2565 c3/return +2566 +2567 test-string-length-at-start-of-slice: +2568 # . prolog +2569 55/push-EBP +2570 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +2571 # setup: (EAX..ECX) = "\"abc\" def" +2572 b8/copy-to-EAX "\"abc\" def"/imm32 +2573 8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX +2574 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/EAX 1/index/ECX . 1/r32/ECX 4/disp8 . # copy EAX+ECX+4 to ECX +2575 05/add-to-EAX 4/imm32 +2576 # EAX = string-length-at-start-of-slice(EAX, ECX) +2577 # . . push args +2578 51/push-ECX +2579 50/push-EAX +2580 # . . call +2581 e8/call string-length-at-start-of-slice/disp32 +2582 # . . discard args +2583 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +2584 # check-ints-equal(EAX, 3, msg) +2585 # . . push args +2586 68/push "F - test-string-length-at-start-of-slice"/imm32 +2587 68/push 3/imm32 +2588 50/push-EAX +2589 # . . call +2590 e8/call check-ints-equal/disp32 +2591 # . . discard args +2592 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +2593 # . epilog +2594 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +2595 5d/pop-to-EBP +2596 c3/return +2597 +2598 test-string-length-at-start-of-slice-escaped: +2599 # . prolog +2600 55/push-EBP +2601 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +2602 # setup: (EAX..ECX) = "\"ab\\c\" def" +2603 b8/copy-to-EAX "\"ab\\c\" def"/imm32 +2604 8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX +2605 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/EAX 1/index/ECX . 1/r32/ECX 4/disp8 . # copy EAX+ECX+4 to ECX +2606 05/add-to-EAX 4/imm32 +2607 # EAX = string-length-at-start-of-slice(EAX, ECX) +2608 # . . push args +2609 51/push-ECX +2610 50/push-EAX +2611 # . . call +2612 e8/call string-length-at-start-of-slice/disp32 +2613 # . . discard args +2614 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +2615 # check-ints-equal(EAX, 3, msg) +2616 # . . push args +2617 68/push "F - test-string-length-at-start-of-slice-escaped"/imm32 +2618 68/push 3/imm32 +2619 50/push-EAX +2620 # . . call +2621 e8/call check-ints-equal/disp32 +2622 # . . discard args +2623 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +2624 # . epilog +2625 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +2626 5d/pop-to-EBP +2627 c3/return +2628 +2629 == data +2630 +2631 Segment-size: +2632 0x1000/imm32/4KB +2633 +2634 Next-string-literal: # tracks the next auto-generated variable name +2635 1/imm32 +2636 +2637 Heap: +2638 # curr +2639 0/imm32 +2640 # limit +2641 0/imm32 +2642 +2643 # length-prefixed string containing just a single space +2644 Space: +2645 # size +2646 1/imm32 +2647 # data +2648 20/space +2649 +2650 # length-prefixed string containing just a single slash +2651 Slash: +2652 # size +2653 1/imm32 +2654 # data +2655 2f/slash +2656 +2657 _test-slice-abc: +2658 22/dquote 61/a 62/b 63/c 22/dquote # "abc" +2659 _test-slice-abc-end: +2660 2f/slash 64/d +2661 _test-slice-abc-metadata-end: +2662 +2663 _test-slice-empty-string-literal: +2664 22/dquote 22/dquote # "" +2665 _test-slice-empty-string-literal-end: +2666 +2667 _test-slice-a-space-b: +2668 22/dquote 61/a 20/space 62/b 22/dquote # "a b" +2669 _test-slice-a-space-b-end: +2670 +2671 _test-slice-a-dquote-b: +2672 22/dquote 61/a 5c/backslash 22/dquote 62/b 22/dquote # "a\"b" +2673 _test-slice-a-dquote-b-end: +2674 +2675 # abc/def/ghi +2676 _test-slice-word: +2677 61/a 62/b 63/c # abc +2678 _test-slice-word-datum-end: +2679 2f/slash 64/d 65/e 66/f # /def +2680 _test-slice-word-end: +2681 2f/slash 67/g 68/h 69/i # /ghi +2682 _test-slice-word-end2: +2683 +2684 # "abc/def"/ghi +2685 _test-slice-literal-string: +2686 22/dquote +2687 61/a 62/b 63/c # abc +2688 2f/slash 64/d 65/e 66/f # /def +2689 22/dquote +2690 _test-slice-literal-string-end: +2691 2f/slash 67/g 68/h 69/i # /ghi +2692 _test-slice-literal-string-with-metadata-end: +2693 +2694 # . . vim:nowrap:textwidth=0 -- cgit 1.4.1-2-gfad0