Click here to Skip to main content
15,867,568 members
Articles / Programming Languages / Javascript

JavaScript Assembler Language Specification (JS-ASM)

Rate me:
Please Sign up or sign in to vote.
5.00/5 (10 votes)
20 Jul 2012CPOL8 min read 38.8K   478   22   7
This is a simple JavaScript assembler language specification with implemented virtual machine

Introduction

This article is about the JavaScript assembler language specification and implemented virtual machine as the execution platform. This article is completely a free-time project. It is written in order to use the new generation JavaScript browser engines to create custom assembler like language. Its purpose is not to be used instead of the native JavaScript language, but to use its data processing routines and be a platform for custom data processing implementations.

Background

The JavaScript is the scripting language for the Web. It runs inside the web page on the browser. There is a special virtual machine implemented inside the browser's core that executes the JavaScript code. Today, this virtual machine is very fast. It does not interpret JavaScript code like before, but rather compiles it into native code and executes it on the CPU. This is how Google's V8 JavaScript engine works. But, other will for sure follow this path.

On the other hand, the low-level assembler language is often very interesting for developers. There is, however, no assembler for JavaScript. This article does not implement this, but uses JavaScript as the execution platform for interpreting the assembler like language called JS-ASM. It syntax is similar to x86 assembler syntax, but its features are only basic since this is an experimental project.

JS-ASM assembler language specification (version 1.1)

The JS-ASM language is created to be easy to use and understand. It operates on the following data types: numbers, strings and objects. It has exactly 31 instruction (or directive) defined.

The included PDF manual contains the full JS-ASM language specification and examples of usage for each directive. Here is the short instruction list:

  • VAR - defines the variable
  • IN - loads the value from external JavaScript variable into the program variable
  • OUT - stores the value from program variable into the external JavaScript variable
  • MOV - moves the source value (variable or constant) to the destination variable
  • SHL - shifts variable values for custom number of bits to the left
  • SHR - shifts variable values for custom number of bits to the right
  • PUSH - pushes value (variable or constant) to the stack
  • POP - pops value from the stack and moves it into the variable
  • ADD, SUB, MUL, DIV - basic arithmetic operations
  • NOT, AND, OR, XOR - basic logical operations
  • CHR - converts number value to string
  • VAL - converts string value to number
  • CMP - compares the two values and sets the corresponding flag
  • JMP - unconditional jump to the defined label
  • JL, JG, JE, JNE, JLE, JGE - conditional jumps to the defined label
  • LIB - includes the external assembler library module
  • CALL - calls the subroutine
  • RET - returns from the subroutine
  • END - ends main program
  • INT - calls the external JavaScript function
  • ; - comment
  • LABEL: - custom label

I will show you in this article the most interesting features of the JS-ASM language, but for the complete reference consult the included PDF documentation.

Basic JS-ASM Assembler Program Example

Below is shown the basic JS-ASM program:

.MAIN
    VAR A
    VAR B
    MOV A, 10
    MOV B, 20
    ADD A, B
END

This code does simple addition. It defines two variables A and B and set its values to 10 and 20, respectively. Then it adds the value of the variable B to the value of the variable A and stores the new values to the variable A.

It is similar to the native x86 assembler syntax and very simple to understand.

Complex JS-ASM assembler program example

Below is shown the more complex JS-ASM program:

.MAIN
    VAR A
    VAR B
    MOV A, 10
    MOV B, 20
    CMP A, B
    JG L1
    SUB B, A
    JMP L2
L1: SUB A, B
L2: END

This code does comparison and branching with some arithmetic operations.

Loading values from the external JavaScript variables and storing them again

See the following code:

.MAIN
    VAR A
    IN A, myValue
    SUB A, 1
    OUT A, myValue
END

This code defines only one variable called A. Then it loads the value from the external JavaScript variable called myValue into this program variable. After that it subtracts the constant number 1 from the value of the program variable A. Finally, it stores the value of the variable A into the external variable myValue.

This is a very simple way to have the bi-directinal communication between the JS-ASM program and the external JavaScript program on the web page.

Calling the External JavaScript Function from the JS-ASM Assembler Program

Here is how to call the custom external JavaScript function:

.MAIN
    PUSH 'Hello, World !!!'
    PUSH 1
    INT myFunction
END

We push first the arguments to the stack. The last PUSH instruction puts the total number of arguments on the stack. Then we make the call to the external JavaScript function.

Somewhere on the web page the following function should be defined:

<script type="text/javascript">
    function myFunction(text)
    {
        // Put your processing code here
        alert(text);
    }
</script>

The INT instruction will call myFunction JavaScript function and the message box would appear (in this example).

Also, in this release of the JS-ASM language specification, the INT instruction is supporting the optional destination operand which can hold the returning value of the external JavaScript function that is being called.

Let's call the global JavaScript function parseInt which converts the floating point value to the integer value:

.MAIN
    VAR A
    PUSH 1.5
    PUSH 1
    INT A, parseInt
END

After the execution of the INT instruction, the variable A will hold the numeric value of 1.

This is identical to the following JavaScript code:

<script type="text/javascript">
    var A = parseInt(1.5);
</script>

Linking to the External Library Modules

It is good thing to have closed library modules that can be included in any program and use its subroutines for data processing when requested. The JS-ASM virtual machine implements this feature also.

Let's say that you have the following library on your web server:

; myLibrary.jsasm

.SUM
    VAR A
    VAR B
    POP B
    POP A
    ADD A, B
    PUSH A
RET

This library contains only one subroutine called .SUM which performs simple addition of two values. It defines two variables, reads two values from the stack and performs addition. Finally, it puts the result of the addition again on the stack.

Your main program will look like the following one:

LIB 'myLibrary.jsasm'

.MAIN
    VAR A
    PUSH 10
    PUSH 20
    CALL .SUM
    POP A
END

The LIB instruction will link your main program and the external library module, so the JS-ASM virtual machine will compile them together. We define only one variable A in the main program. Then we put the two values on the stack. We then call the subroutine from the library using CALL instruction. FInally, we read the result from the stack.

The main program and the external library module are in the separate ASCII files on the server.

JS-ASM Objects (New Feature in JS-ASM Language Specification)

In this release if the JS-ASM language specification the general JavaScript objects are supported.

See the following example:

.MAIN
    VAR P
    MOV P.Name, 'Johny'
    MOV P.Age, 33
END

In this example, a variable P is being created and in the following MOV instructions the two properties Name and Age are added to this variable, convering it to the JavaScript object.

This JS-ASM objects are just like the JavaScript objects. You can work with their object properties the way you work with the normal variables. The object properties can be numbers, strings or objects. In this manner, a hierarchicaly structured objects can be easily created.

With JS-ASM objects defined, the following is possible to do easily:

.MAIN
    VAR N
    IN N, document.getElementById('Log')
    MOV N.innerHTML, 'Hello, World !!!'
    IN N, document.getElementById('Log').innerHTML
END

In this example the HTML DOM element Log is loaded into the program object variable N. You are able to access any property or method of this DOM element from your program object N now. The next instruction modifies the innerHTML property of this element. The last instruction loads the modified property of this DOM element again into the program variable N.

It's important to notice here, since only object references are transfered between JavaScript objects, that the changes are visible on the web page immediately.

JS-ASM objects are very useful extension to the original JS-ASM language specification.

Using the Code

In this section I will show you how to use the JS-ASM virtual machine from the JavaScript code on the web page.

First, let's include the JS-ASM virtual machine JavaScript file to the web page:

<script type="text/javascript" src="jsasm.js"></script>

After this step we are ready to create the virtual machine JavaScript object:

<script type="text/javascript">
    var vmJSASM = new JSASM();
</script>

Next, let's compile some source code:

vmJSASM.compile(url);

The url points to the location on the web-server. After this step, your program is ready to be executed:

vmJSASM.execute();

After the execution step you can access to any JS-ASM assembler code block:

var mainBlock = vmJSASM.getBlockByName(".MAIN");

And get its variables by name or index:

var variable = mainBlock.getVariableByName(name);
var variable = mainBlock.getVariableByIndex(index);

Then, you can get the variable name and value properties:

var name = variable._variableName;
var value = variable._variableValue;

To get the total number of variables use the following:

var variableNumber = mainBlock.getVariableNumber();

To output all blocks and their variables (and also total compilation and execution time) as the innerHTML property of some element on the web page referenced by its id property, do the following:

vmJSASM.output(id);

To get the total compilation and execution time, use the following:

var c_time = vmJSASM.getCompilationTime();
var e_time = vmJSASM.getExecutionTime();

These simple methods would supply you with some kind of debugging tools, since the JS-ASM virtual machine does not supports debugging - yet.

In this release of the JS-ASM virtual machine, the following methods are added:

vmJSASM.compileFromSource(source);
vmJSASM.executeBlock(blockName);
vmJSASM.pushVariable(v);
vmJSASM.popVariable();

The compileFromSource method allows you to pass the JS-ASM source code directly to the virtual machine, so it does not have to be loaded from the web-server (except if it contains JS-ASM libraries). This way, you are able to generate the JS-ASM source code on your web page and compile it.

The executeBlock method allows you to execute only the specific block from your JS-ASM source code, referenced by name. In order to pass the variables to this JS-ASM block, use the pushVariable method. In order to get the results from this block, use the popVariable method.

Points of Interest

This was a very interesting project for me, since the JavaScript platform made possible for me to create a simple working virtual machine for a short time.

History

  • July, 2012. - JS-ASM assembler language specification, version 1.0
  • July, 2012. - JS-ASM assembler language specification, version 1.1 (new variable types added: objects)

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) Elektromehanika d.o.o. Nis
Serbia Serbia
He has a master degree in Computer Science at Faculty of Electronics in Nis (Serbia), and works as a C++/C# application developer for Windows platforms since 2001. He likes traveling, reading and meeting new people and cultures.

Comments and Discussions

 
GeneralMy vote of 5 Pin
nsimeonov10-Jul-12 9:03
nsimeonov10-Jul-12 9:03 
GeneralWhy? Pin
nsimeonov10-Jul-12 8:50
nsimeonov10-Jul-12 8:50 
Idea behind assembler is to be native and very fast. Idea behind higher level languages is to make programming easier.

Why on earth would one use a high-level language (scripting at that) to implement assembler interpreter? I mean for real not as university exercise??? You lose the speed of assembler because it's interpreted language not native. It's also hard to program because it's the lowest level language possible.

Nobody uses assembler if the task can be accomplished using C even for controllers and single-chip computers. All C compilers perform a lot of optimizations, so it's basically pointless to use assembler, except when you really have to and you need to squeeze CPU cycles for time-critical processing on very slow CPUs and this is maybe 0.000000001% of the cases or even less.

So...... WHY ?
QuestionRe: Why? Pin
sobo12310-Jul-12 16:19
sobo12310-Jul-12 16:19 
GeneralRe: Why? Pin
Member 1001861029-Apr-13 14:22
Member 1001861029-Apr-13 14:22 
QuestionInteresting... Pin
erikjacobsen8-Jul-12 23:34
erikjacobsen8-Jul-12 23:34 
AnswerRe: Interesting... Pin
darkoman8-Jul-12 23:45
darkoman8-Jul-12 23:45 
GeneralRe: Interesting... Pin
nsimeonov10-Jul-12 9:02
nsimeonov10-Jul-12 9:02 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.