TEIMSI
Developer's platform of programming text codes
Home|Utilities|Forum|Documentation

Table of contents -> Chapter 5 - Introduction to the use of FASM with Teimsi

FASM

FASM (Flat assembler), is a compiler and assembler program for assembly language source code. The accepted syntax by it depends on the version of it, the version used by the current version of the TEIMSI editor is 1.68.

To compile an assembler language file is relatively simple, some examples of themes are at the "EXAMPLES" folder inside the "FASM" folder.

The assembler also allows you to create executable files with .elf format used in Linux (specifically Debian and Ubuntu) operating systems. The main difference between Linux and programs Win.2000/XP/7/... is that Linux does not have the import section of libraries "API", but it must included the "C" library functions (we expect to give better support to the creation of application on Linux systems in further versions of the editor to compile .ELF files using the "xlib" library for creating windows and controls).

Returning to the topic's title, an example of simple program is shown next.


		; //############################################################
		
		
		format PE GUI 4.0
		
		include 'include\win32a.inc'

		
		section '.text' code readable executable
		
			invoke	MessageBoxA,0,_message,_caption,MB_ICONINFORMATION
		
			invoke	ExitProcess,0
		
		
		section '.data' data readable writeable
		
			_message db 'Hello world!',0
			_caption db 'Message',0
		
		
		section '.idata' import data readable writeable
		
			library kernel32,'KERNEL32.DLL',\
				user32,'USER32.DLL'
			
			import kernel32,\
				ExitProcess,'ExitProcess'
			
			import user32,\
				MessageBoxA,'MessageBoxA'
		
		; //############################################################


To compile it, after placing the text in a file called "example.asm" it must be run the command line: "fasm.exe example.asm". The editor simplifies the task because we just open the editor for a file called "example.tsi" put the instruction alert("Hello World") and compile with the F5 key.

The assembler allows us to create an executable program (with .exe extension) or dynamic library from the content created by TEIMSI.

The content created by TEIMSI includes a folder whose name begins with the same TEIMSI code file's name (which has .tsi extension), it will be placed into the same folder as the .tsi file and its name is followed by the "_asm_files" string; for example if the project file is "UltraProgri.tsi" then the folder that the compiler will create is "UtraProgri_asm_files", on it will be saved the necessary files for the assembler compiler to make its output creation. The project file can be a file with another extension such as ".thp" or ".php" or ".tco" or ".asm" because they are accepted by the TEIMSI editor. But as convention we preferred to use the .tsi extension to indicate the main file of a TEIMSI project, also the .thp extension for files with additional TEIMSI code to a project and the ".tco" extension for "object" files compiled by the TEIMSI editor. The ".php" extension applies to text in Php language or for custom contained text that includes (for example) comments and code examples, while the ".asm" files have assembler language code, to be included through the include "filename" instruction; available in the assembler instruction set.

To begin creating a TEIMSI project, simply create a folder with the project name and create file on it with the ".tsi" extension which will contain the main TEIMSI code and any possible includec() and include_tco() instructions to include other files to the project the files with ".thp" or ".tco" extension. (For more information see File inclusions. The default paths constants).

After the folder and file are created, open the tsi file with the TEIMSI editor by making double click on it, and we put on it (as example) the following:


; //########################################################################################################

	var message1="Hello world! number77=";

	function show(msg){
		alert(msg)
	}
	var number77=0;		//	creates an integer type variable.
	_direct{
		mov eax, 11
		mov ebx, 7
		mul ebx
		mov [number77+reg.vo], eax
	}
	show(message1+number77)

@eof_file

; //########################################################################################################

Then press the F5 key (or click on the Compile menu and then "Create and run .exe ..."), the ".exe" that will be created will have the filename of the .tsi project file.

Let's do a brief analysis code. We distinguish the root module as the code that excludes the code written functions, so for the compiler understands that after the instruction "var message1=..." comes the instruction "var number77=0". In the first line it was wrote:

var message1= "Hello World! number77 =";

This instruction declares the root module variable "message1" which contains a static text (length 21 bytes). When including static string variables, there are TEIMSI three types of modalities for variables (see TEIMSI Variables).

In the following lines it's written:

	function show(msg){
		alert(msg)
	}

It's a function that doesn't return a value, indeed the alert(show("a")==undefined) instruction will show "true" and then shows the "a" text. The "show" function only shows a string and then terminates. In the next line it's written:

	var number77=0;

This states that "number77" is a variable that will contain a long integer, it could be a boolean by placing "var number77=false" or a floating point number with double precision by placing "var number77=0.0" (note the additional ".0"), but it was chosen an integer which has the easiest way to access (read and write) to it's information using assembler. In the following lines it's written:

	_direct{
		mov eax, 11
		mov ebx, 7
		mul ebx
		mov [number77+reg.vo], eax
	}

The "_direct{" instruction sends the following lines directly to the assembler code text until an alone "}" character it's encountered. Indeed if that line is discussed putting "} // Commenting" a syntax error will occur because the compiler does not perceive the end of the assembler block lines. Nor would be right to declare "_direct{ // Comment".

The valid language for this block is FASM's assembler language, for the example, it's placed the 11 integer into the eax register, then 7 into the ebx register, and then makes a "mul ebx" which actually put in the edx register the "high part" of the multiplication and into eax the "low part"; for now we are interested only in eax, because the result will not exceed the value of the 32 bits minus one which is 4294967295. Then it puts the result of eax into the space determined by the value of the variable "number77" whose offset is indicated by "+reg.vo". All the variables under TEIMSI are "variant" and so to determine their type, data type, length value: it's used a structure with 16 bytes or 4 dwords. The structure has been called "reg" or "regvar" which is equivalent to the following structure:

reg

 

		struct reg
			mo	dd	?		; Contains the mode
			ty	dd	?		; Contains the data type (boolean, integer, double, string, etc) 
			vo	dd	?		; Contains the value for booleans, integers and doubles; or the string's handle.
			nu	dd	?		; Contains the string's length or the highest part of the floating point number with double precision (8 bytes).
		ends


regvar

The structure "regvar" is equivalent to "reg":

		struct regvar
			vmode	dd	?
			vtype	dd	?
			vofix	dd	?
			vnull	dd	?
		ends

Then after running "mov [number77+reg.vo], eax" the number77 variable has the value of the integer that the eax register had which is 11 * 7 = 77.

In the next line it's written:

show(mensaje1+number77)

We would wonder what happened to the character ";" right of instruction, but in TEIMSI such indication is optional (even when compiled is considered as the beginning of a new line for which there is no practical interest with the exception of expressing multiple instructions per row).

With the call to the "show" function it will be shown the output of the sum of "message1" with "number77", number77 is the variable with the 77 integer. It should be noted that just as in other known languages as "Jscript ", since the "message1" variable has a string type, anything added to it's right (or anything that added to it's left) will give a total result of a string. The number77's value is automatically converted to a string, then the result is a string.

And the last instruction is:

@eof_file

It's similar to @eof_module (which indicates the end of the root module) and is used like it is (no spaces on the left and nothing on the right). For the TEIMSI compiler this line and it's exact shown representation indicates the end of the whole project. The compiler separates the text that it is not for him to do the work of creating the output executable, library or TEIMSI compiled object.

This instruction is very useful to place immediately after it programming texts, comments or any text the programmer needs to incorporate into the project file.

FASM is a simple and potential tool whose knowledge is recommended for professional programmers of TEIMSI code, simple applications can be found in the "EXAMPLES" folder of FASM. You can create a script that only makes use of assembly language. The following is an example named "sample.tsi":


;// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 

//	What this assembler example does is to add the inverse squares from 1 to 1000 (sum tends to pi*pi/6) and then displays the integer that is the total sum multiplied by 10000.

	place_idata{
		numsum dq 0.0
		numdd  dd 0
	}
	_direct{
		mov ecx, 1000
		@@:
			mov [numdd], ecx
			fild [numdd]
			fld st
			fmulp st1, st
			fld1
			fdivrp st1, st		;	That in other words is to find 1/(ecx*ecx) and add it to the numsum variable.
			fadd [numsum]
			fstp [numsum]
		dec ecx
		jnz @b
		mov [numdd], 10000
	
		fld [numsum]
		fimul [numdd]			;	Multiply the sum by 10000.
		fistp [numdd]
	
		MOSTRAR2 [numdd]		;	This macro "MOSTRAR2" sample value/32-bit register in this case is 16439.
	}

	;Important Observation:
	;	The "FISTP [numdd]" instruction saves the contents of st Coprocessor register but
	;	the rounding mode of a number to an integer is determined by the flags of 
	;	Coprocessor "control" register served by the instruction "fldcw" and "fstcw". the
	;	TEIMSI applications change in the base code (which precedes the user code) the
	;	Coprocessor integer rounding mode: by default when you start
	;	a program a number is rounded to an integer "FISTP [numdd]" but since 
	;	 base code changed the flag, it's a lower rounded integer value, for example 1.6 becomes 1.
	;	To change that behavior you should load the default mode according indicate the following
	;	three instructions:
	;	
	;		fldcw [public_old_fpu_cw]		;	Load the default control register in order to round to nearest integer.
	;		fistp [numdd]
	;		fldcw [public_new_fpu_cw]		;	Restores the modified control register (which is used by functions TEIMSI) to round to the nearest lower integer.
	;	
	;	The result is an integer that is equivalent to one that is shown in the following TEIMSI instruction:
	;
	;		alert(parseint(10000*numsum))


// The following is an example named "sample2.tsi", it has the equivalent TEIMSI code:

	var numsum=0.0
	for(var t=1000;t>=1;t--){
		numsum+=1/(t*t)
	}
	alert(floor(10000*numsum))		//	Shows "16439". Equivalent to: alert_ex(floor(10000*numsum), "The sum is:", _mb_ok)

// Note that in this case with only 5 lines of TEIMSI code do what about 23 assembler lines, the assembler's advantage is to be faster.


;// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 


Go to top