#8086 disassembler in (just a bit over) 2K of 8086 code and data
1 messages · Page 1 of 1 (latest)
nice
and i just spotted a bug, shl ax, cl should've been shl ax, 1 :^)
I've done something similar
and it took a bit more than 8 kiB
though it was a debugger with assembly/disassembly function
yeah i was at first thinking of making a whole debug.com clone
but i got bored, then decided to visit the disassembler part as it's own thing since i got the idea for the implementation
namely the decode table with the upper nibble representing the operation
but yeah, seems like you have a much better opcode table than I have
the only problem with it is that it imposes a limit that the offset is >4K (so it must be in it's own segment)
wait does it have to be in its own segment because the offset is >4K or the offset is >4K because it must be in its own segment?
if you were to put it in a larger program then you'd have to position it so all offsets within the disassembler opcode table are <4K
since the highest nibble determines the index into the subroutine pointer table
ah
my opcode table is a bit more bloated and it was probably a bad idea to embed the opcode strings in hindsight
i was thinking of making the opcode table a sparse array (is that the term?) by having a count byte before each entry
so for example all the push/pop reg16 would be encoded with 2 entries instead of 16
although idk if the savings in the big blocks would outweigh the decoding cost and all the one off opcodes being one byte longer
there's also a quirk with in imm8, al/ax, namely that it's represented as in al/ax, imm8
to save on a bit of space by reusing the operation for decoding mnemonic imm8
yeah, the special cases are kinda annoying
ended up with a lot of spaghetti code
though my lack of use of jump tables might also have contributed :^)
well embedding the string means you save 2 bytes for the pointer to the string
although the decoder becomes a bit bigger
well it happens a bit
8
push, >8pop, >8inc, >8decat least
and also the arithmetic and bit ops
and they're also common between GRP1/3/4 and the main opcodes
i have a bunch of redundant strings that include the register
adc_al_str: db "ADC AL,", 0
push_ss_str: db "PUSH SS", 0
sbb_al_str: db "SBB AL,", 0
push_ds_str: db "PUSH DS", 0
pop_ds_str: db "POP DS", 0
and_al_str: db "AND AL,", 0
oh
but the base ones only appear once
the ones with the registers in them are for encodings that use a fixed register
nice job qooke
reminds me of a project i stumbled upon a few days ago: https://github.com/revng/revng
revng: the core repository of the rev.ng project. Contribute to revng/revng development by creating an account on GitHub.
its a native binary translator, that can do x86->arm for example
but it solves the problem of writing an x86 parser, by just reusing the TCG parser in qemu
so it uses qemu to parse _ to TCG-IR, then converts TCG-IR to LLVM-IR, then LLVM-IR to _
so it can accept anything qemu supports as an input
and anything llvm supports as an output