Buchempfehlung
Visual Basic 6 Kochbuch
Visual Basic 6 Kochbuch
Viele praktische Tipps zum Programmieren mit Visual Basic 6, die sich oft auch auf FB übertragen lassen. [Mehr Infos...]
FreeBASIC-Chat
Es sind Benutzer im FreeBASIC-Chat online.
(Stand:  )
FreeBASIC bei Twitter
Twitter FreeBASIC-Nachrichten jetzt auch über Twitter erhalten. Follow us!

Tutorial

Inlineassembler in FreeBASIC

von RedakteurVoltaSeite 4 von 9

Rechenoperationen in Inlineassembler

Einschränkung: erst einmal keine Beachtung von überlauf und Vorzeichen.

Addition ADD

Dim As Long z1, z2, z3

z1 = 123456789
z2 = 234567890

asm
 mov eax, [z1] 'eax = [z1]
 mov ebx, [z2] 'ebx = [z2]
 add eax, ebx  'eax + ebx
 mov [z3], eax '[z3] = eax
End asm

Print z1, z2, z3
sleep

Eine klassische Operation nach dem EVA - Prinzip:

Trick:

Dim As Long z1, z2, z3

z1 = 123456789
z2 = 234567890

asm
 mov eax, [z1]
 mov ebx, [z2]
 lea eax, [eax + ebx]
 mov [z3], eax
End asm

Print z1, z2, z3
sleep

Sieht auf den ersten Blick nicht wie eine Addition aus, ist aber eine.
Hier wird der LEA Befehl zur Addition benutzt. Das hat manchmal einen kleinen Geschwindigkeitsvorteil, da dieser Befehl nur mit den Registern des Prozessors arbeitet.
Eine Konstante dürfte noch zusätzlich addiert werden (z.B. lea eax, [eax + ebx + 64])
Variante zum ersten Beispiel:
Das Ergebnis soll in z2 berechnet werden, vergleichbar mit freeBASIC z2 += z1.

Dim As Long z1, z2

z1 = 123456789
z2 = 234567890

asm
 mov eax, [z1]
 add [z2], eax
End asm

Print z1, z2
sleep

Genau wie beim MOV - Befehl dürfen auch beim ADD - Befehl nicht beide Operanden auf eine Adresse zeigen, deshalb wird hier das eax - Register mitbenutzt.

Subtraktion SUB

Klassische Version:

Dim As Long z1, z2, z3

z1 = 123456789
z2 = 234567890

asm
 mov eax, [z1] 'eax = [z1]
 mov ebx, [z2] 'ebx = [z2]
 sub eax, ebx  'eax - ebx
 mov [z3], eax '[z3] = eax
End asm

Print z1, z2, z3
sleep

Wenn man eine größere Zahl von einer kleineren Zahl abzieht dann kommt ein negatives Ergebnis, aber nur weil wir hier mit vorzeichenbehafteten [url=ref:321;Integer[/url] - Variablen (z1, z2, z3) arbeiten!
Ändere dies:

Dim As ULong z1, z2, z3

und das Ergebnis sieht anders aus.

Mal was Neues:

Dim As Byte z3

asm
 jmp Label3     'Springe zu dem Befehl der nach Label3: steht
L1: .Byte 234   'L1: wird wie eine Variable in FB
                'behandelt die den Wert 234 enthält
L2: .Byte 246

Label3:
 mov al, [L1]   'Hier wieder klassisch
 mov bl, [L2]   'nur mit Byte
 sub al, bl
 mov [z3], al
End asm

Print z3
sleep

Label setzen
Ein Label (oder Marke) ist durch einen Doppelpunkt am Ende gekennzeichnet, dann wird dem Ausdruck eine Adresse im Speicher zugewiesen.
An dieser Stelle befindet sich sozusagen ein Fixpunkt, der entweder im Programmablauf liegt und als Ansprungmarke dient, oder eine Stelle kennzeichnet an der Daten abgelegt wurden.
Im Beispiel werden beide Arten gezeigt: Label3 ist eine Sprungmarke, L1 und L2 kennzeichnen Daten.

Wie war das noch, ein Prozessor kann eigentlich nicht subtrahieren?
Er bildet das Externer Link! Zweierkomplement und addiert dann?
Versucht wir es mal:

Dim As Short z3

asm
 jmp Label3
L1: .short 2345
L2: .short 2467

Label3:
 mov ax, [L1]
 mov bx, [L2]
     'Zweierkomplement von bx bilden
 Not bx       'negieren von bx
 inc bx       'bx + 1

 add ax, bx   'dann addieren
 mov [z3], ax
End asm

Print z3
sleep

Na also, geht noch!
Die Subtraktion wird auf eine Addition zurückgeführt.
Da ist noch ein neuer Befehl enthalten INC, damit kann ein Register um den Wert 1 erhöht werden. Der entsprechende Befehl für Register - 1 ist DEC. Beide werden bei der Erstellung von Zählschleifen häufig eingesetzt.

Multiplikation MUL

Dim As ULong z1, z2, z3, z4
Dim zlang As UlongInt

z1 = 207700
z2 = 56012

asm
 mov ebx, [z2] 'ebx <- [z2]
 mov eax, [z1] 'eax <- [z1]
 'cdq           'Vorzeichenerweiterung auf edx - Register
 xor edx, edx  'edx <- 0
 mul ebx       'edx:eax <- eax * ebx
 mov [z3], eax '[z3] <- eax
 mov [z4], edx '[z4] <- edx ; übertrag

 mov [zlang], eax     '[zlang ; xxxxLLLL] <- eax
 mov [zlang + 4], edx '[zlang ; HHHHxxxx] <- edx
 End asm

Print z4, z3
Print zlang
sleep

Viel zu aufwändig der Asm - Teil? Sonst steht da nur 'MUL reg' und fertig!
Na ja, wenn ich sicher bin 32 Bit, die Registergröße, nicht zu überschreiten mach ich das auch so. Wenn ich das aber nicht von vornherein festlegen kann, dann ist mir dieser Aufwand lieber, denn ich bekomme ein genaues Ergebnis.

Trick:

Dim As Long  z3

asm
 mov eax, 2077
 shl eax,1        ' multiplizieren mit 2
 mov [z3], eax
End asm

Print z3
sleep

SHL reg, n ist ein Befehl der alle Bitwerte des Registers (reg) um die Anzahl (n) Stellen nach links versetzt (schiebt)und rechts eine 0 einfügt.
Wenn wir das in unserem gewohnten Dezimalsystem machen, sprechen wir davon "das Komma eine Stelle nach rechts zu schieben", wir multiplizieren mit 10.
Im Binärsystem multiplizieren wir mit der Basis 2. D.h. jedes linksschieben entspricht einer Multiplikation mit 2, jedes rechtsschieben (SHR reg, n) entspricht einer Division durch 2.

Division DIV

Bei der Division gibt es nicht die Überlaufprobleme wie bei der Multiplikation.
Trotzdem wird wieder das edx - Register mitbenutzt!

Dim As integer z1, z2, z3, z4

z1 = 207700
z2 = 560

asm
 mov eax, [z1]
 mov ebx, [z2]
 xor edx, edx
 div ebx        ' dividieren
 mov [z3], eax  '
 mov [z4], edx  ' Rest ( z1 Mod Z2)
End asm

Print z3, "Rest: ";z4
sleep

Bei der BefehlsreferenzeintragIntegerdivision (Ganzzahldivision mit Rest) wird das Ergebnis in das eax - Register und der verbleibende Rest in das edx - Register gespeichert. Der Rest im edx - Register hat das gleiche Ergebnis wie die BefehlsreferenzeintragMOD-Operation in freeBASIC.

 

Gehe zu Seite Gehe zu Seite  1  2  3  4  5  6  7  8  9  
Zusätzliche Informationen und Funktionen
  • Das Tutorial wurde am 09.08.2008 von RedakteurVolta angelegt.
  • Die aktuellste Version wurde am 09.12.2015 von RedakteurVolta gespeichert.
  Bearbeiten Bearbeiten  

  Versionen Versionen