From 6f6d458fcd619810d657fe3e1b82b4d1970dc2df Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Mon, 13 May 2019 17:27:45 -0700 Subject: start using the new carry flag Skimping on tests; the code changes seem pretty trivial. Will this fix CI?! --- subx/012elf.cc | 23 ++++++++--------- subx/013direct_addressing.cc | 14 +++++------ subx/014indirect_addressing.cc | 23 ++++++++--------- subx/015immediate_addressing.cc | 6 ++--- subx/017jump_disp8.cc | 54 +++++++++++++++++++++++++++++++++------- subx/019functions.cc | 22 ++++++++-------- subx/031check_operands.cc | 4 +++ subx/040---tests.cc | 4 +-- subx/057write.subx | 2 +- subx/060read.subx | 2 +- subx/062write-stream.subx | 2 +- subx/apps/assort | Bin 21809 -> 21809 bytes subx/apps/crenshaw2-1 | Bin 18968 -> 18968 bytes subx/apps/crenshaw2-1b | Bin 19527 -> 19527 bytes subx/apps/factorial | Bin 17884 -> 17884 bytes subx/apps/handle | Bin 18711 -> 18711 bytes subx/apps/hex | Bin 21977 -> 21977 bytes subx/apps/pack | Bin 36569 -> 36569 bytes 18 files changed, 96 insertions(+), 60 deletions(-) (limited to 'subx') diff --git a/subx/012elf.cc b/subx/012elf.cc index 0fa9d793..0ae0b108 100644 --- a/subx/012elf.cc +++ b/subx/012elf.cc @@ -141,20 +141,17 @@ 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: 0x7dffffff -> 0x7d000000 (downward; not in ELF binary) -// argv hack: 0x7f000000 -> 0x7fffffff (not in ELF binary) +// stack: 0xbdffffff -> 0xbd000000 (downward; not in ELF binary) +// argv hack: 0xbf000000 -> 0xbfffffff (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 START_HEAP = 0x0b000000; -const int END_HEAP = 0x7d000000; -const int STACK_SEGMENT = 0x7d000000; -const int AFTER_STACK = 0x7e000000; -const int ARGV_DATA_SEGMENT = 0x7f000000; +// Addresses above 0xc0000000 are reserved for the Linux kernel. +const uint32_t CODE_SEGMENT = 0x09000000; +const uint32_t DATA_SEGMENT = 0x0a000000; +const uint32_t START_HEAP = 0x0b000000; +const uint32_t END_HEAP = 0xbd000000; +const uint32_t STACK_SEGMENT = 0xbd000000; +const uint32_t AFTER_STACK = 0xbe000000; +const uint32_t ARGV_DATA_SEGMENT = 0xbf000000; // When updating the above memory map, don't forget to update `mmap`'s // implementation in the 'syscalls' layer. :(before "End Dump Info for Instruction") diff --git a/subx/013direct_addressing.cc b/subx/013direct_addressing.cc index a2331213..2914e0dd 100644 --- a/subx/013direct_addressing.cc +++ b/subx/013direct_addressing.cc @@ -1183,8 +1183,8 @@ put_new(Name, "57", "push EDI to stack (push)"); :(code) void test_push_r32() { - Mem.push_back(vma(0x7d000000)); // manually allocate memory - Reg[ESP].u = 0x7d000008; + Mem.push_back(vma(0xbd000000)); // manually allocate memory + Reg[ESP].u = 0xbd000008; Reg[EBX].i = 0x0000000a; run( "== 0x1\n" // code segment @@ -1193,7 +1193,7 @@ void test_push_r32() { ); CHECK_TRACE_CONTENTS( "run: push EBX\n" - "run: decrementing ESP to 0x7d000004\n" + "run: decrementing ESP to 0xbd000004\n" "run: pushing value 0x0000000a\n" ); } @@ -1228,9 +1228,9 @@ put_new(Name, "5f", "pop top of stack to EDI (pop)"); :(code) void test_pop_r32() { - Mem.push_back(vma(0x7d000000)); // manually allocate memory - Reg[ESP].u = 0x7d000008; - write_mem_i32(0x7d000008, 0x0000000a); // ..before this write + Mem.push_back(vma(0xbd000000)); // manually allocate memory + Reg[ESP].u = 0xbd000008; + write_mem_i32(0xbd000008, 0x0000000a); // ..before this write run( "== 0x1\n" // code segment // op ModR/M SIB displacement immediate @@ -1241,7 +1241,7 @@ void test_pop_r32() { CHECK_TRACE_CONTENTS( "run: pop into EBX\n" "run: popping value 0x0000000a\n" - "run: incrementing ESP to 0x7d00000c\n" + "run: incrementing ESP to 0xbd00000c\n" ); } diff --git a/subx/014indirect_addressing.cc b/subx/014indirect_addressing.cc index e89a9986..a281921f 100644 --- a/subx/014indirect_addressing.cc +++ b/subx/014indirect_addressing.cc @@ -561,7 +561,6 @@ case 0x3b: { // set SF if r32 < r/m32 const uint8_t modrm = next(); const uint8_t reg1 = (modrm>>3)&0x7; trace(Callstack_depth+1, "run") << "compare " << rname(reg1) << " with r/m32" << end(); - const int32_t signed_arg1 = Reg[reg1].i; const int32_t* signed_arg2 = effective_address(modrm); const int32_t signed_difference = Reg[reg1].i - *signed_arg2; SF = (signed_difference < 0); @@ -732,8 +731,8 @@ void test_jump_mem_at_r32() { // op ModR/M SIB displacement immediate " ff 20 \n" // jump to *EAX // ModR/M in binary: 00 (indirect mode) 100 (jump to r/m32) 000 (src EAX) - " 05 00 00 00 01\n" - " 05 00 00 00 02\n" + " b8 00 00 00 01\n" + " b8 00 00 00 02\n" "== 0x2000\n" // data segment "08 00 00 00\n" // 0x00000008 ); @@ -742,9 +741,9 @@ void test_jump_mem_at_r32() { "run: jump to r/m32\n" "run: effective address is 0x00002000 (EAX)\n" "run: jumping to 0x00000008\n" - "run: 0x00000008 opcode: 05\n" + "run: 0x00000008 opcode: b8\n" ); - CHECK_TRACE_DOESNT_CONTAIN("run: 0x00000003 opcode: 05"); + CHECK_TRACE_DOESNT_CONTAIN("run: 0x00000003 opcode: b8"); } :(before "End Op ff Subops") @@ -761,8 +760,8 @@ case 4: { // jump to r/m32 :(code) void test_push_mem_at_r32() { Reg[EAX].i = 0x2000; - Mem.push_back(vma(0x7d000000)); // manually allocate memory - Reg[ESP].u = 0x7d000014; + Mem.push_back(vma(0xbd000000)); // manually allocate memory + Reg[ESP].u = 0xbd000014; run( "== 0x1\n" // code segment // op ModR/M SIB displacement immediate @@ -773,7 +772,7 @@ void test_push_mem_at_r32() { CHECK_TRACE_CONTENTS( "run: push r/m32\n" "run: effective address is 0x00002000 (EAX)\n" - "run: decrementing ESP to 0x7d000010\n" + "run: decrementing ESP to 0xbd000010\n" "run: pushing value 0x000000af\n" ); } @@ -794,9 +793,9 @@ put_new(Name, "8f", "pop top of stack to rm32 (pop)"); :(code) void test_pop_mem_at_r32() { Reg[EAX].i = 0x60; - Mem.push_back(vma(0x7d000000)); // manually allocate memory - Reg[ESP].u = 0x7d000000; - write_mem_i32(0x7d000000, 0x00000030); + Mem.push_back(vma(0xbd000000)); // manually allocate memory + Reg[ESP].u = 0xbd000000; + write_mem_i32(0xbd000000, 0x00000030); run( "== 0x1\n" // code segment // op ModR/M SIB displacement immediate @@ -807,7 +806,7 @@ void test_pop_mem_at_r32() { "run: pop into r/m32\n" "run: effective address is 0x00000060 (EAX)\n" "run: popping value 0x00000030\n" - "run: incrementing ESP to 0x7d000004\n" + "run: incrementing ESP to 0xbd000004\n" ); } diff --git a/subx/015immediate_addressing.cc b/subx/015immediate_addressing.cc index 6bf394df..4210c024 100644 --- a/subx/015immediate_addressing.cc +++ b/subx/015immediate_addressing.cc @@ -1191,8 +1191,8 @@ put_new(Name, "68", "push imm32 to stack (push)"); :(code) void test_push_imm32() { - Mem.push_back(vma(0x7d000000)); // manually allocate memory - Reg[ESP].u = 0x7d000014; + Mem.push_back(vma(0xbd000000)); // manually allocate memory + Reg[ESP].u = 0xbd000014; run( "== 0x1\n" // code segment // op ModR/M SIB displacement immediate @@ -1200,7 +1200,7 @@ void test_push_imm32() { ); CHECK_TRACE_CONTENTS( "run: push imm32 0x000000af\n" - "run: ESP is now 0x7d000010\n" + "run: ESP is now 0xbd000010\n" "run: contents at ESP: 0x000000af\n" ); } diff --git a/subx/017jump_disp8.cc b/subx/017jump_disp8.cc index 22ae6567..35cc1331 100644 --- a/subx/017jump_disp8.cc +++ b/subx/017jump_disp8.cc @@ -135,7 +135,8 @@ void test_jne_rel8_fail() { //:: jump if greater :(before "End Initialize Op Names") -put_new(Name, "7f", "jump disp8 bytes away if greater, if ZF is unset and SF == OF (jcc/jg/jnle)"); +put_new(Name, "7f", "jump disp8 bytes away if greater (signed), if ZF is unset and SF == OF (jcc/jg/jnle)"); +put_new(Name, "77", "jump disp8 bytes away if greater (unsigned), if ZF is unset and CF is unset (jcc/ja/jnbe)"); :(code) void test_jg_rel8_success() { @@ -158,9 +159,17 @@ void test_jg_rel8_success() { } :(before "End Single-Byte Opcodes") -case 0x7f: { // jump rel8 if !SF and !ZF +case 0x7f: { // jump rel8 if SF == OF and !ZF const int8_t offset = static_cast(next()); - if (!ZF && SF == OF) { + if (SF == OF && !ZF) { + trace(Callstack_depth+1, "run") << "jump " << NUM(offset) << end(); + EIP += offset; + } + break; +} +case 0x77: { // jump rel8 if !CF and !ZF + const int8_t offset = static_cast(next()); + if (!CF && !ZF) { trace(Callstack_depth+1, "run") << "jump " << NUM(offset) << end(); EIP += offset; } @@ -190,7 +199,8 @@ void test_jg_rel8_fail() { //:: jump if greater or equal :(before "End Initialize Op Names") -put_new(Name, "7d", "jump disp8 bytes away if greater or equal, if SF == OF (jcc/jge/jnl)"); +put_new(Name, "7d", "jump disp8 bytes away if greater or equal (signed), if SF == OF (jcc/jge/jnl)"); +put_new(Name, "73", "jump disp8 bytes away if greater or equal (unsigned), if CF is unset (jcc/jae/jnb)"); :(code) void test_jge_rel8_success() { @@ -212,7 +222,7 @@ void test_jge_rel8_success() { } :(before "End Single-Byte Opcodes") -case 0x7d: { // jump rel8 if !SF +case 0x7d: { // jump rel8 if SF == OF const int8_t offset = static_cast(next()); if (SF == OF) { trace(Callstack_depth+1, "run") << "jump " << NUM(offset) << end(); @@ -220,6 +230,14 @@ case 0x7d: { // jump rel8 if !SF } break; } +case 0x73: { // jump rel8 if !CF + const int8_t offset = static_cast(next()); + if (!CF) { + trace(Callstack_depth+1, "run") << "jump " << NUM(offset) << end(); + EIP += offset; + } + break; +} :(code) void test_jge_rel8_fail() { @@ -243,7 +261,8 @@ void test_jge_rel8_fail() { //:: jump if lesser :(before "End Initialize Op Names") -put_new(Name, "7c", "jump disp8 bytes away if lesser, if SF != OF (jcc/jl/jnge)"); +put_new(Name, "7c", "jump disp8 bytes away if lesser (signed), if SF != OF (jcc/jl/jnge)"); +put_new(Name, "72", "jump disp8 bytes away if lesser (unsigned), if CF is set (jcc/jb/jnae)"); :(code) void test_jl_rel8_success() { @@ -266,7 +285,7 @@ void test_jl_rel8_success() { } :(before "End Single-Byte Opcodes") -case 0x7c: { // jump rel8 if SF and !ZF +case 0x7c: { // jump rel8 if SF != OF const int8_t offset = static_cast(next()); if (SF != OF) { trace(Callstack_depth+1, "run") << "jump " << NUM(offset) << end(); @@ -274,6 +293,14 @@ case 0x7c: { // jump rel8 if SF and !ZF } break; } +case 0x72: { // jump rel8 if CF + const int8_t offset = static_cast(next()); + if (CF) { + trace(Callstack_depth+1, "run") << "jump " << NUM(offset) << end(); + EIP += offset; + } + break; +} :(code) void test_jl_rel8_fail() { @@ -298,7 +325,8 @@ void test_jl_rel8_fail() { //:: jump if lesser or equal :(before "End Initialize Op Names") -put_new(Name, "7e", "jump disp8 bytes away if lesser or equal, if ZF is set or SF != OF (jcc/jle/jng)"); +put_new(Name, "7e", "jump disp8 bytes away if lesser or equal (signed), if ZF is set or SF != OF (jcc/jle/jng)"); +put_new(Name, "76", "jump disp8 bytes away if lesser or equal (unsigned), if ZF is set or CF is set (jcc/jbe/jna)"); :(code) void test_jle_rel8_equal() { @@ -341,7 +369,7 @@ void test_jle_rel8_lesser() { } :(before "End Single-Byte Opcodes") -case 0x7e: { // jump rel8 if SF or ZF +case 0x7e: { // jump rel8 if ZF or SF != OF const int8_t offset = static_cast(next()); if (ZF || SF != OF) { trace(Callstack_depth+1, "run") << "jump " << NUM(offset) << end(); @@ -349,6 +377,14 @@ case 0x7e: { // jump rel8 if SF or ZF } break; } +case 0x76: { // jump rel8 if ZF or CF + const int8_t offset = static_cast(next()); + if (ZF || CF) { + trace(Callstack_depth+1, "run") << "jump " << NUM(offset) << end(); + EIP += offset; + } + break; +} :(code) void test_jle_rel8_greater() { diff --git a/subx/019functions.cc b/subx/019functions.cc index 27fb4fb0..00da8397 100644 --- a/subx/019functions.cc +++ b/subx/019functions.cc @@ -5,8 +5,8 @@ put_new(Name, "e8", "call disp32 (call)"); :(code) void test_call_disp32() { - Mem.push_back(vma(0x7d000000)); // manually allocate memory - Reg[ESP].u = 0x7d000064; + Mem.push_back(vma(0xbd000000)); // manually allocate memory + Reg[ESP].u = 0xbd000064; run( "== 0x1\n" // code segment // op ModR/M SIB displacement immediate @@ -15,7 +15,7 @@ void test_call_disp32() { ); CHECK_TRACE_CONTENTS( "run: call imm32 0x000000a0\n" - "run: decrementing ESP to 0x7d000060\n" + "run: decrementing ESP to 0xbd000060\n" "run: pushing value 0x00000006\n" "run: jumping to 0x000000a6\n" ); @@ -37,8 +37,8 @@ case 0xe8: { // call disp32 relative to next EIP :(code) void test_call_r32() { - Mem.push_back(vma(0x7d000000)); // manually allocate memory - Reg[ESP].u = 0x7d000064; + Mem.push_back(vma(0xbd000000)); // manually allocate memory + Reg[ESP].u = 0xbd000064; Reg[EBX].u = 0x000000a0; run( "== 0x1\n" // code segment @@ -49,7 +49,7 @@ void test_call_r32() { CHECK_TRACE_CONTENTS( "run: call to r/m32\n" "run: r/m32 is EBX\n" - "run: decrementing ESP to 0x7d000060\n" + "run: decrementing ESP to 0xbd000060\n" "run: pushing value 0x00000003\n" "run: jumping to 0x000000a3\n" ); @@ -68,8 +68,8 @@ case 2: { // call function pointer at r/m32 :(code) void test_call_mem_at_r32() { - Mem.push_back(vma(0x7d000000)); // manually allocate memory - Reg[ESP].u = 0x7d000064; + Mem.push_back(vma(0xbd000000)); // manually allocate memory + Reg[ESP].u = 0xbd000064; Reg[EBX].u = 0x2000; run( "== 0x1\n" // code segment @@ -82,7 +82,7 @@ void test_call_mem_at_r32() { CHECK_TRACE_CONTENTS( "run: call to r/m32\n" "run: effective address is 0x00002000 (EBX)\n" - "run: decrementing ESP to 0x7d000060\n" + "run: decrementing ESP to 0xbd000060\n" "run: pushing value 0x00000003\n" "run: jumping to 0x000000a3\n" ); @@ -95,8 +95,8 @@ put_new(Name, "c3", "return from most recent unfinished call (ret)"); :(code) void test_ret() { - Mem.push_back(vma(0x7d000000)); // manually allocate memory - Reg[ESP].u = 0x7d000064; + Mem.push_back(vma(0xbd000000)); // manually allocate memory + Reg[ESP].u = 0xbd000064; write_mem_u32(Reg[ESP].u, 0x10); run( "== 0x1\n" // code segment diff --git a/subx/031check_operands.cc b/subx/031check_operands.cc index 9590979f..aad84da6 100644 --- a/subx/031check_operands.cc +++ b/subx/031check_operands.cc @@ -152,8 +152,12 @@ void init_permitted_operands() { // jump put(Permitted_operands, "eb", 0x04); + put(Permitted_operands, "72", 0x04); + put(Permitted_operands, "73", 0x04); put(Permitted_operands, "74", 0x04); put(Permitted_operands, "75", 0x04); + put(Permitted_operands, "76", 0x04); + put(Permitted_operands, "77", 0x04); put(Permitted_operands, "7c", 0x04); put(Permitted_operands, "7d", 0x04); put(Permitted_operands, "7e", 0x04); diff --git a/subx/040---tests.cc b/subx/040---tests.cc index 237bb811..e5949bbd 100644 --- a/subx/040---tests.cc +++ b/subx/040---tests.cc @@ -16,8 +16,8 @@ Transform.push_back(create_test_function); :(code) void test_run_test() { - Mem.push_back(vma(0x7d000000)); // manually allocate memory - Reg[ESP].u = 0x7d000100; + Mem.push_back(vma(0xbd000000)); // manually allocate memory + Reg[ESP].u = 0xbd000100; run( "== 0x1\n" // code segment "main:\n" diff --git a/subx/057write.subx b/subx/057write.subx index 3135003b..455146ac 100644 --- a/subx/057write.subx +++ b/subx/057write.subx @@ -27,7 +27,7 @@ write: # f : fd or (address stream), s : (address array byte) -> 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP # if (f < 0x08000000) _write(f, s) and return # f can't be a user-mode address, so treat it as a kernel file descriptor 81 7/subop/compare 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 0x08000000/imm32 # compare *(EBP+8) - 7d/jump-if-greater-or-equal $write:fake/disp8 + 73/jump-if-greater-unsigned-or-equal $write:fake/disp8 # . . push args ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) diff --git a/subx/060read.subx b/subx/060read.subx index cedafbf5..d377a1ad 100644 --- a/subx/060read.subx +++ b/subx/060read.subx @@ -51,7 +51,7 @@ read: # f : fd or (address stream), s : (address stream) -> num-bytes-read/EAX 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP # if (f < 0x08000000) return _read(f, s) # f can't be a user-mode address, so treat it as a kernel file descriptor 81 7/subop/compare 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 0x08000000/imm32 # compare *(EBP+8) - 7d/jump-if-greater-or-equal $read:fake/disp8 + 73/jump-if-greater-unsigned-or-equal $read:fake/disp8 # . . push args ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) diff --git a/subx/062write-stream.subx b/subx/062write-stream.subx index 83268422..92c67dc2 100644 --- a/subx/062write-stream.subx +++ b/subx/062write-stream.subx @@ -21,7 +21,7 @@ write-stream: # f : fd or (address stream), s : (address stream) -> 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP # if (f < 0x08000000) _write-stream(f, s), return # f can't be a user-mode address, so treat it as a kernel file descriptor 81 7/subop/compare 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 0x08000000/imm32 # compare *(EBP+8) - 7d/jump-if-greater-or-equal $write-stream:fake/disp8 + 73/jump-if-greater-unsigned-or-equal $write-stream:fake/disp8 # . . push args ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) diff --git a/subx/apps/assort b/subx/apps/assort index 3fbc3b7e..d2aaaf1a 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 ca1e52fa..3fbc9c33 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 8a468ff5..71265ffe 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 9ea9716b..4f5f7dc2 100755 Binary files a/subx/apps/factorial and b/subx/apps/factorial differ diff --git a/subx/apps/handle b/subx/apps/handle index b32183db..520ca276 100755 Binary files a/subx/apps/handle and b/subx/apps/handle differ diff --git a/subx/apps/hex b/subx/apps/hex index ed1d9eeb..667fbc1f 100755 Binary files a/subx/apps/hex and b/subx/apps/hex differ diff --git a/subx/apps/pack b/subx/apps/pack index a4a20626..2b313f08 100755 Binary files a/subx/apps/pack and b/subx/apps/pack differ -- cgit 1.4.1-2-gfad0