This is interesting, though it might be a bit of a cheat. He's put some data in the BIOS image to assist in decoding instructions (not to take away from how amazing this is!): "CPU supports the full 8086/186 instruction set. Due to the complexities of the 8086’s arbitrary-length instruction decoding and flags, 8086 instructions are first converted to a simpler intermediate format before being executed. This conversio…
Abuse of the rules, if done well, is a time-honored IOCCC tradition.
An 8086 PC emulator in 4043 bytes
31–39 of 39 posts
Re: An 8086 PC emulator in 4043 bytes
#32Earlier quoted context omitted.
Abuse of the rules, if done well, is a time-honored IOCCC tradition.
It's not the only abuse of the rules. Looking at the hint, I think there's some flaw in the size-testing tool which they've exploited.
I/**/n
The code up to that point (2100 bytes total) is roughly as long as the listed output of the size tool (1979). The difference is probably due to the fact that I just counted raw bytes rather than accounting for whitespace and such. My guess, then, is that /* */ without a space hits a bug in the size tool where it probably counts that as the beginning of a comment but misses the end, causing it to count the entire remainder of the program as a comment. The compiler, meanwhile, will see that as an empty comment and continue reading code.This was a fairly predictable consequence of providing an official size tool. Used to be, they just laid out the rules for figuring out sizes, and you had to either count manually, or build your own tool to count. Now, bugs in the size tool end up being bugs in the rules, and fun like this ensues. Whether this is good or bad is a matter of opinion. I would say it certainly makes things interesting!
Edit: HN formatting makes the inline form of that comment look like a C++/C99-style // comment. Fun!
Re: An 8086 PC emulator in 4043 bytes
#33Earlier quoted context omitted.
It's not the only abuse of the rules. Looking at the hint, I think there's some flaw in the size-testing tool which they've exploited.
The hint mentions "the importance of comments". The only comment I can spot in the actual code is here (with a couple of characters of context): I/**/n The code up to that point (2100 bytes total) is roughly as long as the listed output of the size tool (1979). The difference is probably due to the fact that I just counted raw bytes rather than accounting for whitespace and such. My guess, then, is that /* */ without…
Re: An 8086 PC emulator in 4043 bytes
#34It's only complex and irregular if you look at it wrong. ;)
The x86 (like the 808{5,6} and the Z80) instructions look organised in an octal format: ftp://mipt.cc/Opcode.txt
I haven't inspected the code in any detail to see if it takes advantage of this.
Re: An 8086 PC emulator in 4043 bytes
#35Here's a link to a fully functional Windows binary (built with Visual Studio 2013): http://sdrv.ms/1hodqjP Just add the bios and image files elsewhere.
Missing MSVCR120D.dll. Can you compile in release mode or include that DLL too? Installing the Visual C++ Redistributable Packages for Visual Studio 2013 didn't help.
Re: An 8086 PC emulator in 4043 bytes
#36Earlier quoted context omitted.
Did you do this by hand? Line 38 looks weird: main(BX,nE)char nE; {
No, just passed through gcc -E which essentially preprocesses the file only (in this case in order to unpack all the defines) without fully compiling.
Re: An 8086 PC emulator in 4043 bytes
#37Re: An 8086 PC emulator in 4043 bytes
#38Has someone already unobfuscated the source code?
edit: P.S. working deobfuscation, i.e. you can build the executable. Including some minor corrections to the orgininal (e.g. 1MB of RAM allocation instead 2MB, BIOS file size limited to 65536-256 bytes, etc.). It a nice code, minimalistic, e.g. the "rep" prefixed instructions are actually repeated, not unrolled. Really optimized for code size. Even deobfuscated it takes 12-13KB and 22KB of executable (x86-64 Linux, stripped binary). Very cool.
Re: An 8086 PC emulator in 4043 bytes
#39Earlier quoted context omitted.
No, just passed through gcc -E which essentially preprocesses the file only (in this case in order to unpack all the defines) without fully compiling.
For those that don't know C, basically preprocessing (cpp, gcc -E, clang -E) is one of the first steps to occurs before the C compiler is invoked. It's easiest to think of the preprocessor as a templating language that can be used (or abused) to DRY up code and make it easier to maintain and customize. So the only thing that ever really gets compiled is the amalgamated processed .c files altered and configured by .h…