Assembler Tutorial

Diskussionen zu Tutorials, Änderungs- und Erweiterungswünsche
Sunji

Re: Assembler Tutorial

Beitrag von Sunji » Mo Nov 07, 2011 6:28 pm

Ok Xin, dann geht es hier mal weiter ....

Heute wollen wir anschaulich demonstrieren, wie man Assembler und C++ kombinieren kann. In unserem Beispiel werden wir eine Assembler Funktion innerhalb eines C++ Programms aufrufen. Da ich die Inline Variante nicht mag, habe ich mich entschlossen zwei separate Dateien zu erstellen und später zu einer zu verbinden.

Ein Thread hier im Forum bzgl. der Funktion (!(value & 1) hat mich auf die Idee gebracht dies als Beispiel zu benutzen.

Wir wollen also eine Funktion in Assembler schreiben, die bestimmt ob eine Zahl gerade oder ungerade ist. Das Problem bei der ganzen Sache ist wie bekommen wir die beiden Dateien zusammen und das sie miteinander interagieren ?
Der Befehl "extern" hilft uns da weiter.

Hier der Quellcode des main.cpp Programms :

Code: Alles auswählen

/*
	Programm: ISEVEN	
	Beschreibung : Testet eine Integer Variable ob sie gerade ist
	Syntax : bool iseven(int value)
	Return : 0 = FALSE ; 1 = TRUE
*/
#include <iostream>
extern "C" bool iseven(int value);
using namespace std;

int main()
{
	for (int i = 1; i < 11; ++i)
	{
		cout << i << " ist gerade : ";
		if (iseven(i))  
			{cout << "WAHR" << endl;} 
			else 
			{cout << "FALSCH" << endl;};
	}
	return 0;
}
Das Programm ruft also eine externe Funktion bool iseven(int value) auf die wir nun in Assembler liefern wollen.

iseven.asm

Code: Alles auswählen

; extern "C" bool iseven(int value);

global iseven              ; linker und NASM benötigen das Symbol

section .text              

iseven:
       push ebp             ; Sichern der Register und Zeiger
       mov  ebp, esp      
       push ecx              
       push esi

calc:                                   ; Die eigentliche Funktion beginnt hier
       mov eax, [ebp+8]	   ; kopiert 'value' nach eax 
       and eax, 1	                   ; eax = eax AND 1
                                           ; Da wir ja nur noch 1 oder 0 haben
			                   ; können wir mit Register al weitermachen
			                   ; sprich 1 byte
       xor al, 1                   ; al = al ^ 1 (negieren)
			                   ; ... und endet hier return (al)
			   
return:
       pop esi             ; Register wieder herstellen
       pop ecx
       pop ebp
       ret                  ; return ausführen
Kompiliert wird das ganze wie folgt :

Code: Alles auswählen

nasm -f elf iseven.asm
g++ main.cpp iseven.o
Die ausführbare Datei die daraus entsteht lautet a.out.
Fertig!

Viele Dinge können einfacher in C oder C++ programmiert werden. Wenn aber gewisse Teile geschwindigkeitsabhängige Operationen ausführen sollen, ist es ratsam sie in Assembler zu programmieren. Ein gutes Beispiel ist der letzte Wörter-zähl Wettbewerb. Die Algorithmen in Assembler waren alle schneller und ließen die C/C++ Fraktion weit hinter sich.
In diesem Sinne

Cya Sunji

Antworten