7 ms·
It warms my heart to see such a brilliant hack. It's especially impressive that this doesn't use any external tools like sed. If you scroll to the bottom, you
by s_tec 12y ago
It warms my heart to see such a brilliant hack. It's especially impressive that this doesn't use any external tools like sed.
If you scroll to the bottom, you can see how it works. Each x86 instruction is actually a shell function, and the input to the the assembler is itself a shell script. Each line of the input script basically tells the assembler which bytes to output. There is some fun stuff for dealing with variable-length x86 jump instructions, but otherwise that's the basic idea.
The new Mill CPU architecture actually uses a similar idea in their assembler. Each of their instructions is a C++ function. To assemble Mill software, the first step is to run the "assembly language" through a C++ compiler. The resulting program emits the appropriate Mill machine code when it runs. This is an interesting approach, since it turns the assembler into a reusable piece of software.
Another side-benefit of this technique is that it gives the assembler a super-powerful macro language. In this case, the macro language is basically bash shell. So you want to emit 100 add instructions? Just put the instructions inside a bash `for` loop!
- illumen 12y agoI worked on a runtime assembler based on C++ that worked like this. The nice thing is you could dynamically generate code from C++. Which made hardware shader languages run at an acceptable speed on CPUs. Because rather than have branches in your code to support thousands of possible combinations of inputs, you would generate the exact code needed for that data and function. Strangely I still sometimes use some of these assembler techniques in JavaScript to great effect. Want to loop faster? Use something like duffs device. Have lots of ifs/elses in a loop? Parse it out, and make specific code for the inputs at runtime. Not often, but sometimes it's been helpful to improve things.
- fit2rule 12y agoWarms my heart too, but what interests me most about this story is that I recall assemblers being written this way as a sort of a standard technique in the 70's and 80's, and it seems to have been a lost art, now recovered (or, at least in 2001) .. I remember some Tandem (or perhaps Wang?) machines used the shell to emit assembly instructions, and in the days of MIPS as a hardware manufacturer (RISCOS pizzabox) there were such assemblers, very rudimentary, for the boot console, so you could emit code to start the machines .. {Hmm .. what is the term for this, it occurs so often I'm sure there must be a description of it, where new, old stuff becomes new and interesting again?}
- vidarh 12y ago> and in the days of MIPS as a hardware manufacturer (RISCOS pizzabox) I was very confused there for a moment - I'd never heard of RISC OS pizza box in any other context than the Acorn / ARM machines. In case anyone else is similarly confused: This is RISC/os the Unix for MIPS based systems.
- fit2rule 12y agoRight, sorry for the confusion, and thanks for clearing that up.
- mattgodbolt 12y agoJavaScript emulators also use this internal code generator approach. For example the jsbeeb 6502 emulator code is generated from the opcodes text and then 'eval'ed to yield the actual code to run for each instruction. See http://xania.org/201405/jsbeeb-getting-the-timings-right-CPU http://xania.org/201405/jsbeeb-getting-the-timings-right-CPU towards the end.
- mzs 12y agoMaybe you mean rom monitor?