From bcd2b245aa564f0b2b55404c885e330515b8bbd2 Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Fri, 26 Apr 2019 08:24:27 -0700 Subject: exercise: reimplement print-int-decimal --- subx/074print-int-decimal.subx | 98 +----------------------------------------- 1 file changed, 1 insertion(+), 97 deletions(-) (limited to 'subx') diff --git a/subx/074print-int-decimal.subx b/subx/074print-int-decimal.subx index 86015a00..cce8e21e 100644 --- a/subx/074print-int-decimal.subx +++ b/subx/074print-int-decimal.subx @@ -13,109 +13,13 @@ #? cd/syscall 0x80/imm8 print-int32-decimal: # out : (address stream), n : int32 - # works by generating characters from lowest to highest and pushing them - # to the stack, before popping them one by one into the stream - # - # pseudocode: - # copy ESP to EBX - # EAX = |n| - # while true - # if (EAX == 0) break - # sign-extend EAX into EDX - # EAX, EDX = EAX/10, EAX%10 - # push EDX - # if n < 0 - # push '-' - '0' = -3 - # max/ECX = &out->data[out->length] - # w/EAX = out->write - # curr/EDI = &out->data[out->write] - # while true - # if (ESP == EBX) break - # if (curr >= max) abort - # pop into EDX - # EDX += '0' # convert decimal digit to ascii - # *curr = DL - # ++curr - # ++w - # out->write = w - # # . prolog 55/push-EBP 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP # . save registers - 50/push-EAX - 51/push-ECX - 52/push-EDX - 53/push-EBX - 57/push-EDI - # copy ESP to EBX - 89/copy 3/mod/direct 3/rm32/EBX . . . 4/r32/ESP . . # copy ESP to EBX - # ten/ECX = 10 - b9/copy-to-ECX 0xa/imm32 - # EAX = |n| - 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 0/r32/EAX 0xc/disp8 . # copy *(EBP+12) to EAX - 3d/compare-EAX-with 0/imm32 - 7d/jump-if-greater-or-equal $print-int32-decimal:read-loop/disp8 -$print-int32-decimal:negative: - f7 3/subop/negate 3/mod/direct 0/rm32/EAX . . . . . . # negate EAX -$print-int32-decimal:read-loop: - # if (EAX == 0) break - 3d/compare-EAX-and 0/imm32 - 74/jump-if-equal $print-int32-decimal:read-break/disp8 - # sign-extend - 99/sign-extend-EAX-into-EDX - # EAX, EDX = divide-with-remainder EAX/ten, EAX%ten - f7 7/subop/divide-by 3/mod/direct 1/rm32/ECX . . . . . . # divide EDX:EAX by ECX, storing quotient in EAX and remainder in EDX - # push EDX - 52/push-EDX - eb/jump $print-int32-decimal:read-loop/disp8 -$print-int32-decimal:read-break: - # if (n < 0) push('-') - 81 7/subop/compare 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 0/imm32 # compare *(EBP+12) - 7d/jump-if-greater-or-equal $print-int32-decimal:write/disp8 -$print-int32-decimal:push-negative: - 68/push -3/imm32/dash-minus-zero - # fall through -$print-int32-decimal:write: - # EDI = out - 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 7/r32/EDI 8/disp8 . # copy *(EBP+8) to EDI - # max/ECX = &out->data[out->length] - 8b/copy 1/mod/*+disp8 7/rm32/EDI . . . 1/r32/ECX 8/disp8 . # copy *(EDI+8) to ECX - 8d/copy-address 1/mod/*+disp8 4/rm32/sib 7/base/EDI 1/index/ECX . 1/r32/ECX 0xc/disp8 . # copy EDI+ECX+12 to ECX - # w/EAX = out->write - 8b/copy 0/mod/indirect 7/rm32/EDI . . . 0/r32/EAX . . # copy *EDI to EAX - # curr/EDI = &out->data[out->write] - 8d/copy-address 1/mod/*+disp8 4/rm32/sib 7/base/EDI 0/index/EAX . 7/r32/EDI 0xc/disp8 . # copy EDI+EAX+12 to EDI -$print-int32-decimal:write-loop: - # if (ESP == EBX) break - 39/compare 3/mod/direct 4/rm32/ESP . . . 3/r32/EBX . . # compare ESP and EBX - 74/jump-if-equal $print-int32-decimal:write-break/disp8 - # if (curr >= max) abort - 39/compare 3/mod/direct 7/rm32/EDI . . . 1/r32/ECX . . # compare EDI and ECX - 7d/jump-if-greater-or-equal $print-int32-decimal:abort/disp8 - # pop into EDX - 5a/pop-into-EDX - # EDX += '0' - 81 0/subop/add 3/mod/direct 2/rm32/EDX . . . . . 0x30/imm32/zero # add to EDX -$print-int32-decimal:write-char: - # *curr = DL - 88/copy-byte 0/mod/indirect 7/rm32/EDI . . . 2/r32/DL . . # copy DL to byte at *ECX - # ++curr - 47/increment-EDI - # ++w - 40/increment-EAX - eb/jump $print-int32-decimal:write-loop/disp8 -$print-int32-decimal:write-break: - # out->write = w - 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 7/r32/EDI 8/disp8 . # copy *(EBP+8) to EDI - 89/copy 0/mod/indirect 7/rm32/EDI . . . 0/r32/EAX . . # copy EAX to *EDI $print-int32-decimal:end: + # . reclaim locals # . restore registers - 5f/pop-to-EDI - 5b/pop-to-EBX - 5a/pop-to-EDX - 59/pop-to-ECX - 58/pop-to-EAX # . epilog 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP 5d/pop-to-EBP -- cgit 1.4.1-2-gfad0 From 4a0b4344a3249fd48ab189c97e3638f83a8a7d1b Mon Sep 17 00:00:00 2001 From: nc Date: Fri, 3 May 2019 21:56:55 -0400 Subject: implemented solution --- subx/074print-int-decimal.subx | 110 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 109 insertions(+), 1 deletion(-) (limited to 'subx') diff --git a/subx/074print-int-decimal.subx b/subx/074print-int-decimal.subx index cce8e21e..e5dbaa30 100644 --- a/subx/074print-int-decimal.subx +++ b/subx/074print-int-decimal.subx @@ -6,20 +6,128 @@ # . 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 #? Entry: # run a single test, while debugging -#? e8/call test-print-int32-decimal/disp32 +#? e8/call test-print-int32-decimal-negative/disp32 +#? #? # syscall(exit, Num-test-failures) #? 8b/copy 0/mod/indirect 5/rm32/.disp32 . . 3/r32/EBX Num-test-failures/disp32 # copy *Num-test-failures to EBX #? b8/copy-to-EAX 1/imm32/exit #? cd/syscall 0x80/imm8 print-int32-decimal: # out : (address stream), n : int32 + # PSEUDOCODE + # based on K&R itoa: https://en.wikibooks.org/wiki/C_Programming/stdlib.h/itoa + # push SENTINAL + # if n >= 0: + # goto digit-encode + # else: + # n = -n + # negative = true + # while true: + # push n % 10 + '0' + # n = n / 10 + # break if n == 0 + # if negative: + # push '-' + # while true: + # EAX = pop + # break if EAX == SENTINAL + # out->data[out->write++] = EAX + # # . prolog 55/push-EBP 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP # . save registers + 50/push-EAX + 51/push-ECX + 52/push-EDX + 53/push-EBX + 57/push-EDI + + # negative = false + bf/copy-to-EDI 0/imm32 # EDI = 0 + + # push sentinal for $append-loop + 68/push-sentinel 0/imm32 + + # EAX = n + 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 0/r32/EAX 0xc/disp8 . # EAX = *(EBP+12) + # if n >= 0 jump to digit-encode + 3d/compare-EAX-and 0/imm32 + 7d/jump-if-greater-eq $digit-encode:prelude/disp8 + # else + # n = -n + f7 3/subop/negate 3/mod/direct 0/rm32/EAX # EAX = -EAX + + # negative = true + bf/copy-to-EDI 1/imm32 # EDI = 1 + +$digit-encode:prelude: + # EBX = n + 8b/copy 3/mod/direct 0/rm32/EAX . . . 3/r32/EBX . . # EBX = EAX + +$digit-encode-loop: + # EAX = EBX(n) + 89/copy 3/mod/direct 0/rm32/EAX . . . 3/r32/EBX . . # EAX = EBX + b9/copy-to-ECX 0xa/imm32 + 99/sign-extend-EAX-into-EDX + # EDX:EAX(n) / ECX(10) + + # EDX, EAX = n % 10, n / 10 + f7 7/subop/idiv 3/mod/direct 1/rm32/ECX . . . . . . # divide EDX:EAX by ECX, storing quotient in EAX and remainder in EDX + 81 0/subop/add 3/mod/direct 2/rm32/EDX . . . . . 0x30/imm32 # EDX += '0' (0x30) + + # push n % 10 + '0' + 52/push-EDX + + # EBX = n / 10 + 89/copy 3/mod/direct 3/rm32/EBX . . . 0/r32/EAX . . # EBX = EAX + + # loop if n / 10 > 0 + 3d/compare-EAX-and 0/imm32 + 7f/jump-if-greater $digit-encode-loop/disp8 + # else: + + 8b/copy 3/mod/direct 7/rm32/EDI . . . 0/r32/EAX . . # EAX = EDX + # . if !negative: goto append-loop + 3d/compare-EAX-and 0/imm32 + 74/jump-if-equal $append-loop:prelude/disp8 + # . else + 68/push-negative 0x2d/imm32 # push '-' + +$append-loop:prelude: + # EBX = &out + 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 3/r32/EBX 8/disp8 . # copy *(EBP+8) to EBX + +$append-loop: + # EAX = next_character + 58/pop-to-EAX + + 3d/compare-EAX . . . . . . . 0/imm32 # EAX == 0 + 74/jump-if-equal $append-loop:break/disp8 + + # ECX = out->write + 8b/copy 0/mod/indirect 3/rm32/EBX . . . 1/r32/ECX . . # ECX = *EBX + + # out->data[out->write] = next_character + # . ECX = &out->data[out->write] + 8d/copy-address 1/mod/*+disp8 4/rm32/sib 3/base/EBX 1/index/ECX . 1/r32/ECX 0xc/disp8 . # copy EBX+ECX+12 to ECX + # . out->data[out->write] = EAX + 89/copy 0/mod/indirect 1/rm32/ECX . . . 0/r32/ECX . . # *ECX = EAX + + # out->write++ + ff 0/subop/increment 0/mod/indirect 3/rm32/EBX . . . . . . # (*EBX)++ + eb/jump $append-loop/disp8 + +$append-loop:break: + $print-int32-decimal:end: # . reclaim locals # . restore registers + 57/pop-to-EDI + 5b/pop-to-EBX + 5a/pop-to-EDX + 59/pop-to-ECX + 58/pop-to-EAX # . epilog 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP 5d/pop-to-EBP -- cgit 1.4.1-2-gfad0 From e96fc8696f2a509fc8f95058056cc39494804dd2 Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Sat, 4 May 2019 08:10:36 -0700 Subject: 5135 --- subx/apps/assort | Bin 21302 -> 21306 bytes subx/apps/crenshaw2-1 | Bin 18490 -> 18494 bytes subx/apps/crenshaw2-1b | Bin 19049 -> 19053 bytes subx/apps/factorial | Bin 17406 -> 17410 bytes subx/apps/handle | Bin 18180 -> 18184 bytes subx/apps/hex | Bin 21499 -> 21503 bytes subx/apps/pack | Bin 36091 -> 36095 bytes 7 files changed, 0 insertions(+), 0 deletions(-) (limited to 'subx') diff --git a/subx/apps/assort b/subx/apps/assort index 007ddaa7..04dce00d 100755 Binary files a/subx/apps/assort and b/subx/apps/assort differ diff --git a/subx/apps/crenshaw2-1 b/subx/apps/crenshaw2-1 index 51765a39..a199a555 100755 Binary files a/subx/apps/crenshaw2-1 and b/subx/apps/crenshaw2-1 differ diff --git a/subx/apps/crenshaw2-1b b/subx/apps/crenshaw2-1b index 6f8a2228..453cb3f3 100755 Binary files a/subx/apps/crenshaw2-1b and b/subx/apps/crenshaw2-1b differ diff --git a/subx/apps/factorial b/subx/apps/factorial index 74d03c89..77c2f23b 100755 Binary files a/subx/apps/factorial and b/subx/apps/factorial differ diff --git a/subx/apps/handle b/subx/apps/handle index 17ae017d..549588ef 100755 Binary files a/subx/apps/handle and b/subx/apps/handle differ diff --git a/subx/apps/hex b/subx/apps/hex index 1d455fbd..c3ab8a6b 100755 Binary files a/subx/apps/hex and b/subx/apps/hex differ diff --git a/subx/apps/pack b/subx/apps/pack index 54c3f203..2537f73f 100755 Binary files a/subx/apps/pack and b/subx/apps/pack differ -- cgit 1.4.1-2-gfad0 From 2d61d10eca7b7858588a4aa0eb40a7952120f527 Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Sat, 4 May 2019 12:16:33 -0700 Subject: 5136 - test for a previous bug Thanks Charles Saternos for the bugfix in 4a0b4344a3! --- subx/074print-int-decimal.subx | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'subx') diff --git a/subx/074print-int-decimal.subx b/subx/074print-int-decimal.subx index e5dbaa30..31999dcd 100644 --- a/subx/074print-int-decimal.subx +++ b/subx/074print-int-decimal.subx @@ -178,6 +178,36 @@ test-print-int32-decimal: # . end c3/return +test-print-int32-decimal-zero: + # - check that 0 converts correctly + # setup + # . clear-stream(_test-stream) + # . . push args + 68/push _test-stream/imm32 + # . . call + e8/call clear-stream/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + # print-int32-decimal(_test-stream, 0) + # . . push args + 68/push 0/imm32 + 68/push _test-stream/imm32 + # . . call + e8/call print-int32-decimal/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + # check-stream-equal(_test-stream, "0", msg) + # . . push args + 68/push "F - test-print-int32-decimal-zero"/imm32 + 68/push "0"/imm32 + 68/push _test-stream/imm32 + # . . call + e8/call check-stream-equal/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + # . end + c3/return + test-print-int32-decimal-multiple-digits: # - check that a multi-digit number converts correctly # setup -- cgit 1.4.1-2-gfad0 From 02b105fee40399410e6aa05ee33d4ee2cef8fd4d Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Sat, 4 May 2019 12:58:09 -0700 Subject: 5137 A few minor stylistic things that may ease reading, but not significantly enough that I care to force others to follow them: * no end-of-line comments for instructions without /rm32 * arguments either at tab stops or after 2 spaces * compare 'with' when using in asymmetric tests (greater/lesser), compare 'and' for symmetric equality checking * prefix internal labels with function name --- subx/074print-int-decimal.subx | 129 +++++++++++++++++------------------------ 1 file changed, 52 insertions(+), 77 deletions(-) (limited to 'subx') diff --git a/subx/074print-int-decimal.subx b/subx/074print-int-decimal.subx index 31999dcd..72c99495 100644 --- a/subx/074print-int-decimal.subx +++ b/subx/074print-int-decimal.subx @@ -14,24 +14,25 @@ #? cd/syscall 0x80/imm8 print-int32-decimal: # out : (address stream), n : int32 - # PSEUDOCODE - # based on K&R itoa: https://en.wikibooks.org/wiki/C_Programming/stdlib.h/itoa - # push SENTINAL - # if n >= 0: - # goto digit-encode - # else: - # n = -n - # negative = true - # while true: - # push n % 10 + '0' - # n = n / 10 - # break if n == 0 - # if negative: - # push '-' - # while true: - # EAX = pop - # break if EAX == SENTINAL - # out->data[out->write++] = EAX + # pseudocode: + # push sentinel + # EAX, negative? = abs(n), sign(n) + # while true + # sign-extend EAX into EDX + # EAX, EDX = EAX/10, EAX%10 + # EDX += '0' + # push EDX + # if (EAX == 0) break + # if negative? + # push '-' + # while true + # pop into EAX + # if (EAX == sentinel) break + # out->data[out->write] = AL + # ++out->write + # (based on K&R itoa: https://en.wikibooks.org/wiki/C_Programming/stdlib.h/itoa) + # (this pseudocode contains registers because operations like division + # require specific registers in x86) # # . prolog 55/push-EBP @@ -42,86 +43,60 @@ print-int32-decimal: # out : (address stream), n : int32 52/push-EDX 53/push-EBX 57/push-EDI - - # negative = false - bf/copy-to-EDI 0/imm32 # EDI = 0 - - # push sentinal for $append-loop - 68/push-sentinel 0/imm32 - - # EAX = n + # push sentinel + 68/push 0/imm32/sentinel + # EAX, negative?/EDI = abs(n), sign(n) + bf/copy-to-EDI 0/imm32/false 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 0/r32/EAX 0xc/disp8 . # EAX = *(EBP+12) - # if n >= 0 jump to digit-encode - 3d/compare-EAX-and 0/imm32 - 7d/jump-if-greater-eq $digit-encode:prelude/disp8 - # else - # n = -n - f7 3/subop/negate 3/mod/direct 0/rm32/EAX # EAX = -EAX - - # negative = true - bf/copy-to-EDI 1/imm32 # EDI = 1 - -$digit-encode:prelude: + 3d/compare-EAX-with 0/imm32 + 7d/jump-if-greater-or-equal $print-int32-decimal:read/disp8 + f7 3/subop/negate 3/mod/direct 0/rm32/EAX . . . . . . # negate EAX + bf/copy-to-EDI 1/imm32/true +$print-int32-decimal:read: # EBX = n 8b/copy 3/mod/direct 0/rm32/EAX . . . 3/r32/EBX . . # EBX = EAX - -$digit-encode-loop: +$print-int32-decimal:read-loop: # EAX = EBX(n) 89/copy 3/mod/direct 0/rm32/EAX . . . 3/r32/EBX . . # EAX = EBX - b9/copy-to-ECX 0xa/imm32 + b9/copy-to-ECX 0xa/imm32 + # EAX, EDX = EAX / 10, EAX % 10 99/sign-extend-EAX-into-EDX - # EDX:EAX(n) / ECX(10) - - # EDX, EAX = n % 10, n / 10 f7 7/subop/idiv 3/mod/direct 1/rm32/ECX . . . . . . # divide EDX:EAX by ECX, storing quotient in EAX and remainder in EDX - 81 0/subop/add 3/mod/direct 2/rm32/EDX . . . . . 0x30/imm32 # EDX += '0' (0x30) - - # push n % 10 + '0' + # EDX += '0' + 81 0/subop/add 3/mod/direct 2/rm32/EDX . . . . . 0x30/imm32 # add to EDX + # push EDX 52/push-EDX - # EBX = n / 10 89/copy 3/mod/direct 3/rm32/EBX . . . 0/r32/EAX . . # EBX = EAX - - # loop if n / 10 > 0 + # if (EAX == 0) break 3d/compare-EAX-and 0/imm32 - 7f/jump-if-greater $digit-encode-loop/disp8 - # else: - + 7f/jump-if-greater $print-int32-decimal:read-loop/disp8 +$print-int32-decimal:read-break: + # if (negative?) push('-') 8b/copy 3/mod/direct 7/rm32/EDI . . . 0/r32/EAX . . # EAX = EDX - # . if !negative: goto append-loop - 3d/compare-EAX-and 0/imm32 - 74/jump-if-equal $append-loop:prelude/disp8 - # . else - 68/push-negative 0x2d/imm32 # push '-' - -$append-loop:prelude: - # EBX = &out + 3d/compare-EAX-and 0/imm32 + 74/jump-if-equal $print-int32-decimal:write/disp8 + 68/push 0x2d/imm32/- +$print-int32-decimal:write: + # EBX = out 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 3/r32/EBX 8/disp8 . # copy *(EBP+8) to EBX - -$append-loop: - # EAX = next_character +$print-int32-decimal:write-loop: + # pop into EAX 58/pop-to-EAX - - 3d/compare-EAX . . . . . . . 0/imm32 # EAX == 0 - 74/jump-if-equal $append-loop:break/disp8 - - # ECX = out->write + # if (EAX == sentinel) break + 3d/compare-EAX-and 0/imm32/sentinel + 74/jump-if-equal $print-int32-decimal:end/disp8 + # out->data[out->write] = AL + # . ECX = out->write 8b/copy 0/mod/indirect 3/rm32/EBX . . . 1/r32/ECX . . # ECX = *EBX - - # out->data[out->write] = next_character # . ECX = &out->data[out->write] 8d/copy-address 1/mod/*+disp8 4/rm32/sib 3/base/EBX 1/index/ECX . 1/r32/ECX 0xc/disp8 . # copy EBX+ECX+12 to ECX # . out->data[out->write] = EAX 89/copy 0/mod/indirect 1/rm32/ECX . . . 0/r32/ECX . . # *ECX = EAX - # out->write++ - ff 0/subop/increment 0/mod/indirect 3/rm32/EBX . . . . . . # (*EBX)++ - eb/jump $append-loop/disp8 - -$append-loop:break: - + ff 0/subop/increment 0/mod/indirect 3/rm32/EBX . . . . . . # increment *EBX + eb/jump $print-int32-decimal:write-loop/disp8 $print-int32-decimal:end: - # . reclaim locals # . restore registers 57/pop-to-EDI 5b/pop-to-EBX -- cgit 1.4.1-2-gfad0 From e450523829337ff46d71ca6bab289982de85eafc Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Sat, 4 May 2019 14:07:37 -0700 Subject: 5138 Drop some redundant transfers between registers. The x86 instruction set can perform most operations on all available registers, and things are more comprehensible if each conceptual variable has a single location. --- subx/074print-int-decimal.subx | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) (limited to 'subx') diff --git a/subx/074print-int-decimal.subx b/subx/074print-int-decimal.subx index 72c99495..064d8672 100644 --- a/subx/074print-int-decimal.subx +++ b/subx/074print-int-decimal.subx @@ -43,22 +43,18 @@ print-int32-decimal: # out : (address stream), n : int32 52/push-EDX 53/push-EBX 57/push-EDI + # ten/ECX = 10 + b9/copy-to-ECX 0xa/imm32 # push sentinel 68/push 0/imm32/sentinel # EAX, negative?/EDI = abs(n), sign(n) bf/copy-to-EDI 0/imm32/false 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 0/r32/EAX 0xc/disp8 . # EAX = *(EBP+12) 3d/compare-EAX-with 0/imm32 - 7d/jump-if-greater-or-equal $print-int32-decimal:read/disp8 + 7d/jump-if-greater-or-equal $print-int32-decimal:read-loop/disp8 f7 3/subop/negate 3/mod/direct 0/rm32/EAX . . . . . . # negate EAX bf/copy-to-EDI 1/imm32/true -$print-int32-decimal:read: - # EBX = n - 8b/copy 3/mod/direct 0/rm32/EAX . . . 3/r32/EBX . . # EBX = EAX $print-int32-decimal:read-loop: - # EAX = EBX(n) - 89/copy 3/mod/direct 0/rm32/EAX . . . 3/r32/EBX . . # EAX = EBX - b9/copy-to-ECX 0xa/imm32 # EAX, EDX = EAX / 10, EAX % 10 99/sign-extend-EAX-into-EDX f7 7/subop/idiv 3/mod/direct 1/rm32/ECX . . . . . . # divide EDX:EAX by ECX, storing quotient in EAX and remainder in EDX @@ -66,15 +62,12 @@ $print-int32-decimal:read-loop: 81 0/subop/add 3/mod/direct 2/rm32/EDX . . . . . 0x30/imm32 # add to EDX # push EDX 52/push-EDX - # EBX = n / 10 - 89/copy 3/mod/direct 3/rm32/EBX . . . 0/r32/EAX . . # EBX = EAX # if (EAX == 0) break 3d/compare-EAX-and 0/imm32 7f/jump-if-greater $print-int32-decimal:read-loop/disp8 $print-int32-decimal:read-break: # if (negative?) push('-') - 8b/copy 3/mod/direct 7/rm32/EDI . . . 0/r32/EAX . . # EAX = EDX - 3d/compare-EAX-and 0/imm32 + 81 7/subop/compare 3/mod/direct 7/rm32/EDI . . . . . 0/imm32/false # compare EDI 74/jump-if-equal $print-int32-decimal:write/disp8 68/push 0x2d/imm32/- $print-int32-decimal:write: -- cgit 1.4.1-2-gfad0 From d2410e14c6af85f917f79de6f19fb6e60d37d74f Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Sat, 4 May 2019 14:17:13 -0700 Subject: 5139 Replace the 'negative?' variable with a second read from the stack. It's not clear if this is more or less efficient (https://github.com/akkartik/mu/pull/20#issuecomment-489285130) but taking out the local variable does seem easier to read. --- subx/074print-int-decimal.subx | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) (limited to 'subx') diff --git a/subx/074print-int-decimal.subx b/subx/074print-int-decimal.subx index 064d8672..a3e2eb9e 100644 --- a/subx/074print-int-decimal.subx +++ b/subx/074print-int-decimal.subx @@ -16,14 +16,14 @@ print-int32-decimal: # out : (address stream), n : int32 # pseudocode: # push sentinel - # EAX, negative? = abs(n), sign(n) + # EAX = abs(n) # while true # sign-extend EAX into EDX # EAX, EDX = EAX/10, EAX%10 # EDX += '0' # push EDX # if (EAX == 0) break - # if negative? + # if n < 0 # push '-' # while true # pop into EAX @@ -42,18 +42,15 @@ print-int32-decimal: # out : (address stream), n : int32 51/push-ECX 52/push-EDX 53/push-EBX - 57/push-EDI # ten/ECX = 10 b9/copy-to-ECX 0xa/imm32 # push sentinel 68/push 0/imm32/sentinel - # EAX, negative?/EDI = abs(n), sign(n) - bf/copy-to-EDI 0/imm32/false + # EAX = abs(n) 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 0/r32/EAX 0xc/disp8 . # EAX = *(EBP+12) 3d/compare-EAX-with 0/imm32 7d/jump-if-greater-or-equal $print-int32-decimal:read-loop/disp8 f7 3/subop/negate 3/mod/direct 0/rm32/EAX . . . . . . # negate EAX - bf/copy-to-EDI 1/imm32/true $print-int32-decimal:read-loop: # EAX, EDX = EAX / 10, EAX % 10 99/sign-extend-EAX-into-EDX @@ -66,9 +63,9 @@ $print-int32-decimal:read-loop: 3d/compare-EAX-and 0/imm32 7f/jump-if-greater $print-int32-decimal:read-loop/disp8 $print-int32-decimal:read-break: - # if (negative?) push('-') - 81 7/subop/compare 3/mod/direct 7/rm32/EDI . . . . . 0/imm32/false # compare EDI - 74/jump-if-equal $print-int32-decimal:write/disp8 + # if (n < 0) push('-') + 81 7/subop/compare 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 0/imm32 # compare *(EBP+12) + 7d/jump-if-greater-or-equal $print-int32-decimal:write/disp8 68/push 0x2d/imm32/- $print-int32-decimal:write: # EBX = out @@ -91,7 +88,6 @@ $print-int32-decimal:write-loop: eb/jump $print-int32-decimal:write-loop/disp8 $print-int32-decimal:end: # . restore registers - 57/pop-to-EDI 5b/pop-to-EBX 5a/pop-to-EDX 59/pop-to-ECX -- cgit 1.4.1-2-gfad0 From c4c30c7dc92ad8f5c00bf8facaa089b4ed9cab53 Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Sat, 4 May 2019 14:20:16 -0700 Subject: 5140 - fix an out-of-bounds bug We were writing 32-bit words when we meant to write 8-bit bytes. Most of the time this doesn't matter because: * x86 is little endian, * a write to (x, x+1, x+2, x+3) is over-written by the next to (x+1, x+2, x+3, x+4), and * the 3 higher/later bytes are always 0 so no information is lost The only place this matters is if we're close to the end of the stream. --- subx/074print-int-decimal.subx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'subx') diff --git a/subx/074print-int-decimal.subx b/subx/074print-int-decimal.subx index a3e2eb9e..b7994c68 100644 --- a/subx/074print-int-decimal.subx +++ b/subx/074print-int-decimal.subx @@ -81,8 +81,8 @@ $print-int32-decimal:write-loop: 8b/copy 0/mod/indirect 3/rm32/EBX . . . 1/r32/ECX . . # ECX = *EBX # . ECX = &out->data[out->write] 8d/copy-address 1/mod/*+disp8 4/rm32/sib 3/base/EBX 1/index/ECX . 1/r32/ECX 0xc/disp8 . # copy EBX+ECX+12 to ECX - # . out->data[out->write] = EAX - 89/copy 0/mod/indirect 1/rm32/ECX . . . 0/r32/ECX . . # *ECX = EAX + # . out->data[out->write] = AL + 88/copy-byte 0/mod/indirect 1/rm32/ECX . . . 0/r32/AL . . # copy AL to byte at *ECX # out->write++ ff 0/subop/increment 0/mod/indirect 3/rm32/EBX . . . . . . # increment *EBX eb/jump $print-int32-decimal:write-loop/disp8 -- cgit 1.4.1-2-gfad0 From 85a3e39cd5b4d11bc38d2fc400015770e1994774 Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Sat, 4 May 2019 14:28:48 -0700 Subject: 5141 Another minor stylistic point: I try to use EDI for destination operands. --- subx/074print-int-decimal.subx | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'subx') diff --git a/subx/074print-int-decimal.subx b/subx/074print-int-decimal.subx index b7994c68..a3f9bf9e 100644 --- a/subx/074print-int-decimal.subx +++ b/subx/074print-int-decimal.subx @@ -41,7 +41,7 @@ print-int32-decimal: # out : (address stream), n : int32 50/push-EAX 51/push-ECX 52/push-EDX - 53/push-EBX + 57/push-EDI # ten/ECX = 10 b9/copy-to-ECX 0xa/imm32 # push sentinel @@ -68,8 +68,8 @@ $print-int32-decimal:read-break: 7d/jump-if-greater-or-equal $print-int32-decimal:write/disp8 68/push 0x2d/imm32/- $print-int32-decimal:write: - # EBX = out - 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 3/r32/EBX 8/disp8 . # copy *(EBP+8) to EBX + # EDI = out + 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 7/r32/EDI 8/disp8 . # copy *(EBP+8) to EDI $print-int32-decimal:write-loop: # pop into EAX 58/pop-to-EAX @@ -78,17 +78,17 @@ $print-int32-decimal:write-loop: 74/jump-if-equal $print-int32-decimal:end/disp8 # out->data[out->write] = AL # . ECX = out->write - 8b/copy 0/mod/indirect 3/rm32/EBX . . . 1/r32/ECX . . # ECX = *EBX + 8b/copy 0/mod/indirect 7/rm32/EDI . . . 1/r32/ECX . . # copy *EDI to ECX # . ECX = &out->data[out->write] - 8d/copy-address 1/mod/*+disp8 4/rm32/sib 3/base/EBX 1/index/ECX . 1/r32/ECX 0xc/disp8 . # copy EBX+ECX+12 to ECX + 8d/copy-address 1/mod/*+disp8 4/rm32/sib 7/base/EDI 1/index/ECX . 1/r32/ECX 0xc/disp8 . # copy EBX+ECX+12 to ECX # . out->data[out->write] = AL 88/copy-byte 0/mod/indirect 1/rm32/ECX . . . 0/r32/AL . . # copy AL to byte at *ECX # out->write++ - ff 0/subop/increment 0/mod/indirect 3/rm32/EBX . . . . . . # increment *EBX + ff 0/subop/increment 0/mod/indirect 7/rm32/EDI . . . . . . # increment *EDI eb/jump $print-int32-decimal:write-loop/disp8 $print-int32-decimal:end: # . restore registers - 5b/pop-to-EBX + 5f/pop-to-EDI 5a/pop-to-EDX 59/pop-to-ECX 58/pop-to-EAX -- cgit 1.4.1-2-gfad0 From 37aa2bf3e8c3b22c6b87925148cf938d1c1cc185 Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Sat, 4 May 2019 14:39:45 -0700 Subject: 5142 Hoist address computation out of the loop. I'm giving in to the temptation to optimize here, and violating my own rule of minimizing local variables by introducing 'curr'. My fig leaf is that the number of instructions inside the loop goes down, and duplicating inside the loop may be distracting to readers. --- subx/074print-int-decimal.subx | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) (limited to 'subx') diff --git a/subx/074print-int-decimal.subx b/subx/074print-int-decimal.subx index a3f9bf9e..7f9dadc5 100644 --- a/subx/074print-int-decimal.subx +++ b/subx/074print-int-decimal.subx @@ -25,11 +25,15 @@ print-int32-decimal: # out : (address stream), n : int32 # if (EAX == 0) break # if n < 0 # push '-' + # w = out->write + # curr = &out->data[out->write] # while true # pop into EAX # if (EAX == sentinel) break - # out->data[out->write] = AL - # ++out->write + # *curr = AL + # ++curr + # ++w + # out->write = w # (based on K&R itoa: https://en.wikibooks.org/wiki/C_Programming/stdlib.h/itoa) # (this pseudocode contains registers because operations like division # require specific registers in x86) @@ -47,7 +51,7 @@ print-int32-decimal: # out : (address stream), n : int32 # push sentinel 68/push 0/imm32/sentinel # EAX = abs(n) - 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 0/r32/EAX 0xc/disp8 . # EAX = *(EBP+12) + 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 0/r32/EAX 0xc/disp8 . # copy *(EBP+12) to EAX 3d/compare-EAX-with 0/imm32 7d/jump-if-greater-or-equal $print-int32-decimal:read-loop/disp8 f7 3/subop/negate 3/mod/direct 0/rm32/EAX . . . . . . # negate EAX @@ -70,22 +74,26 @@ $print-int32-decimal:read-break: $print-int32-decimal:write: # EDI = out 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 7/r32/EDI 8/disp8 . # copy *(EBP+8) to EDI + # w/EDX = out->write + 8b/copy 0/mod/indirect 7/rm32/EDI . . . 2/r32/EDX . . # copy *EDI to EDX + # curr/ECX = &out->data[out->write] + 8d/copy-address 1/mod/*+disp8 4/rm32/sib 7/base/EDI 2/index/EDX . 1/r32/ECX 0xc/disp8 . # copy EBX+EDX+12 to ECX $print-int32-decimal:write-loop: # pop into EAX 58/pop-to-EAX # if (EAX == sentinel) break 3d/compare-EAX-and 0/imm32/sentinel - 74/jump-if-equal $print-int32-decimal:end/disp8 - # out->data[out->write] = AL - # . ECX = out->write - 8b/copy 0/mod/indirect 7/rm32/EDI . . . 1/r32/ECX . . # copy *EDI to ECX - # . ECX = &out->data[out->write] - 8d/copy-address 1/mod/*+disp8 4/rm32/sib 7/base/EDI 1/index/ECX . 1/r32/ECX 0xc/disp8 . # copy EBX+ECX+12 to ECX - # . out->data[out->write] = AL + 74/jump-if-equal $print-int32-decimal:write-break/disp8 + # *curr = AL 88/copy-byte 0/mod/indirect 1/rm32/ECX . . . 0/r32/AL . . # copy AL to byte at *ECX - # out->write++ - ff 0/subop/increment 0/mod/indirect 7/rm32/EDI . . . . . . # increment *EDI + # ++curr + 41/increment-ECX + # ++w + 42/increment-EDX eb/jump $print-int32-decimal:write-loop/disp8 +$print-int32-decimal:write-break: + # out->write = w + 89/copy 0/mod/indirect 7/rm32/EDI . . . 2/r32/EDX . . # copy EDX to *EDI $print-int32-decimal:end: # . restore registers 5f/pop-to-EDI -- cgit 1.4.1-2-gfad0 From 8591331a7f674d71c50ea0f560e1412d56001801 Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Sat, 4 May 2019 14:57:04 -0700 Subject: 5143 - add a bounds check We'll just loudly abort the entire program if the output stream isn't large enough to accept all the characters we want to print. --- subx/074print-int-decimal.subx | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'subx') diff --git a/subx/074print-int-decimal.subx b/subx/074print-int-decimal.subx index 7f9dadc5..c6f4951c 100644 --- a/subx/074print-int-decimal.subx +++ b/subx/074print-int-decimal.subx @@ -27,9 +27,11 @@ print-int32-decimal: # out : (address stream), n : int32 # push '-' # w = out->write # curr = &out->data[out->write] + # max = &out->data[out->length] # while true # pop into EAX # if (EAX == sentinel) break + # if (curr >= max) abort # *curr = AL # ++curr # ++w @@ -45,6 +47,7 @@ print-int32-decimal: # out : (address stream), n : int32 50/push-EAX 51/push-ECX 52/push-EDX + 53/push-EBX 57/push-EDI # ten/ECX = 10 b9/copy-to-ECX 0xa/imm32 @@ -78,12 +81,18 @@ $print-int32-decimal:write: 8b/copy 0/mod/indirect 7/rm32/EDI . . . 2/r32/EDX . . # copy *EDI to EDX # curr/ECX = &out->data[out->write] 8d/copy-address 1/mod/*+disp8 4/rm32/sib 7/base/EDI 2/index/EDX . 1/r32/ECX 0xc/disp8 . # copy EBX+EDX+12 to ECX + # max/EBX = &out->data[out->length] + 8b/copy 1/mod/*+disp8 7/rm32/EDI . . . 3/r32/EBX 8/disp8 . # copy *(EDI+8) to EBX + 8d/copy-address 1/mod/*+disp8 4/rm32/sib 7/base/EDI 3/index/EBX . 3/r32/EBX 0xc/disp8 . # copy EDI+EBX+12 to EBX $print-int32-decimal:write-loop: # pop into EAX 58/pop-to-EAX # if (EAX == sentinel) break 3d/compare-EAX-and 0/imm32/sentinel 74/jump-if-equal $print-int32-decimal:write-break/disp8 + # if (curr >= max) abort + 39/compare 3/mod/direct 1/rm32/ECX . . . 3/r32/EBX . . # compare ECX with EBX + 7d/jump-if-greater-or-equal $print-int32-decimal:abort/disp8 # *curr = AL 88/copy-byte 0/mod/indirect 1/rm32/ECX . . . 0/r32/AL . . # copy AL to byte at *ECX # ++curr @@ -97,6 +106,7 @@ $print-int32-decimal:write-break: $print-int32-decimal:end: # . restore registers 5f/pop-to-EDI + 5b/pop-to-EBX 5a/pop-to-EDX 59/pop-to-ECX 58/pop-to-EAX -- cgit 1.4.1-2-gfad0 From d36c42fa3ff4d6f2f4282bde3c586c67fdacda46 Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Sat, 4 May 2019 14:58:13 -0700 Subject: 5144 Pull in some final stylistic and debugging-friendly tweaks from my old version of commit 5132 and earlier. --- subx/074print-int-decimal.subx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'subx') diff --git a/subx/074print-int-decimal.subx b/subx/074print-int-decimal.subx index c6f4951c..04385795 100644 --- a/subx/074print-int-decimal.subx +++ b/subx/074print-int-decimal.subx @@ -14,6 +14,9 @@ #? cd/syscall 0x80/imm8 print-int32-decimal: # out : (address stream), n : int32 + # works by generating characters from lowest to highest and pushing them + # to the stack, before popping them one by one into the stream + # # pseudocode: # push sentinel # EAX = abs(n) @@ -57,7 +60,8 @@ print-int32-decimal: # out : (address stream), n : int32 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 0/r32/EAX 0xc/disp8 . # copy *(EBP+12) to EAX 3d/compare-EAX-with 0/imm32 7d/jump-if-greater-or-equal $print-int32-decimal:read-loop/disp8 - f7 3/subop/negate 3/mod/direct 0/rm32/EAX . . . . . . # negate EAX +$print-int32-decimal:negative: + f7 3/subop/negate 3/mod/direct 0/rm32/EAX . . . . . . # negate EAX $print-int32-decimal:read-loop: # EAX, EDX = EAX / 10, EAX % 10 99/sign-extend-EAX-into-EDX @@ -73,6 +77,7 @@ $print-int32-decimal:read-break: # if (n < 0) push('-') 81 7/subop/compare 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 0/imm32 # compare *(EBP+12) 7d/jump-if-greater-or-equal $print-int32-decimal:write/disp8 +$print-int32-decimal:push-negative: 68/push 0x2d/imm32/- $print-int32-decimal:write: # EDI = out @@ -93,6 +98,7 @@ $print-int32-decimal:write-loop: # if (curr >= max) abort 39/compare 3/mod/direct 1/rm32/ECX . . . 3/r32/EBX . . # compare ECX with EBX 7d/jump-if-greater-or-equal $print-int32-decimal:abort/disp8 +$print-int32-decimal:write-char: # *curr = AL 88/copy-byte 0/mod/indirect 1/rm32/ECX . . . 0/r32/AL . . # copy AL to byte at *ECX # ++curr -- cgit 1.4.1-2-gfad0 From 45bef6b9e952beb8908fd971e7f81c26430a8fa9 Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Sat, 4 May 2019 15:00:01 -0700 Subject: 5145 --- subx/apps/assort | Bin 21306 -> 21414 bytes subx/apps/crenshaw2-1 | Bin 18494 -> 18602 bytes subx/apps/crenshaw2-1b | Bin 19053 -> 19161 bytes subx/apps/factorial | Bin 17410 -> 17518 bytes subx/apps/handle | Bin 18184 -> 18292 bytes subx/apps/hex | Bin 21503 -> 21611 bytes subx/apps/pack | Bin 36095 -> 36203 bytes 7 files changed, 0 insertions(+), 0 deletions(-) (limited to 'subx') diff --git a/subx/apps/assort b/subx/apps/assort index 04dce00d..a0e89c63 100755 Binary files a/subx/apps/assort and b/subx/apps/assort differ diff --git a/subx/apps/crenshaw2-1 b/subx/apps/crenshaw2-1 index a199a555..9e07eb8d 100755 Binary files a/subx/apps/crenshaw2-1 and b/subx/apps/crenshaw2-1 differ diff --git a/subx/apps/crenshaw2-1b b/subx/apps/crenshaw2-1b index 453cb3f3..173ea621 100755 Binary files a/subx/apps/crenshaw2-1b and b/subx/apps/crenshaw2-1b differ diff --git a/subx/apps/factorial b/subx/apps/factorial index 77c2f23b..8313b27a 100755 Binary files a/subx/apps/factorial and b/subx/apps/factorial differ diff --git a/subx/apps/handle b/subx/apps/handle index 549588ef..fa345498 100755 Binary files a/subx/apps/handle and b/subx/apps/handle differ diff --git a/subx/apps/hex b/subx/apps/hex index c3ab8a6b..8992e424 100755 Binary files a/subx/apps/hex and b/subx/apps/hex differ diff --git a/subx/apps/pack b/subx/apps/pack index 2537f73f..1da1a476 100755 Binary files a/subx/apps/pack and b/subx/apps/pack differ -- cgit 1.4.1-2-gfad0 From 5ed05c40bec0cb566fdb8012e134ed61ee93209f Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Wed, 8 May 2019 09:50:59 -0700 Subject: 5146 --- subx/013direct_addressing.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'subx') diff --git a/subx/013direct_addressing.cc b/subx/013direct_addressing.cc index 779c7e0a..c2dfa911 100644 --- a/subx/013direct_addressing.cc +++ b/subx/013direct_addressing.cc @@ -488,7 +488,7 @@ void test_shift_right_logical_r32_with_cl() { } :(before "End Op d3 Subops") -case 5: { // shift right r/m32 by CL, preserving sign +case 5: { // shift right r/m32 by CL, padding zeroes trace(Callstack_depth+1, "run") << "subop: shift right by CL bits, while padding zeroes" << end(); uint8_t count = Reg[ECX].u & 0x1f; // OF is only defined if count is 1 -- cgit 1.4.1-2-gfad0 From 3ae1fd0048cb0745f570df0263a828a30315a00b Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Wed, 8 May 2019 23:10:14 -0700 Subject: 5147 --- subx/039debug.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'subx') diff --git a/subx/039debug.cc b/subx/039debug.cc index 26bb5f7a..8aa40558 100644 --- a/subx/039debug.cc +++ b/subx/039debug.cc @@ -46,14 +46,14 @@ else :(code) string debug_info(uint32_t inst_address) { - uint8_t op = read_mem_u8(EIP); + uint8_t op = read_mem_u8(inst_address); if (op != 0xe8) { ostringstream out; out << HEXBYTE << NUM(op); return out.str(); } - int32_t offset = read_mem_i32(EIP+/*skip op*/1); - uint32_t next_eip = EIP+/*inst length*/5+offset; + int32_t offset = read_mem_i32(inst_address+/*skip op*/1); + uint32_t next_eip = inst_address+/*inst length*/5+offset; if (contains_key(Symbol_name, next_eip)) return "e8/call "+get(Symbol_name, next_eip); ostringstream out; -- cgit 1.4.1-2-gfad0 From fbc21293299f1d5b2d108e3ee98ea4e9083965b5 Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Thu, 9 May 2019 09:25:01 -0700 Subject: 5148 Snapshot of incomplete work to have the memory allocator use `mmap` rather than `brk`. C tests pass, but the SubX layers are still broken. --- subx/012elf.cc | 16 +++++++--------- subx/037heap.cc | 29 ----------------------------- subx/038---literal_strings.cc | 7 +++++++ subx/053new-segment.subx | 13 ++++++++++++- subx/069allocate.subx | 8 -------- 5 files changed, 26 insertions(+), 47 deletions(-) delete mode 100644 subx/037heap.cc (limited to 'subx') diff --git a/subx/012elf.cc b/subx/012elf.cc index 0f058504..6a31826e 100644 --- a/subx/012elf.cc +++ b/subx/012elf.cc @@ -129,15 +129,13 @@ void load_segment_from_program_header(uint8_t* elf_contents, int segment_index, } :(before "End Includes") -// Very primitive/fixed/insecure ELF segments for now: just consecutive VMAs. -// code: 0x09000000 -> 0x09ffffff -// data/heap: 0x0a000000 -> 0x0affffff -// stack: 0x0b000ffc -> 0x0b000000 (downward) -const int CODE_SEGMENT = 0x09000000; -const int DATA_SEGMENT = 0x0a000000; // keep sync'd with `Heap.limit` in allocate.subx -const int STACK_SEGMENT = 0x0b000000; -const int AFTER_STACK = 0x0c000000; -const int ARGV_DATA_SEGMENT = 0x0c000000; +// Very primitive/fixed/insecure ELF segments for now. +// code: 0x09000000 -> 0x09ffffff +// stack: 0xbe000000 -> 0xb0000000 (downward) +const int CODE_SEGMENT = 0x09000000; +const int STACK_SEGMENT = 0xb0000000; +const int AFTER_STACK = 0xbe000000; +const int ARGV_DATA_SEGMENT = 0xbf000000; :(before "End Dump Info for Instruction") //? dump_stack(); // slow :(code) diff --git a/subx/037heap.cc b/subx/037heap.cc deleted file mode 100644 index 315fd0d5..00000000 --- a/subx/037heap.cc +++ /dev/null @@ -1,29 +0,0 @@ -//: Support for dynamic allocation. -//: -//: Just provide a special label marking the first unused address in the data -//: segment. Then we'll write SubX helpers to make use of it. - -:(before "Begin rewrite_global_variables") -insert_heap_global_variable(p); -:(code) -void insert_heap_global_variable(program& p) { - if (SIZE(p.segments) < 2) - return; // no data segment defined - // Start-of-heap: - p.segments.at(1).lines.push_back(label("Start-of-heap")); -} - -line label(string s) { - line result; - result.words.push_back(word()); - result.words.back().data = (s+":"); - return result; -} - -line imm32(const string& s) { - line result; - result.words.push_back(word()); - result.words.back().data = s; - result.words.back().metadata.push_back("imm32"); - return result; -} diff --git a/subx/038---literal_strings.cc b/subx/038---literal_strings.cc index 65a7740b..9b2c3902 100644 --- a/subx/038---literal_strings.cc +++ b/subx/038---literal_strings.cc @@ -184,6 +184,13 @@ void skip_comment(istream& in) { } } +line label(string s) { + line result; + result.words.push_back(word()); + result.words.back().data = (s+":"); + return result; +} + // helper for tests void parse_instruction_character_by_character(const string& line_data) { vector out; diff --git a/subx/053new-segment.subx b/subx/053new-segment.subx index 1669b097..21837628 100644 --- a/subx/053new-segment.subx +++ b/subx/053new-segment.subx @@ -1,4 +1,15 @@ -# Create a new segment (for data) using mmap(). +# Create a new segment (pool of memory for allocating chunks from) in the form +# of an *allocation descriptor* that can be passed to the memory allocator +# (defined in a later layer). +# +# Currently an allocation descriptor consists of just the bounds of the pool of +# available memory: +# +# curr : address +# end : address +# +# This isn't enough information to reclaim individual allocations. We can't +# support arbitrary reclamation yet. == code # instruction effective address register displacement immediate diff --git a/subx/069allocate.subx b/subx/069allocate.subx index 402467fe..14e9fd50 100644 --- a/subx/069allocate.subx +++ b/subx/069allocate.subx @@ -16,14 +16,6 @@ # very same 'allocate' helper. They just need a new allocation descriptor for # their book-keeping. -== data - -# The 'global' allocation descriptor. Pass this into 'allocate' to claim a -# hitherto unused bit of memory. -Heap: - Start-of-heap/imm32 # curr - 0x0b000000/imm32 # limit; keep sync'd with DATA_SEGMENT + SEGMENT_ALIGNMENT - == code # instruction effective address register displacement immediate # . op subop mod rm32 base index scale r32 -- cgit 1.4.1-2-gfad0 From a1305217980a75ed5534daa7016a83f2d5602b43 Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Fri, 10 May 2019 10:24:24 -0700 Subject: 5149 Tests still broken. --- subx/012elf.cc | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'subx') diff --git a/subx/012elf.cc b/subx/012elf.cc index 6a31826e..11e0e4bc 100644 --- a/subx/012elf.cc +++ b/subx/012elf.cc @@ -66,6 +66,7 @@ void load_elf_contents(uint8_t* elf_contents, size_t size, int argc, char* argv[ assert(overlap.find(STACK_SEGMENT) == overlap.end()); Mem.push_back(vma(STACK_SEGMENT)); assert(overlap.find(AFTER_STACK) == overlap.end()); + // The stack grows downward. Reg[ESP].u = AFTER_STACK; Reg[EBP].u = 0; EIP = e_entry; @@ -130,10 +131,14 @@ void load_segment_from_program_header(uint8_t* elf_contents, int segment_index, :(before "End Includes") // Very primitive/fixed/insecure ELF segments for now. -// code: 0x09000000 -> 0x09ffffff -// stack: 0xbe000000 -> 0xb0000000 (downward) +// code: 0x09000000 -> 0x09ffffff (specified in ELF binary) +// data: 0x0a000000 -> 0x0affffff (specified in ELF binary) +// --- heap gets mmap'd somewhere here --- +// stack: 0xbdffffff -> 0xbd000000 (downward; not in ELF binary) +// argv hack: 0xbf000000 -> 0xc0000000 (not in ELF binary) const int CODE_SEGMENT = 0x09000000; -const int STACK_SEGMENT = 0xb0000000; +const int DATA_SEGMENT = 0x0a000000; +const int STACK_SEGMENT = 0xbd000000; const int AFTER_STACK = 0xbe000000; const int ARGV_DATA_SEGMENT = 0xbf000000; :(before "End Dump Info for Instruction") -- cgit 1.4.1-2-gfad0 From cdfb2dbfcf18cd2f23bf74199082392c3692a599 Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Fri, 10 May 2019 11:18:56 -0700 Subject: 5150 - change interface for 'new-segment' Tests still failing. Passing until layer 53. --- subx/053new-segment.subx | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) (limited to 'subx') diff --git a/subx/053new-segment.subx b/subx/053new-segment.subx index 21837628..83c890ea 100644 --- a/subx/053new-segment.subx +++ b/subx/053new-segment.subx @@ -17,39 +17,54 @@ # . 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 Entry: # manual test - # EAX = new-segment(0x1000) + # var ad/ECX : (address allocation-descriptor) = {0, 0} + 68/push 0/imm32/limit + 68/push 0/imm32/curr + 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX + # new-segment(0x1000, ad) # . . push args + 51/push-ECX 68/push 0x1000/imm32 # . . call e8/call new-segment/disp32 # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + # EAX = ad->curr + 8b/copy 0/mod/indirect 1/rm32/ECX . . . 0/r32/EAX . . # copy *ECX to EAX # write to *EAX to check that we have access to the newly-allocated segment c7 0/subop/copy 0/mod/direct 0/rm32/EAX . . . . . 0x34/imm32 # copy to *EAX - # syscall(exit, EAX) 89/copy 3/mod/direct 3/rm32/EBX . . . 0/r32/EAX . . # copy EAX to EBX b8/copy-to-EAX 1/imm32/exit cd/syscall 0x80/imm8 -new-segment: # len : int -> address +new-segment: # len : int, ad : (address allocation-descriptor) # . prolog 55/push-EBP 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + # . save registers + 50/push-EAX 53/push-EBX # copy len to _mmap-new-segment->len - # TODO: compute _mmap-new-segment+4 before runtime 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 0/r32/EAX 8/disp8 . # copy *(EBP+8) to EAX - bb/copy-to-EBX _mmap-new-segment/imm32 - 89/copy 1/mod/*+disp8 3/rm32/EBX . . . 0/r32/EAX 4/disp8 . # copy EAX to *(EBX+4) + 89/copy 0/mod/indirect 5/rm32/.disp32 . . 0/r32/EAX _mmap-new-segment:len/disp32 # copy EAX to *_mmap-new-segment:len # mmap(_mmap-new-segment) bb/copy-to-EBX _mmap-new-segment/imm32 b8/copy-to-EAX 0x5a/imm32/mmap cd/syscall 0x80/imm8 + # copy {EAX, EAX+len} to *ad + # . EBX = ad + 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 3/r32/EBX 0xc/disp8 . # copy *(EBP+12) to EBX + # . *EBX = EAX + 89/copy 0/mod/indirect 3/rm32/EBX . . . 0/r32/EAX . . # copy EAX to *EBX + # . *(EBX+4) = EAX+len + 03/add 1/mod/*+disp8 5/rm32/EBP . . . 0/r32/EAX 8/disp8 . # add *(EBP+8) to EAX + 89/copy 1/mod/*+disp8 3/rm32/EBX . . . 0/r32/EAX 4/disp8 . # copy EAX to *(EBX+4) $new-segment:end: - # . epilog + # . restore registers 5b/pop-to-EBX + 58/pop-to-EAX + # . epilog 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP 5d/pop-to-EBP c3/return @@ -60,6 +75,7 @@ $new-segment:end: _mmap-new-segment: # type mmap_arg_struct # addr 0/imm32 +_mmap-new-segment:len: # len 0/imm32 # protection flags -- cgit 1.4.1-2-gfad0 From c88b9e31259d433c7e63fcb19d430daf9b1c723c Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Fri, 10 May 2019 16:45:22 -0700 Subject: 5151 - use mmap everywhere we need a heap All tests passing now. Things are very explicit; before a program can `allocate` memory, it has to first obtain a segment from the OS using `new-segment`. --- subx/012elf.cc | 17 +++++++---- subx/020syscalls.cc | 21 ++++++++------ subx/070new-stream.subx | 15 +++++----- subx/072slice.subx | 16 +++++++++-- subx/apps/assort | Bin 21414 -> 21492 bytes subx/apps/assort.subx | 24 ++++++++++++++++ subx/apps/crenshaw2-1 | Bin 18602 -> 18651 bytes subx/apps/crenshaw2-1b | Bin 19161 -> 19210 bytes subx/apps/dquotes | Bin 20916 -> 21106 bytes subx/apps/dquotes.subx | 24 ++++++++++++++++ subx/apps/factorial | Bin 17518 -> 17567 bytes subx/apps/handle | Bin 18292 -> 18394 bytes subx/apps/handle.subx | 74 +++++++++++++++++++++++++++++++++--------------- subx/apps/hex | Bin 21611 -> 21660 bytes subx/apps/pack | Bin 36203 -> 36252 bytes 15 files changed, 146 insertions(+), 45 deletions(-) (limited to 'subx') diff --git a/subx/012elf.cc b/subx/012elf.cc index 11e0e4bc..d0a3fbd2 100644 --- a/subx/012elf.cc +++ b/subx/012elf.cc @@ -134,13 +134,20 @@ void load_segment_from_program_header(uint8_t* elf_contents, int segment_index, // code: 0x09000000 -> 0x09ffffff (specified in ELF binary) // data: 0x0a000000 -> 0x0affffff (specified in ELF binary) // --- heap gets mmap'd somewhere here --- -// stack: 0xbdffffff -> 0xbd000000 (downward; not in ELF binary) -// argv hack: 0xbf000000 -> 0xc0000000 (not in ELF binary) +// stack: 0x7dffffff -> 0x7d000000 (downward; not in ELF binary) +// argv hack: 0x7f000000 -> 0x7fffffff (not in ELF binary) +// +// For now we avoid addresses with the most significant bit set; SubX doesn't +// support unsigned comparison yet (https://github.com/akkartik/mu/issues/30) +// Once we do, we can go up to 0xc0000000; higher addresses are reserved for +// the Linux kernel. const int CODE_SEGMENT = 0x09000000; const int DATA_SEGMENT = 0x0a000000; -const int STACK_SEGMENT = 0xbd000000; -const int AFTER_STACK = 0xbe000000; -const int ARGV_DATA_SEGMENT = 0xbf000000; +const int STACK_SEGMENT = 0x7d000000; +const int AFTER_STACK = 0x7e000000; +const int ARGV_DATA_SEGMENT = 0x7f000000; +// When updating the above memory map, don't forget to update `mmap`'s +// implementation in the 'syscalls' layer. :(before "End Dump Info for Instruction") //? dump_stack(); // slow :(code) diff --git a/subx/020syscalls.cc b/subx/020syscalls.cc index a17e9525..6b9faa2c 100644 --- a/subx/020syscalls.cc +++ b/subx/020syscalls.cc @@ -24,14 +24,14 @@ void process_int80() { trace(Callstack_depth+1, "run") << "read: " << Reg[EBX].u << ' ' << Reg[ECX].u << ' ' << Reg[EDX].u << end(); Reg[EAX].i = read(/*file descriptor*/Reg[EBX].u, /*memory buffer*/mem_addr_u8(Reg[ECX].u), /*size*/Reg[EDX].u); trace(Callstack_depth+1, "run") << "result: " << Reg[EAX].i << end(); - if (Reg[EAX].i == -1) raise << strerror(errno) << '\n' << end(); + if (Reg[EAX].i == -1) raise << "read: " << strerror(errno) << '\n' << end(); break; case 4: trace(Callstack_depth+1, "run") << "write: " << Reg[EBX].u << ' ' << Reg[ECX].u << ' ' << Reg[EDX].u << end(); trace(Callstack_depth+1, "run") << Reg[ECX].u << " => " << mem_addr_string(Reg[ECX].u, Reg[EDX].u) << end(); Reg[EAX].i = write(/*file descriptor*/Reg[EBX].u, /*memory buffer*/mem_addr_u8(Reg[ECX].u), /*size*/Reg[EDX].u); trace(Callstack_depth+1, "run") << "result: " << Reg[EAX].i << end(); - if (Reg[EAX].i == -1) raise << strerror(errno) << '\n' << end(); + if (Reg[EAX].i == -1) raise << "write: " << strerror(errno) << '\n' << end(); break; case 5: { check_flags(ECX); @@ -40,14 +40,14 @@ void process_int80() { trace(Callstack_depth+1, "run") << Reg[EBX].u << " => " << mem_addr_kernel_string(Reg[EBX].u) << end(); Reg[EAX].i = open(/*filename*/mem_addr_kernel_string(Reg[EBX].u), /*flags*/Reg[ECX].u, /*mode*/0640); trace(Callstack_depth+1, "run") << "result: " << Reg[EAX].i << end(); - if (Reg[EAX].i == -1) raise << strerror(errno) << '\n' << end(); + if (Reg[EAX].i == -1) raise << "open: " << strerror(errno) << '\n' << end(); break; } case 6: trace(Callstack_depth+1, "run") << "close: " << Reg[EBX].u << end(); Reg[EAX].i = close(/*file descriptor*/Reg[EBX].u); trace(Callstack_depth+1, "run") << "result: " << Reg[EAX].i << end(); - if (Reg[EAX].i == -1) raise << strerror(errno) << '\n' << end(); + if (Reg[EAX].i == -1) raise << "close: " << strerror(errno) << '\n' << end(); break; case 8: check_mode(ECX); @@ -55,14 +55,14 @@ void process_int80() { trace(Callstack_depth+1, "run") << Reg[EBX].u << " => " << mem_addr_kernel_string(Reg[EBX].u) << end(); Reg[EAX].i = creat(/*filename*/mem_addr_kernel_string(Reg[EBX].u), /*mode*/0640); trace(Callstack_depth+1, "run") << "result: " << Reg[EAX].i << end(); - if (Reg[EAX].i == -1) raise << strerror(errno) << '\n' << end(); + if (Reg[EAX].i == -1) raise << "creat: " << strerror(errno) << '\n' << end(); break; case 10: trace(Callstack_depth+1, "run") << "unlink: " << Reg[EBX].u << end(); trace(Callstack_depth+1, "run") << Reg[EBX].u << " => " << mem_addr_kernel_string(Reg[EBX].u) << end(); Reg[EAX].i = unlink(/*filename*/mem_addr_kernel_string(Reg[EBX].u)); trace(Callstack_depth+1, "run") << "result: " << Reg[EAX].i << end(); - if (Reg[EAX].i == -1) raise << strerror(errno) << '\n' << end(); + if (Reg[EAX].i == -1) raise << "unlink: " << strerror(errno) << '\n' << end(); break; case 38: trace(Callstack_depth+1, "run") << "rename: " << Reg[EBX].u << " -> " << Reg[ECX].u << end(); @@ -70,7 +70,7 @@ void process_int80() { trace(Callstack_depth+1, "run") << Reg[ECX].u << " => " << mem_addr_kernel_string(Reg[ECX].u) << end(); Reg[EAX].i = rename(/*old filename*/mem_addr_kernel_string(Reg[EBX].u), /*new filename*/mem_addr_kernel_string(Reg[ECX].u)); trace(Callstack_depth+1, "run") << "result: " << Reg[EAX].i << end(); - if (Reg[EAX].i == -1) raise << strerror(errno) << '\n' << end(); + if (Reg[EAX].i == -1) raise << "rename: " << strerror(errno) << '\n' << end(); break; case 45: // brk: modify size of data segment trace(Callstack_depth+1, "run") << "grow data segment to " << Reg[EBX].u << end(); @@ -110,7 +110,12 @@ void check_mode(int reg) { } :(before "End Globals") -uint32_t Next_segment = 0xb0000000; // 0xc0000000 and up is reserved for Linux kernel +// Very primitive/fixed/insecure mmap segments for now. +// For now we avoid addresses with the most significant bit set; SubX doesn't +// support unsigned comparison yet (https://github.com/akkartik/mu/issues/30) +// Once we do, we can go up to 0xc0000000; higher addresses are reserved for +// the Linux kernel. +uint32_t Next_segment = 0x7c000000; const uint32_t SPACE_FOR_SEGMENT = 0x01000000; :(code) uint32_t new_segment(uint32_t length) { diff --git a/subx/070new-stream.subx b/subx/070new-stream.subx index ad6ab68d..8a833581 100644 --- a/subx/070new-stream.subx +++ b/subx/070new-stream.subx @@ -68,20 +68,21 @@ test-new-stream: # . prolog 55/push-EBP 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP - # var ad/ECX : (address allocation-descriptor) = allocate-region(Heap, 512) - # . EAX = allocate-region(Heap, 512) + # var heap/ECX : (address allocation-descriptor) = {0, 0} + 68/push 0/imm32/limit + 68/push 0/imm32/curr + 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX + # heap = new-segment(512) # . . push args + 51/push-ECX 68/push 0x200/imm32 - 68/push Heap/imm32 # . . call - e8/call allocate-region/disp32 + e8/call new-segment/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - # . ECX = EAX - 89/copy 3/mod/direct 1/rm32/ECX . . . 0/r32/EAX . . # copy EAX to ECX # var start/EDX = ad->curr 8b/copy 0/mod/indirect 1/rm32/ECX . . . 2/r32/EDX . . # copy *ECX to EDX - # EAX = new-stream(ad, 3, 2) + # EAX = new-stream(heap, 3, 2) # . . push args 68/push 2/imm32 68/push 3/imm32 diff --git a/subx/072slice.subx b/subx/072slice.subx index 9c285097..683c4c7b 100644 --- a/subx/072slice.subx +++ b/subx/072slice.subx @@ -917,14 +917,26 @@ test-slice-to-string: # . prolog 55/push-EBP 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + # var heap/EDX : (address allocation-descriptor) = {0, 0} + 68/push 0/imm32/limit + 68/push 0/imm32/curr + 89/copy 3/mod/direct 2/rm32/EDX . . . 4/r32/ESP . . # copy ESP to EDX + # heap = new-segment(512) + # . . push args + 52/push-EDX + 68/push 0x200/imm32 + # . . call + e8/call new-segment/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP # var slice/ECX = "Abc" 68/push _test-slice-data-3/imm32/end 68/push _test-slice-data-0/imm32/start 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX - # EAX = slice-to-string(Heap, slice) + # EAX = slice-to-string(heap, slice) # . . push args 51/push-ECX - 68/push Heap/imm32 + 52/push-EDX # . . call e8/call slice-to-string/disp32 # . . discard args diff --git a/subx/apps/assort b/subx/apps/assort index a0e89c63..e331ce8a 100755 Binary files a/subx/apps/assort and b/subx/apps/assort differ diff --git a/subx/apps/assort.subx b/subx/apps/assort.subx index ecb1c213..cfdef5e1 100644 --- a/subx/apps/assort.subx +++ b/subx/apps/assort.subx @@ -26,12 +26,30 @@ Entry: # run tests if necessary, convert stdin if not # for debugging: run a single test +#? # . Heap = new-segment(4096) +#? # . . push args +#? 68/push Heap/imm32 +#? 68/push 0x1000/imm32 +#? # . . call +#? e8/call new-segment/disp32 +#? # . . discard args +#? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +#? # . test() #? e8/call test-convert/disp32 #? 8b/copy 0/mod/indirect 5/rm32/.disp32 . . 3/r32/EBX Num-test-failures/disp32 # copy *Num-test-failures to EBX #? eb/jump $main:end/disp8 # . prolog 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + # initialize heap + # . Heap = new-segment(4096) + # . . push args + 68/push Heap/imm32 + 68/push 0x1000/imm32 + # . . call + e8/call new-segment/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP # - if argc > 1 and argv[1] == "test", then return run_tests() # . argc > 1 81 7/subop/compare 1/mod/*+disp8 5/rm32/EBP . . . . 0/disp8 1/imm32 # compare *EBP @@ -1316,4 +1334,10 @@ Segment-size: 0x100/imm32 #? 0x1000/imm32/4KB +Heap: + # curr + 0/imm32 + # limit + 0/imm32 + # . . vim:nowrap:textwidth=0 diff --git a/subx/apps/crenshaw2-1 b/subx/apps/crenshaw2-1 index 9e07eb8d..eb187bb3 100755 Binary files a/subx/apps/crenshaw2-1 and b/subx/apps/crenshaw2-1 differ diff --git a/subx/apps/crenshaw2-1b b/subx/apps/crenshaw2-1b index 173ea621..e8d72937 100755 Binary files a/subx/apps/crenshaw2-1b and b/subx/apps/crenshaw2-1b differ diff --git a/subx/apps/dquotes b/subx/apps/dquotes index e1d12550..b63744d1 100644 Binary files a/subx/apps/dquotes and b/subx/apps/dquotes differ diff --git a/subx/apps/dquotes.subx b/subx/apps/dquotes.subx index b236ac2f..fcac2698 100644 --- a/subx/apps/dquotes.subx +++ b/subx/apps/dquotes.subx @@ -22,12 +22,30 @@ Entry: # run tests if necessary, convert stdin if not # for debugging: run a single test +#? # . Heap = new-segment(4096) +#? # . . push args +#? 68/push Heap/imm32 +#? 68/push 0x1000/imm32 +#? # . . call +#? e8/call new-segment/disp32 +#? # . . discard args +#? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +#? # . test() #? e8/call test-next-word-returns-string-with-escapes/disp32 #? 8b/copy 0/mod/indirect 5/rm32/.disp32 . . 3/r32/EBX Num-test-failures/disp32 # copy *Num-test-failures to EBX #? eb/jump $main:end/disp8 # . prolog 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + # initialize heap + # . Heap = new-segment(4096) + # . . push args + 68/push Heap/imm32 + 68/push 0x1000/imm32 + # . . call + e8/call new-segment/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP # - if argc > 1 and argv[1] == "test", then return run_tests() # . argc > 1 81 7/subop/compare 1/mod/*+disp8 5/rm32/EBP . . . . 0/disp8 1/imm32 # compare *EBP @@ -1054,4 +1072,10 @@ Segment-size: Next-string-literal: # tracks the next auto-generated variable name 1/imm32 +Heap: + # curr + 0/imm32 + # limit + 0/imm32 + # . . vim:nowrap:textwidth=0 diff --git a/subx/apps/factorial b/subx/apps/factorial index 8313b27a..2c47ab8a 100755 Binary files a/subx/apps/factorial and b/subx/apps/factorial differ diff --git a/subx/apps/handle b/subx/apps/handle index fa345498..274677fe 100755 Binary files a/subx/apps/handle and b/subx/apps/handle differ diff --git a/subx/apps/handle.subx b/subx/apps/handle.subx index f866ea59..0ed12067 100644 --- a/subx/apps/handle.subx +++ b/subx/apps/handle.subx @@ -79,17 +79,29 @@ test-new: # . prolog 55/push-EBP 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + # var heap/EDX : (address allocation-descriptor) = {0, 0} + 68/push 0/imm32/limit + 68/push 0/imm32/curr + 89/copy 3/mod/direct 2/rm32/EDX . . . 4/r32/ESP . . # copy ESP to EDX + # heap = new-segment(512) + # . . push args + 52/push-EDX + 68/push 0x200/imm32 + # . . call + e8/call new-segment/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP # *Next-alloc-id = 0x34 c7 0/subop/copy 0/mod/indirect 5/rm32/.disp32 . . . Next-alloc-id/disp32 0x34/imm32 # copy to *Next-alloc-id # var handle/ECX = {0, 0} 68/push 0/imm32/address 68/push 0/imm32/alloc-id 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX - # new(Heap, 2, handle/ECX) + # new(heap, 2, handle/ECX) # . . push args 51/push-ECX 68/push 2/imm32/size - 68/push Heap/imm32 + 52/push-EDX # . . call e8/call new/disp32 # . . discard args @@ -234,17 +246,29 @@ test-lookup-success: 55/push-EBP 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP # . save registers + # var heap/EBX : (address allocation-descriptor) = {0, 0} + 68/push 0/imm32/limit + 68/push 0/imm32/curr + 89/copy 3/mod/direct 3/rm32/EBX . . . 4/r32/ESP . . # copy ESP to EBX + # heap = new-segment(512) + # . . push args + 53/push-EBX + 68/push 0x200/imm32 + # . . call + e8/call new-segment/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP # var handle/ECX = {0, 0} 68/push 0/imm32/address 68/push 0/imm32/alloc-id 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX - # var old_top/EDX = Heap->curr - 8b/copy 0/mod/indirect 5/rm32/.disp32 . . 2/r32/EDX Heap/disp32 . # copy *Heap to EDX - # new(Heap, 2, handle) + # var old_top/EDX = heap->curr + 8b/copy 0/mod/indirect 3/rm32/EBX . . . 2/r32/EDX . . # copy *EBX to EDX + # new(heap, 2, handle) # . . push args 51/push-ECX 68/push 2/imm32/size - 68/push Heap/imm32 + 53/push-EBX # . . call e8/call new/disp32 # . . discard args @@ -256,7 +280,7 @@ test-lookup-success: e8/call lookup/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - # EAX contains old top of Heap, except skipping the alloc id in the payload + # EAX contains old top of heap, except skipping the alloc id in the payload # . check-ints-equal(EAX, old_top+4, msg) # . . push args 68/push "F - test-lookup-success"/imm32 @@ -282,38 +306,46 @@ test-lookup-failure: # . prolog 55/push-EBP 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP - # . save registers - 50/push-EAX - 51/push-ECX - 52/push-EDX + # var heap/ESI : (address allocation-descriptor) = {0, 0} + 68/push 0/imm32/limit + 68/push 0/imm32/curr + 89/copy 3/mod/direct 6/rm32/ESI . . . 4/r32/ESP . . # copy ESP to ESI + # heap = new-segment(512) + # . . push args + 56/push-ESI + 68/push 0x200/imm32 + # . . call + e8/call new-segment/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP # var h1/ECX = {0, 0} 68/push 0/imm32/address 68/push 0/imm32/alloc-id 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX - # var old_top/EBX = Heap->curr - 8b/copy 0/mod/indirect 5/rm32/.disp32 . . 3/r32/EBX Heap/disp32 . # copy *Heap to EBX + # var old_top/EBX = heap->curr + 8b/copy 0/mod/indirect 6/rm32/ESI . . . 3/r32/EBX . . # copy *ESI to EBX # first allocation, to h1 - # . new(Heap, 2, h1) + # . new(heap, 2, h1) # . . push args 51/push-ECX 68/push 2/imm32/size - 68/push Heap/imm32 + 56/push-ESI # . . call e8/call new/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - # reset Heap->curr to mimic reclamation - 89/copy 0/mod/indirect 5/rm32/.disp32 . . 3/r32/EBX Heap/disp32 . # copy EBX to *Heap + # reset heap->curr to mimic reclamation + 89/copy 0/mod/indirect 6/rm32/ESI . . . 3/r32/EBX . . # copy EBX to *ESI # second allocation that returns the same address as the first # var h2/EDX = {0, 0} 68/push 0/imm32/address 68/push 0/imm32/alloc-id 89/copy 3/mod/direct 2/rm32/EDX . . . 4/r32/ESP . . # copy ESP to EDX - # . new(Heap, 2, h2) + # . new(heap, 2, h2) # . . push args 52/push-EDX 68/push 2/imm32/size - 68/push Heap/imm32 + 56/push-ESI # . . call e8/call new/disp32 # . . discard args @@ -338,10 +370,6 @@ test-lookup-failure: # clean up # . *Next-alloc-id = 1 c7 0/subop/copy 0/mod/indirect 5/rm32/.disp32 . . . Next-alloc-id/disp32 1/imm32 # copy to *Next-alloc-id - # . restore registers - 5a/pop-to-EDX - 59/pop-to-ECX - 58/pop-to-EAX # . epilog 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP 5d/pop-to-EBP diff --git a/subx/apps/hex b/subx/apps/hex index 8992e424..70734450 100755 Binary files a/subx/apps/hex and b/subx/apps/hex differ diff --git a/subx/apps/pack b/subx/apps/pack index 1da1a476..7e8cc761 100755 Binary files a/subx/apps/pack and b/subx/apps/pack differ -- cgit 1.4.1-2-gfad0