Pure client-side combination of Nasm, DosBox and WebAssembly to show off yout x86 skills in a tweet (or more)
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
em-dosbox
nasm
tweetx86
build.sh
readme.md

readme.md

TweetX86

Pure client-side combination of Nasm, DosBox and WebAssembly to show off your x86 skills in a tweet (or more).
You can play with it here : http://twt86.co

What ?

Enter your x86 assembly code in the text area, or load one of the examples, and click the Run button.
When you assemble, the generated binary (a .COM file) is converted to base64 in the text box on the right.
You can use this base64 string in the URL (Snake example) :

http://twt86.co?c=swFoAKAHvqB9uBMAzRC/wPi5gAjzqqqBxz4Bc/jkYDxIchE8UHcNN5hISHIFLAJrwLCJwwHetIa2780VtEUmMCR72uvB

The max code size is limited by your browser capabilities (memory) and specifications (URL length).
But you can code far more than a tweet !

Technicalities

TweetX86 is based on :

Nasm, NDisasm and Em-Dosbox are basically treated as shell commands. Each of them is a C program with a main(int cargs, char *argvs[]), and seems to be stateful.
Therefore, to make them stateless, each command is in an IFrame. When TweetX86 needs to call a command, it simply create a DOM node with the corresponding IFrame :

function launchCommand(commandId, msg) {
    let p = new Promise((resolve, reject) => {
        let command = commands[commandId];
        if (command) {
            command.iframe.parentNode.removeChild(command.iframe);
        }
        command = commands[commandId] = {
            iframe: document.createElement('iframe'),
            msg,
            resolve,
            reject
        }
        command.iframe.src = `${commandId}.html`;
        command.iframe.name = commandId;
        document.getElementById(commandId).appendChild(command.iframe);
    })
    return p;
}

Nasm and NDisasm have been modified to be an Emscripten compliant WASM able to accept command line arguments :

let nasm = Module.cwrap('nasm', 'number', ['string']);
let now = new Date();
let asmFileName = `/asm${now.getTime()}.asm`;
let comFileName = `/asm${now.getTime()}.com`;
let cmdLine = `-fbin ${asmFileName} -o${comFileName}`;
let retVal = nasm(cmdLine);

Build

First, install Emscripten.

Then build Nasm and NDisasm :

cd nasm
make clean
emconfigure ./configure
emmake make
mv nasm nasm.bc
mv ndisasm ndisasm.bc
emcc nasm.bc -s WASM=1 -o nasm.js -s NO_EXIT_RUNTIME=0 -s 'EXTRA_EXPORTED_RUNTIME_METHODS=["cwrap"]'
emcc ndisasm.bc -s WASM=1 -o ndisasm.js -s NO_EXIT_RUNTIME=0 -s 'EXTRA_EXPORTED_RUNTIME_METHODS=["cwrap"]'
cp ./nasm.wasm ../tweetx86
cp ./nasm.js ../tweetx86
cp ./ndisasm.wasm ../tweetx86
cp ./ndisasm.js ../tweetx86

Build Em-Dosbox :

cd em-dosbox
./autogen.sh
emconfigure ./configure
make
cp src/dosbox.js ../tweetx86
cp src/dosbox.html.mem ../tweetx86

Build and launch TweetX86 :

cd tweetx86
npm install
npm start