diff options
author | Kartik Agaram <vc@akkartik.com> | 2019-03-12 18:56:55 -0700 |
---|---|---|
committer | Kartik Agaram <vc@akkartik.com> | 2019-03-12 19:14:12 -0700 |
commit | 4a943d4ed313eff001504c2b5c472266e86a38af (patch) | |
tree | a5757233a8c81b303a808f251180c7344071ed51 /subx/021byte_addressing.cc | |
parent | 43711b0e9f18e0225ce14687fb6ea0902aa6fc61 (diff) | |
download | mu-4a943d4ed313eff001504c2b5c472266e86a38af.tar.gz |
5001 - drop the :(scenario) DSL
I've been saying for a while[1][2][3] that adding extra abstractions makes things harder for newcomers, and adding new notations doubly so. And then I notice this DSL in my own backyard. Makes me feel like a hypocrite. [1] https://news.ycombinator.com/item?id=13565743#13570092 [2] https://lobste.rs/s/to8wpr/configuration_files_are_canary_warning [3] https://lobste.rs/s/mdmcdi/little_languages_by_jon_bentley_1986#c_3miuf2 The implementation of the DSL was also highly hacky: a) It was happening in the tangle/ tool, but was utterly unrelated to tangling layers. b) There were several persnickety constraints on the different kinds of lines and the specific order they were expected in. I kept finding bugs where the translator would silently do the wrong thing. Or the error messages sucked, and readers may be stuck looking at the generated code to figure out what happened. Fixing error messages would require a lot more code, which is one of my arguments against DSLs in the first place: they may be easy to implement, but they're hard to design to go with the grain of the underlying platform. They require lots of iteration. Is that effort worth prioritizing in this project? On the other hand, the DSL did make at least some readers' life easier, the ones who weren't immediately put off by having to learn a strange syntax. There were fewer quotes to parse, fewer backslash escapes. Anyway, since there are also people who dislike having to put up with strange syntaxes, we'll call that consideration a wash and tear this DSL out. --- This commit was sheer drudgery. Hopefully it won't need to be redone with a new DSL because I grow sick of backslashes.
Diffstat (limited to 'subx/021byte_addressing.cc')
-rw-r--r-- | subx/021byte_addressing.cc | 126 |
1 files changed, 75 insertions, 51 deletions
diff --git a/subx/021byte_addressing.cc b/subx/021byte_addressing.cc index c96bc9c1..106cd426 100644 --- a/subx/021byte_addressing.cc +++ b/subx/021byte_addressing.cc @@ -40,19 +40,25 @@ uint8_t* reg_8bit(uint8_t rm) { :(before "End Initialize Op Names") put_new(Name, "88", "copy r8 to r8/m8-at-r32"); -:(scenario copy_r8_to_mem_at_r32) -% Reg[EBX].i = 0x224488ab; -% Reg[EAX].i = 0x2000; -== 0x1 -# op ModR/M SIB displacement immediate - 88 18 # copy BL to the byte at *EAX -# ModR/M in binary: 00 (indirect mode) 011 (src BL) 000 (dest EAX) -== 0x2000 -f0 cc bb aa -+run: copy BL to r8/m8-at-r32 -+run: effective address is 0x00002000 (EAX) -+run: storing 0xab -% CHECK_EQ(0xaabbccab, read_mem_u32(0x2000)); +:(code) +void test_copy_r8_to_mem_at_r32() { + Reg[EBX].i = 0x224488ab; + Reg[EAX].i = 0x2000; + run( + "== 0x1\n" // code segment + // op ModR/M SIB displacement immediate + " 88 18 \n" // copy BL to the byte at *EAX + // ModR/M in binary: 00 (indirect mode) 011 (src BL) 000 (dest EAX) + "== 0x2000\n" // data segment + "f0 cc bb aa\n" + ); + CHECK_TRACE_CONTENTS( + "run: copy BL to r8/m8-at-r32\n" + "run: effective address is 0x00002000 (EAX)\n" + "run: storing 0xab\n" + ); + CHECK_EQ(0xaabbccab, read_mem_u32(0x2000)); +} :(before "End Single-Byte Opcodes") case 0x88: { // copy r8 to r/m8 @@ -72,20 +78,26 @@ case 0x88: { // copy r8 to r/m8 :(before "End Initialize Op Names") put_new(Name, "8a", "copy r8/m8-at-r32 to r8"); -:(scenario copy_mem_at_r32_to_r8) -% Reg[EBX].i = 0xaabbcc0f; // one nibble each of lowest byte set to all 0s and all 1s, to maximize value of this test -% Reg[EAX].i = 0x2000; -== 0x1 -# op ModR/M SIB displacement immediate - 8a 18 # copy just the byte at *EAX to BL -# ModR/M in binary: 00 (indirect mode) 011 (dest EBX) 000 (src EAX) -== 0x2000 # data segment -ab ff ff ff # 0xab with more data in following bytes -+run: copy r8/m8-at-r32 to BL -+run: effective address is 0x00002000 (EAX) -+run: storing 0xab -# remaining bytes of EBX are *not* cleared -+run: EBX now contains 0xaabbccab +:(code) +void test_copy_mem_at_r32_to_r8() { + Reg[EBX].i = 0xaabbcc0f; // one nibble each of lowest byte set to all 0s and all 1s, to maximize value of this test + Reg[EAX].i = 0x2000; + run( + "== 0x1\n" // code segment + // op ModR/M SIB displacement immediate + " 8a 18 \n" // copy just the byte at *EAX to BL + // ModR/M in binary: 00 (indirect mode) 011 (dest EBX) 000 (src EAX) + "== 0x2000\n" // data segment + "ab ff ff ff\n" // 0xab with more data in following bytes + ); + CHECK_TRACE_CONTENTS( + "run: copy r8/m8-at-r32 to BL\n" + "run: effective address is 0x00002000 (EAX)\n" + "run: storing 0xab\n" + // remaining bytes of EBX are *not* cleared + "run: EBX now contains 0xaabbccab\n" + ); +} :(before "End Single-Byte Opcodes") case 0x8a: { // copy r/m8 to r8 @@ -102,36 +114,48 @@ case 0x8a: { // copy r/m8 to r8 break; } -:(scenario cannot_copy_byte_to_ESP_EBP_ESI_EDI) -% Reg[ESI].u = 0xaabbccdd; -% Reg[EBX].u = 0x11223344; -== 0x1 -# op ModR/M SIB displacement immediate - 8a f3 # copy just the byte at *EBX to 8-bit register '6' -# ModR/M in binary: 11 (direct mode) 110 (dest 8-bit 'register 6') 011 (src EBX) -# ensure 8-bit register '6' is DH, not ESI -+run: copy r8/m8-at-r32 to DH -+run: storing 0x44 -# ensure ESI is unchanged -% CHECK_EQ(Reg[ESI].u, 0xaabbccdd); +:(code) +void test_cannot_copy_byte_to_ESP_EBP_ESI_EDI() { + Reg[ESI].u = 0xaabbccdd; + Reg[EBX].u = 0x11223344; + run( + "== 0x1\n" // code segment + // op ModR/M SIB displacement immediate + " 8a f3 \n" // copy just the byte at *EBX to 8-bit register '6' + // ModR/M in binary: 11 (direct mode) 110 (dest 8-bit 'register 6') 011 (src EBX) + ); + CHECK_TRACE_CONTENTS( + // ensure 8-bit register '6' is DH, not ESI + "run: copy r8/m8-at-r32 to DH\n" + "run: storing 0x44\n" + ); + // ensure ESI is unchanged + CHECK_EQ(Reg[ESI].u, 0xaabbccdd); +} //: :(before "End Initialize Op Names") put_new(Name, "c6", "copy imm8 to r8/m8-at-r32 (mov)"); -:(scenario copy_imm8_to_mem_at_r32) -% Reg[EAX].i = 0x2000; -== 0x1 -# op ModR/M SIB displacement immediate - c6 00 dd # copy to the byte at *EAX -# ModR/M in binary: 00 (indirect mode) 000 (unused) 000 (dest EAX) -== 0x2000 -f0 cc bb aa -+run: copy imm8 to r8/m8-at-r32 -+run: effective address is 0x00002000 (EAX) -+run: storing 0xdd -% CHECK_EQ(0xaabbccdd, read_mem_u32(0x2000)); +:(code) +void test_copy_imm8_to_mem_at_r32() { + Reg[EAX].i = 0x2000; + run( + "== 0x1\n" // code segment + // op ModR/M SIB displacement immediate + " c6 00 dd \n" // copy to the byte at *EAX + // ModR/M in binary: 00 (indirect mode) 000 (unused) 000 (dest EAX) + "== 0x2000\n" // data segment + "f0 cc bb aa\n" + ); + CHECK_TRACE_CONTENTS( + "run: copy imm8 to r8/m8-at-r32\n" + "run: effective address is 0x00002000 (EAX)\n" + "run: storing 0xdd\n" + ); + CHECK_EQ(0xaabbccdd, read_mem_u32(0x2000)); +} :(before "End Single-Byte Opcodes") case 0xc6: { // copy imm8 to r/m8 |