VM translator generate x86 windows assembly

classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

VM translator generate x86 windows assembly

jacklack
While looking on how to generate windows executable from Jack source, I tried to understand how the PE executable format works.

Instead of going this route, I now go through a most logical and layered route, which is make the VM translator generate x86 win 32 asm code instead of hack code!
This is what I should have done instead of looking into PE stuff. As first you get an assembly file then you can use a windows assembler (there are many) to generate a windows executable.

I am doing this now, trying to get the vmtranslator generate masm style x86 win 32 assembler code.

In the process, it looks to be easier than generating hack....one of the reason is that x86 has a push and pop functions built in.

I am on it, and hopefully will get jack breakout working on a windows console.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: VM translator generate x86 windows assembly

jacklack
I made a new code generator that generates x86 code instead of Hack.

It turned out to be easier to implement than Hack, or maybe I found it easier because of the experience I already had with Hack...and the 8 register of the x86 help a lot too. (I wonder why there is only 8 registers, more would have been even more better ).

The os files need to be modified for use with the x86 windows platform. For example, the os file Memory need to allocate using windows libraries in assembly code.

I am planning to add an asm{ code } or similar style keyword that will tell the compiler to bypass the compilation of the block, and make the virtual machine just stick that block in the generated x86 code. If there is a better way to handle this issue, please tell me.

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: VM translator generate x86 windows assembly

cadet1620
Administrator
One thing that you might consider is writing your Jack OS classes in C (not C++).

C has a simple calling convention (cdecl [1]) that should be compatible with Jack.  Have your VM use something like "_ _ _" [2] instead of "." when generating identifier names in the ASM, and use the C calling convention for all calls generated by the VM.

Then your VM ASM can be directly linked to C.  Example Memory.alloc and deAllc would look something like
#include <stdint.h>
#include <stdlib.h>
#include "JackClass.h"

int16_t Memory___alloc(int16_t size)
{
    char * p;

    p = malloc(size);
    if ( ! p)
        Sys___error(6);     // does not return

    return allocJackPointer(p);
}

int16_t Memory___deAlloc(int16_t this)
{
    char * p;

    p = derefJackPointer(this);     // returns NULL if 'this' not in map
    free(p);
    removeJackPointer(this);

    return 0;
}
etcJackPointer functions would need to translate between 32-bit system memory pointers and 16-bit memory "handles" that the OS code would use to access system.

[Stream of conscience writing...]
How do you handle vm references to 'this' and 'that'? The pointer registers are only 16-bit so they can't hold a 32-bit system pointers, but accessing handle+offset is invalid.

Calling Memory___Peek and ___Poke for all this and that references could really slow things down.
Maybe Windows Jack should have all types be 32-bit. Then you wouldn't need to translate pointers <-> handles.

You might want to download the n2t source disto and look at the java in BuiltinVMClasses. They work similarly to the above.

--Mark

----------
[1] http://en.wikipedia.org/wiki/X86_calling_conventions#cdecl
[2] I don't know if any libraries the use 3 underscores in a row in identifier names.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: VM translator generate x86 windows assembly

jacklack
Hi Cadet, thanks for the suggestion;

It's one way to solve this issue...I'll take it into account.

As for the word size issue, the virtual machine is word agnostic, and that's what's great about the nandtotetris layered approach. I use 32 bits for this, that etc on the x86 win32.

For now, I changed the Memory.jack look like this:
class Memory
{

        static int s_HeapHandle;
        static int s_Variable;
       
    /** Initializes memory parameters. */
    function void init()
        {
                asm
                {
                        INVOKE GetProcessHeap ; get handle heap
                        mov Memory@0, eax     ; s_HeapHandle = 0
                }
       
                return;
    }

        /** finds and allocates from the heap a memory block of the
        *  specified size and returns a reference to its base address. */
    function int alloc(int size)
        {
                let s_Variable = size;
                asm
                {
                        push Memory@1 ; s_Variable
                        push 0
                        push Memory@0 ; s_HeapHandle
                       
                        call HeapAlloc
                       
                        mov  Memory@1, eax ;variable has pointer to allocated memory or null
                }
                return s_Variable;
    }
       
        /** De-allocates the given object and frees its space. */
    function void deAlloc(int objectAddress)
        {
                let s_Variable = objectAddress;
                asm
                {
                        push Memory@1 ; s_Variable
                        push 0
                        push Memory@0 ; s_HeapHandle
                       
                        call HeapFree
                }
               
                return;
    }  
}

One advantage of using the c code is that it will work as is  whether it's on windows or linux etc...
whereas the asm code calls are for windows in the example above...
cadet1620 wrote
One thing that you might consider is writing your Jack OS classes in C (not C++).

C has a simple calling convention (cdecl [1]) that should be compatible with Jack.  Have your VM use something like "_ _ _" [2] instead of "." when generating identifier names in the ASM, and use the C calling convention for all calls generated by the VM.

Then your VM ASM can be directly linked to C.  Example Memory.alloc and deAllc would look something like
#include <stdint.h>
#include <stdlib.h>
#include "JackClass.h"

int16_t Memory___alloc(int16_t size)
{
    char * p;

    p = malloc(size);
    if ( ! p)
        Sys___error(6);     // does not return

    return allocJackPointer(p);
}

int16_t Memory___deAlloc(int16_t this)
{
    char * p;

    p = derefJackPointer(this);     // returns NULL if 'this' not in map
    free(p);
    removeJackPointer(this);

    return 0;
}
etcJackPointer functions would need to translate between 32-bit system memory pointers and 16-bit memory "handles" that the OS code would use to access system.

[Stream of conscience writing...]
How do you handle vm references to 'this' and 'that'? The pointer registers are only 16-bit so they can't hold a 32-bit system pointers, but accessing handle+offset is invalid.

Calling Memory___Peek and ___Poke for all this and that references could really slow things down.
Maybe Windows Jack should have all types be 32-bit. Then you wouldn't need to translate pointers <-> handles.

You might want to download the n2t source disto and look at the java in BuiltinVMClasses. They work similarly to the above.

--Mark

----------
[1] http://en.wikipedia.org/wiki/X86_calling_conventions#cdecl
[2] I don't know if any libraries the use 3 underscores in a row in identifier names.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: VM translator generate x86 windows assembly

jacklack
In reply to this post by jacklack
I went for now with the embeded asm route, and it looks to be working fine.
I get programs executing on the windows machine in the same way as in the hack architecture.

Now is the problem of input/output, as I need a way to handle the keyboard and screen, In hack it's memory mapped, but in windows, there is no direct access to memory...

I've been looking at some solutions, I need to use a library for this (directx, or gdi or other). gdi seems to be the easiest so I'll try to get something out of it...
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: VM translator generate x86 windows assembly

jacklack
In reply to this post by jacklack
Have the gdi output part working (slow for now, for some reason).
I'll be doing the keyboard part next (but need to fix the slow gdi part first)
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: VM translator generate x86 windows assembly

jacklack
In reply to this post by jacklack
Output working fine now. Used gdi and double buffering this time for quicker graphics.
Here is a picture showing compiled pong game on windows:


Next now is the keyboard...
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: VM translator generate x86 windows assembly

jacklack
In reply to this post by jacklack
I got the keyboard part working.
I am looking now on how to write a debugger for it...
Loading...