X Sharp

From Wikipedia, the free encyclopedia
  (Redirected from X Sharp (programming language))
Jump to: navigation, search
The correct title of this article is X# (programming language). The substitution or omission of the # is because of technical restrictions.
X Sharp
Developer COSMOS Development Team, part of the Cosmos operating system
Appeared in 2009
Typing discipline weak (almost none)
Platform X86
Filename extension(s) .xs

X# is a low-level programming language developed for x86 processor architecture as a part of Cosmos operating system to make operating system development easier. X# was a programming language designed to bring some of C-like language syntax to assembly language. At the beginning, X# was a help for debugging services of Cosmos. The X# compiler is an open source console interface program with an atypical architecture. It parses lines of code into tokens and compares them with patterns. Finally, matched X# code patterns are translated to intel syntax x86 assembly, usually for the NASM compiler. In first versions, X# operation was mostly 1:1 with assembly code, but hasn't been the reason why the X# compiler was written.

Syntax[edit]

Syntax of X# is pretty simple. Despite its similarity with C, X# still differs and in some ways it is stricter.

Comments[edit]

There is only one type of comments in X# - singleline comments. The comment notation is same as it is in C language. Comment starts with double forwardslash - "//".

Constants[edit]

To declare named constant, you must be out of any function. The constant definition is same as in C++ - use "const" keyword, constant name and equation mark followed by number. To reference constant in code there must use sharp character (#, for example "#VideoMemory").

  • For string constants, single quotes () are used. X# strings are zero-terminated, single quote can be contained in string using backslash before it ('I\'m so happy').
  • For hexadecimal constant numbers, dollar mark ($) before value is used and standard hex. prefix (0x) is omitted (e.g. $B8000 instead of 0xB8000).
  • For decimal there's nothing used, but decimal numbers shouldn't be started with zero.
  • Binary and octal constants aren't supported yet.

Labels[edit]

Task of labels in X# is taken from assembly language, although it uses C keyword for label jump. Label can be defined by writing ':' after label name.

CodeLabel1:

Execution can jump to label using goto keyword.

Namespaces[edit]

Every X# program file must be started with namespace. In X# there's no namespace hierarchy, so typing namespace keyword will change actual namespace and this namespace will be used until it's redefined or until the file ends. Namespaces are prefixes of assembly output, so variable, constant or function name won't be in conflict if they are not in the same namespace. Note that there's no way to reference from one namespace to another (except small cheats with native assembly blocks).

namespace FIRST
// Everything here will be prefixed with FIRST. Hence the "true" full name of the below variable
// is FIRST_aVar
var aVar
namespace SECOND
// Not a problem to name another variable aVar. Its true name is SECOND_aVar
var aVar
namespace FIRST
// And here we get back to the FIRST namespace, until this file ends.

Functions[edit]

All X# executive code should be placed in functions defined by 'function' keyword. Unlike C, X# does not support any formal parameter declaration in the header of the functions, so the brackets after function name are omitted and function name is then followed directly with opening curly bracket. Because line-fixed patterns are specified in syntax implemented in code parser, opening curly bracket can't be placed on the next line, as it's usual for C# or some C language code styles.

function xSharpFunction {
    //function code
}

Because X# low-level, there are no stack frames inserted, so defaultly there should be return EIP on the top of the stack. X# function calls are different in case of brackets. Calls are more like in C. There can be registers, addresses or constants in call brackets. As it standard is in C, they're placed on the stack in reversed order. Note that x86 stack can't push/pop one-byte registers.

function xSharpFunction {
    EAX = $10
    anotherFunction(EAX);
    return
}
function anotherFunction {
    //function code
}

The return keyword returns execution to return EIP saved in stack.

Arithmetic and bitwise operations[edit]

As it is in assembly language, in X# you can work with three data structures: registers, stack and memory (ports are different). For X#, registers are base of all normal operations. You can simply copy the content of one register to another by writing DST = SRC like when programming in high-level languages. Incrementation and decrementation of registers is same. Adding, subtracting, multiplying or dividing is more like in assembly. The first parameter of operation is also destination of result.

ESI = 12345
EDX = #constantForEDX
EAX = EBX     //move EBX to EAX              => mov ebx, eax
EAX--         //decrement EAX                => dec eax
EAX++         //increment EAX                => inc eax
EAX + 2       //add 2 to eax                 => add eax, 2
EAX - $80     //sub. 0x80 from eax           => sub eax, 0x80
BX * CX       //multiply BX by CX            => mul cx      -- division, multiplication and modulo should preserve registers
CX / BX       //divide CX by BX              => div bx
CX mod BX     //remainder of CX/BX to bx     => div bx

Register shifting and rolling is similar to C.

DX << 10  //shift left by 10 bits
CX >> 8   //shift right by 8 bits
EAX <~ 6  //rotate left by 6 bits
EAX ~> 4  //rotate lright by 4 bits

Other bitwise operations are in their usual form.

DL & $08     //applicate and on DX with mask 1000 in binary
CX | 1       //set first bit of CX to 1 (make it odd)
EAX = ~ECX   //NOT the ECX to EAX
EAX ^ EAX    //erase EAX

Stack[edit]

Stack manipulation in X# is solved using + and - prefixes, where + pushes register, value, constant or all registers on stack and - pops the value to some register .Are constants are being pushed on stack as doublewords, until you explicitly specify difference (note that there's not way of pushing bytes).

+ESI                   //push esi
-EDI                   //load edi
+All                   //save all registers   => pushad
-All                   //load all registers   => popad
+$1badboo2             //save 0x1badboo2 on the stack
+$cafe as word         //         \/
+$babe as word         //save 0xcafebabe
+#VideoMemory          //save value of constant VideoMemory

Variables[edit]

Variables are defined within namespaces (no stack frames => no local variables) using var keyword. Arrays can be defined by adding array type and size on the declaration end. Arrays are by default filled with zeroes as the normal variables. Then, whenever the variable is referenced in code, it must be preceded with dot. Using dot will get its value. Preceding dot with address character (@) will get the address of the variable.

namespace XSharpVariables
var zeroVar                      //variable will be assigned to zero
var myVar1 = $f000beef           //variable will be assigned to 0xf000beef
var someString = 'Hello XSharp!' //variable will be assigned to 'Hello XSharp!', 0
var buffer byte[1024]            //variable of size 1024 bytes will be assigned to 1024 zeroes
...
EAX = .myVar1                    //moves value of myVar1 (0xf000beef) to EAX
ESI = @.someString               //moves address of someString to ESI
CL = .someString                 //moves first character of someString ('H') to CL
.zeroVar = EAX                   //assigns zeroVar to value of EAX

With X#, it is possible to access some addressed with specified offset from base by putting the byte offset into square brackets:

var someString = 'Hello XSharp!' //variable will be assigned to 'Hello XSharp!', 0
...
ESI = @.someString       //load address of someString to ESI
CL = 'B'                 //set CL to 'B' (rewrite 'H' on the start)
CH = ESI[1]              //move second character ('E') from string to CH
ESI[4] = $00             //end string
//Value of someString will be 'Bell' (or 'Bell',0,' XSharp!',0)

Comparison[edit]

There are two ways of comparing values: pure comparison and if-comparison.

  • Pure comparison leaves the result in FLAGS so it can be used in native assembly or using if keyword without specifying comparison members.
  • If comparison compares two members directly after if keyword.

Here are two ways of writing slow X# strlen function:

//Way 1: using pure comparison
function strlen {
    ESI = ESP[4] //get pointer to string passed as first argument
    ECX ^ ECX    //xor ecx, ecx (ecx = 0)
Loop:
    AL = ESI[ECX]//get next character
    AL ?= 0      //is it 0? save to FLAGS
    if = return  //if ZF is set, return
    ECX++        //else increment ECX
    goto Loop    //loop...
//Way 2: using if
function strlen {
    ESI = ESP[4]    //get pointer to string passed as first argument
    ECX ^ ECX       //xor ecx, ecx (exc = 0)
Loop:
    AL = ESI[ECX]
    if AL = 0 return//AL = 0? return
    ECX++
    goto Loop       //loop....
}

There are six available comparison operators: < > = <= >= !=. These operators are usable in comparisons as in loops. Note that there's also bitwise AND operator which tests bits:

AL ?& $80      //test AL MSB
if = return    //if ZF is 0, test instruction resulted to 0 and MSB is not set.