C as a portable assembly: porting RAEdit to 64-bit
In the Multiline Ultimate Assembler plugin for OllyDbg, I use an editor component called RAEdit, written by KetilO in 32-bit x86 assembly. It’s a great component, lightweight and simple to use.
Recently, I’ve been working on a port of Multiline Ultimate Assembler for the x64_dbg debugger. After porting the 32-bit version of the plugin, I realized that there’s a problem porting it to 64-bit: the RAEdit component is written in 32-bit x86 assembly. While it’s somewhat similar to 64-bit x86 assembly, there’s no way to automatically port an assembly codebase from 32-bit to 64-bit. I had a couple of options:
- Finding an alternative editor component.
- Using a hack, e.g. running the editor window as a separate 32-bit process.
- Porting RAEdit to 64-bit.
I looked for an alternative, but didn’t find a decent one. Also, I didn’t like the second option, so I’ve decided to port RAEdit. But how do I port an assembly codebase from 32-bit to 64-bit? I’m not familiar with MASM syntax, which the codebase uses. Perhaps it was possible to port the codebase to 64-bit MASM using macros and such. But I came up with a more creative idea: to port it to C first! After all, C is considered by some as a portable assembly.
The code uses MASM macros such as .if/.while extensively, which can be easily translated to C. Most assembly commands can be translated to C as well. I had to manually change some of the exotic stuff (such as usage of the CARRY flag), but most of the code was ready for automatic translation.
Then, I wrote a script which uses regular expression search/replace to translate every line of assembly to C. The initial result can be seen here. After some tweaking, I could get the code to compile. Due to the fact that there’s no type correctness in assembly, GCC displayed more than 1,000 warnings, most of which complain about incompatibility of types. I was actually surprised that it was able to compile.
Obviously, the code didn’t work right away. I had to fix a couple of things manually, but after some tweaking, it actually worked! And after some more tweaks for 64-bit portability (mainly adjusting pointer vs integer types and pointer size constants), the compiled 64-bit library worked as well!
It’s interesting to compare manually written assembly code with code generated by a compiler. Mostly, the original code is slimmer and looks more optimized. For example, assembly vs C of the SkipSpace function (clickable):
So there we have it, originally written in 32-bit x86 assembly, the library can now be (theoretically) compiled on every platform. It would be interesting to check whether it works on ARM/Windows RT, too. The main repository of the C port can be found here: https://github.com/m417z/RAEditC