Technische Informatik I
x86 Maschinensprache + Assembler
Thorsten Thormählen
20. Januar 2022
Teil 10, Kapitel 1
Thorsten Thormählen
20. Januar 2022
Teil 10, Kapitel 1
Dies ist die Druck-Ansicht.
Weiterschalten der Folien durch die → Taste oder
durch das Klicken auf den rechten Folienrand.
Das Weiterschalten der Folien kann ebenfalls durch das Klicken auf den rechten bzw. linken Folienrand erfolgen.
Typ | Schriftart | Beispiele |
---|---|---|
Variablen (Skalare) | kursiv | $a, b, x, y$ |
Funktionen | aufrecht | $\mathrm{f}, \mathrm{g}(x), \mathrm{max}(x)$ |
Vektoren | fett, Elemente zeilenweise | $\mathbf{a}, \mathbf{b}= \begin{pmatrix}x\\y\end{pmatrix} = (x, y)^\top,$ $\mathbf{B}=(x, y, z)^\top$ |
Matrizen | Schreibmaschine | $\mathtt{A}, \mathtt{B}= \begin{bmatrix}a & b\\c & d\end{bmatrix}$ |
Mengen | kalligrafisch | $\mathcal{A}, B=\{a, b\}, b \in \mathcal{B}$ |
Zahlenbereiche, Koordinatenräume | doppelt gestrichen | $\mathbb{N}, \mathbb{Z}, \mathbb{R}^2, \mathbb{R}^3$ |
jmp
verwendet (für engl. "jump");#include <stdio.h> // includes "printf" command ; int add(int varA, int varB ) { // inline assembler starts here __asm { mov eax, varA ; // move first argument to EAX register mov ecx, varB ; // move second argument to ECX register add eax, ecx ; // EAX = EAX + ECX } } int main() { int result = add(1, 2); // call C-function "add" printf( "1 + 2 = %d\n", result); // output result to console return 0; }
-use-msasm
verwendet werden
> icc -use-msasm -o my_program main.cpp
AX
, BX
, CX
und DX
sind als 8-Bit Register
gesondert ansprechbar (z.B. AX
besteht aus AL
und AH
)EAX
, EBX
, usw. angesprochen werdenRegister | Sonderfunktion | Erklärung |
---|---|---|
AX | Akkumulator | Ziel für Rechenoperationen |
BX | Base | Zeiger für Zugriffe auf Speicher |
CX | Counter | Zähler in Schleifen |
DX | Data | Datenregister |
SI | Source Index | Quellindex für Verarbeitung von Zeichenketten |
DI | Destination Index | Zielindex für Verarbeitung von Zeichenketten |
BP | Base Pointer | Anfangsadresse des Stapelsegments |
SP | Stack Pointer | Stapelzeiger |
Flag | Bedeutung | Erklärung |
---|---|---|
CY | Carry | Bereichsüberschreitung für vorzeichenlose Zahlen |
AC | Aux. Carry | Bereichsüberschreitung für vorzeichenlose 4-Bit Zahlen |
OV | Overflow | Bereichsüberschreitung bei arithmetischer Operation auf Zahlen mit Vorzeichen |
PL | Sign | Ergebnis war negativ |
ZR | Zero | Ergebnis war null |
PE | Parity | Ergebnis hat eine gerade Anzahl von Einsen (im niederwertigsten Byte) |
UP | Direction | Legt die Richtung von String-Befehlen fest |
EI | Interrupt | Bestimmt, ob Interrupts zugelassen werden |
Register | Funktion | Erklärung |
---|---|---|
CS | Code Segment | Anfangsadresse des Code-Segments |
DS | Data Segment | Anfangsadresse des Daten-Segments |
SS | Stack Segment | Anfangsadresse des Stack-Segments |
ES | Extra Segment | keine besondere Funktion |
FS | keine besondere Funktion | |
GS | keine besondere Funktion |
[Label] [Operation] [Operanden] [;Kommentar]
op ziel, quelle
op
verknüpft werdenZiel = Ziel op Quelle;
mov eax, ecx ; eax = ecx sub ax, cx ; ax = ax - cx add cx, ax ; cx = cx + ax
mov ziel, quelle
int main() { int varA = 6; int varB = 7; __asm { mov eax, 10h ; // move the hex value 10 to EAX mov eax, 10 ; // move the decimal value 10 to EAX mov eax, 010 ; // move the octal value 10 to EAX mov ecx, eax ; // move EAX register to ECX register //mov fs, ds ; // does not work //mov ax, ds ; // this works instead: (but segment registers //mov fs, ax ; // should not be modified) mov eax, 11111111h ; // EAX = 11111111h; mov ax, 3333h ; // EAX = 11113333h; //mov varA, varB ; // does not work mov eax, varB ; // this works instead: mov varA, eax } return 0; }
add
führt eine Addition aus:
add ziel, quelle
#include <stdio.h> int main() { int varA = 6, varB = 7; __asm { //add varA, varB ; // does not work mov eax, varB ; // this works instead: add varA, eax ; // } printf("varA = %d\n", varA); __asm { mov eax, 21 mov edx, 24 add eax, edx mov varA, eax } printf("varA = %d\n", varA); return 0; }
add
, verändern das Flagregisteradd
beeinflusst: OV
,PL
,ZR
,AC
,
PE
und CY
int main() { __asm { mov eax, 00000000h mov ecx, 00000000h add eax, ecx ; // EAX=0; Flags: OV=0 PL=0 ZR=1 AC=0 PE=1 CY=0 mov eax, 00000000h mov ecx, 00000001h add eax, ecx ; // EAX=1; Flags: OV=0 PL=0 ZR=0 AC=0 PE=0 CY=0 mov eax, 00000001h mov ecx, 0000000Fh add eax, ecx ; // EAX=10; Flags: OV=0 PL=0 ZR=0 AC=1 PE=0 CY=0 mov eax, 00000000h mov ecx, 7FFFFFFFh add eax, ecx ; // EAX=7FFFFFFF; Flags: OV=0 PL=0 ZR=0 AC=0 PE=1 CY=0 mov eax, 00000001h mov ecx, 7FFFFFFFh add eax, ecx ; // EAX=80000000; Flags: OV=1 PL=1 ZR=0 AC=1 PE=1 CY=0 mov eax, 00000001h mov ecx, -2; ; // ECX=FFFFFFFE; (Two's complement) add eax, ecx ; // EAX=FFFFFFFF; Flags: OV=0 PL=1 ZR=0 AC=0 PE=1 CY=0 mov eax, 00000001h mov ecx, -1; ; // ECX=FFFFFFFF; add eax, ecx ; // EAX=00000000; Flags: OV=0 PL=0 ZR=1 AC=1 PE=1 CY=1 } return 0; }
mov eax, 00000002h mov ecx, 7FFFFFFEh add eax, ecx
mov al, -3 ; // AL=FDh; mov cl, -1 ; // CL=FFh; add al, cl ; // AL=FCh; Flags: OV=0 PL=1 ZR=0 AC=1 PE=1 CY=1 mov al, 253 ; // AL=FDh; mov cl, 255 ; // CL=FFh; add al, cl ; // AL=FCh; Flags: OV=0 PL=1 ZR=0 AC=1 PE=1 CY=1
mov eax, 253 mov ecx, 255 add eax, ecx ; // EAX=000001FC; Flags: OV=0 PL=0 ZR=0 AC=1 PE=1 CY=0
adc
verwenden, der genau wie der add
Befehl arbeitet, jedoch
zusätzlich das Carry-Bit hinzuaddiert
mov al, 253 ; // AL=FDh; mov cl, 255 ; // CL=FFh; mov ah, 0 ; // AH=0h; add al, cl ; // AL=FCh; AH=0h; Flags: OV=0 PL=1 ZR=0 AC=1 PE=1 CY=1 adc ah, 0 ; // AL=FCh; AH=1h; Flags: OV=0 PL=0 ZR=0 AC=0 PE=0 CY=0 // AX=01FCh
sub
führt eine Subtraktion aus:
sub ziel, quelle
OV
,PL
,ZR
,AC
,
PE
und CY
CY
gesetzt, wenn $($ziel
$<$ quelle
$)$ (bei Interpretation als vorzeichenlose Zahl).
Das Carry erfüllt dann die Funktion eines Borrow.
OV
relevant
quelle
und dem Zweierkomplement von ziel
implementiert werden,
also $a - b = a + (-b)$ (siehe Kapitel Arithmetik Schaltungen )
ziel
$\ge$ quelle
$)$.
Für den x86-sub
Befehl, müsst das Carry der Harwareschaltung demnach invertiert werdenint main() { __asm { mov al, 2 ; // AL=02h; mov bl, -1 ; // BL=FFh; sub al, bl ; // AL=03h; Flags: OV=0 PL=0 ZR=0 AC=1 PE=1 CY=1 mov al, 2 ; // AL=02h; sub al, 255 ; // AL=03h; Flags: OV=0 PL=0 ZR=0 AC=1 PE=1 CY=1 } return 0; }
CY
wird invertiert):
sbb
steht für engl. "subtract with borrow", d.h.
es wird eine Subtraktion ausgeführt und zusätzlich das Carry subtrahiertint main() { __asm { // mov ax, 800 ; // AX=320h; AL=20h mov cl, 34 ; // CL=22h; sub al, cl ; // AL=FEh=-2; Flags: OV=0 PL=1 ZR=0 AC=1 PE=0 CY=1 sbb ah, 0 ; // AH=02h; Flags: OV=0 PL=0 ZR=0 AC=0 PE=0 CY=0 // AX=2FE=766 } return 0; }
sub
kann verwendet werden, um zwei Operanden zu vergleichensub operandA, operandB
sub operandA, operandB
Aussage | Bedingung |
---|---|
operandA below operandB | CY=1 |
operandA equal operandB | ZR=1 |
operandA above operandB | CY=0 |
Aussage | Bedingung |
---|---|
operandA less operandB | PL ≠ OV |
operandA equal operandB | ZR=1 |
operandA greater operandB | PL = OV |
cmp operandA, operandB
EIP
auf die Zieladresse gesetzt wirdjmp sprungziel
int main() { __asm { mov eax, 3 jmp Important mov eax, 33 Important: mov ecx, 6 add eax, ecx ; // eax = ? } return 0; }
Befehl | Bedeutung | Bedingung für Flags |
---|---|---|
JZ | Spring, wenn null ("jump if zero") | ZR=1 |
JE | Spring, wenn gleich ("jump if equal") | ZR=1 |
JNZ | Spring, wenn nicht null ("jump if not zero") | ZR=0 |
JNE | Spring, wenn nicht gleich ("jump if not equal") | ZR=0 |
Befehl | Bedeutung | Bedingung |
---|---|---|
JB | Spring, wenn niedriger ("jump if below") | CY=1 |
JNAE | Spring, wenn nicht höher oder gleich ("jump if not above or equal") | CY=1 |
JAE | Spring, wenn höher oder gleich ("jump if above or equal") | CY=0 |
JNB | Spring, wenn nicht niedriger ("jump if not below") | CY=0 |
JBE | Spring, wenn niedr. gleich ("jump if below equal") | CY=1 oder ZR=1 |
JNA | Spring, wenn nicht höher ("jump if not above") | CY=1 oder ZR=1 |
JA | Spring, wenn höher ("jump if above") | CY=0 und ZR=0 |
JNBE | Spring, wenn nicht niedriger oder gleich ("jump if not below or equal") | CY=0 und ZR=0 |
Befehl | Bedeutung | Bedingung für Flags |
---|---|---|
JG | Spring, wenn größer ("jump if greater") | ZR=0 und PL = OV |
JNLE | Spring, wenn nicht kleiner oder gleich ("jump if not less or equal") | ZR=0 und PL = OV |
JLE | Spring, wenn kleiner oder gleich ("jump if less or equal") | ZR=1 oder PL ≠ OV |
JNG | Spring, wenn nicht größer ("jump if not greater") | ZR=1 oder PL ≠ OV |
JL | Spring, wenn kleiner ("jump if less") | PL ≠ OV |
JNGE | Spring, wenn nicht größer oder gleich ("jump if not greater or equal") | PL ≠ OV |
JGE | Spring, wenn größer oder gleich ("jump if greater or equal") | PL = OV |
JNL | Spring, wenn nicht kleiner ("jump if not less") | PL = OV |
Befehl | Bedeutung | Bedingung |
---|---|---|
JC | Spring, wenn Carry gesetzt ("jump if carry") | CY=1 |
JNC | Spring, wenn Carry nicht gesetzt ("jump if not carry") | CY=0 |
JO | Spring, wenn Overflow gesetzt ("jump if overflow") | OV=1 |
JNO | Spring, wenn Overflow nicht gesetzt ("jump if not overflow") | OV=0 |
JS | Spring, wenn Sign gesetzt ("jump if sign") | PL=1 |
JNS | Spring, wenn Sign nicht gesetzt ("jump if not sign") | PL=0 |
Befehl | Bedeutung | Bedingung |
---|---|---|
JCXZ | Spring, wenn CX-Register null ist ("jump if register CX is zero") | CX=0 |
JECXZ | Spring, wenn ECX-Register null ist ("jump if register ECX is zero") | ECX=0 |
LOOP | Dekrementiere (E)CX; springe, wenn (E)CX nicht null ("decrement (E)CX; jump if (E)CX not zero") | (E)CX≠0 |
#include <stdio.h> unsigned int smallGauss(unsigned int varA) { // version 1 __asm { mov eax, 0 mov ecx, varA cmp ecx, 0 ExecuteLoop: jz EndLoop add eax, ecx sub ecx, 1 jmp ExecuteLoop; EndLoop: } } int main() { unsigned int n = 5; unsigned int result = smallGauss(n); // call C-function "smallGauss" printf( "smallGauss(%d) = %d\n", n, result); // output result to console return 0; }Quelldatei: main.cpp
inc
und dec
dienen zum Inkrementieren
bzw. Dekrementieren eines Speicher- oder Registerinhaltes um 1smallGauss
angepasst, ergibt sich:
unsigned int smallGauss(unsigned int varA) { // version 2 __asm { mov eax, 0 mov ecx, varA cmp ecx, 0 ExecuteLoop: jz EndLoop add eax, ecx dec ecx jmp ExecuteLoop; EndLoop: } }Quelldatei: main.cpp
inc
und dec
beeinflussen die Flags: OV
,PL
,ZR
,AC
und
PE
add ziel, 1setzt genau dann das Carry-Flag, wenn das Ergebnis null ist und dementsprechend das Zero-Flag gesetzt wird (z.B. bei einem 8-Bit-Register für ziel=FFh)
sub ziel, 1wird genau dann das Carry-Flag gesetzt, wenn vorher ziel=0 war. Auch dies ist leicht zu prüfen, so dass auf das Carry-Flag verzichtet werden kann
loop
wurde bereits bei den bedingten Sprüngen erwähntloop ziel
ziel
eine 16-Bit Adresse, wird das CX- und bei 32-Bit das ECX-Register betrachtetsmallGauss
kann somit nochmal verbessert werden: (main.cpp)
unsigned int smallGauss(unsigned int varA) { // version 3 __asm { mov eax, 0 mov ecx, varA jecxz EndLoop ExecuteLoop: add eax, ecx loop ExecuteLoop EndLoop: } }
mul
führt eine Multiplikation für vorzeichenlose Zahlen ausop ziel, quelleabgewichen, da das Ergebnis im Allgemeinen nicht in ein Register passt
mul quelle
quelle
ab:
Bitbreite | Ziel | Operation |
---|---|---|
8 | AX | AX = AL * quelle |
16 | DX:AX | DX:AX = AX * quelle |
32 | EDX:EAX | EDX:EAX = EAX * quelle |
quelle
werden Carry- und Overflow-Flag
gesetztint main() { __asm { mov cl, 16 ; // CL=10h (8-bit register) mov al, 8 ; // AL=08h mul cl ; // AX=0080h=128 Flags: OV=0, CY=0 mov cx, 4000h ; // CX=4000h (16-bit register) mov ax, 5000h ; // AX=5000h mul cx ; // DX:AX= 1400:0000 Flags: OV=1, CY=1 mov ecx, 7FFFFFFFh ; // ECX=7FFFFFFFh (32-bit register) mov eax, 4 ; // EAX=00000004h mul ecx ; // EDX:EAX=00000001:FFFFFFFC Flags: OV=1, CY=1 } return 0; }Quelldatei: main.cpp
div
führt eine Division aus
div quelle
quelle
angegebenquelle
:
Bitbreite | Dividend | Ganzzahliges Ergebnis | Rest |
---|---|---|---|
8 | AX | AL = AX / quelle | AH = AX mod quelle |
16 | DX:AX | AX = DX:AX / quelle | DX = DX:AX mod quelle |
32 | EDX:EAX | EAX = EDX:EAX / quelle | EDX = EDX:EAX mod quelle |
int main() { __asm { mov cx, 4000h ; // CX=4000h (16-bit register) mov ax, 5000h ; // AX=5000h mul cx ; // DX:AX=1400:0000 Flags: OV=1, CY=1 div cx ; // AX=5000h DX=0000h mov dx, 0000h ; mov ax, 0002h ; // DX:AX=0000:0002h mov cx, 10h ; // CX=10h div cx ; // AX=0000h DX=0002h mov dx, 7FFFh ; mov ax, 0000h ; // DX:AX=7FFF:0000h mov cx, 2h ; // CX=2h div cx ; // result does not fit in AX, throws divide error exception } return 0; }Quelldatei: main.cpp
unsigned int ggT_C(unsigned int a, unsigned int b) { unsigned int res = 0; while(b != 0) { // while b not zero res = (a % b); // res = (a mod b) a = b; b = res; } return a; }
unsigned int ggT_Asm(unsigned int a, unsigned int b) { __asm { mov edx, 0 ; mov eax, a ; // EDX:EAX = a mov ecx, b ; // ECX = b WhileLoop: cmp ecx, 0 ; jz EndLoop ; // jump to "done" if ECX == 0 div ecx ; mov eax, ecx ; // EAX = ECX mov ecx, edx ; // ECX = (a mod b) mov edx, 0 ; // EDX = 0 for next "div" command jmp WhileLoop ; EndLoop: } }Quelldatei: main.cpp
IMUL
führt eine Multiplikation von vorzeichenbehafteten Zahlen ausimul quelle
quelle
und ziel
wird in ziel
gespeichert
imul ziel quelle
operandA
und konstante
wird in ziel
gespeichert
imul ziel operandA konstante
ziel
passen sollten. Carry- und Overflow-Flag werden in diesem Fall gesetzt#include <stdio.h> int main() { int result = 0; __asm { mov eax, -2 mov ecx, 800 imul ecx mov result, eax // EDX is ignored here } printf("result=%d \n", result); __asm { mov eax, -2 mov ecx, 800 imul eax, ecx mov result, eax } printf("result=%d \n", result); __asm { mov ecx, 800 imul eax, ecx, -2 mov result, eax } printf("result=%d \n", result); return 0; }
IDIV
führt eine Division von vorzeichenbehafteten Zahlen ausDIV
verwendet
#include <stdio.h> int main() { int result = 0; int remainder = 0; __asm { mov edx, 0 mov eax, 800 mov ecx, -3 idiv ecx mov result, eax mov remainder, edx } printf("result=%d \n", result); printf("remainder=%d \n", remainder); return 0; }Quelldatei: main.cpp
neg
ändert das Vorzeichen einer vorzeichenbehafteten Zahlint main() { __asm { mov eax, -2 ; // EAX=FFFFFFFEh=-2 neg eax ; // EAX=00000002h= 2 mov al, 254 ; // AL=FEh=-2 neg al ; // AL=02h= 2 } }Quelldatei: main.cpp
and
, or
, und not
führen
elementare logische Grundoperationen aus, wie diese aus der booleschen Algebra bekannt sind$a$ | $b$ | $y = a \land b$ |
0 | 0 | 0 |
0 | 1 | 0 |
1 | 0 | 0 |
1 | 1 | 1 |
$a$ | $b$ | $y = a \lor b$ |
0 | 0 | 0 |
0 | 1 | 1 |
1 | 0 | 1 |
1 | 1 | 1 |
$a$ | $y = \lnot a$ |
0 | 1 |
1 | 0 |
CY
und Overflow-Flag OF
werden auf null gesetzt. Die Flags PL
, ZR
und PE
werden gemäß
des Ergebnisses gesetzt. Das Aux. Carry AC
wird nicht beeinflusst.int main() { unsigned int a = 0x000078F1; unsigned int b = 0x00007F8F; __asm { mov eax, a ; // EAX=000078F1h not eax ; // EAX=FFFF870Eh and eax, b ; // EAX=0000070Eh mov edx, b ; // EDX=0000070Eh not edx ; // EDX=FFFF8070h and edx, a ; // EDX=00000070h or eax, edx ; // EAX=0000077Eh } return 0; }
int main() { unsigned int a = 0x000078F1; unsigned int b = 0x00007F8F; __asm { mov eax, a ; // EAX=000078F1h not eax ; // EAX=FFFF870Eh and eax, b ; // EAX=0000070Eh mov edx, b ; // EDX=0000070Eh not edx ; // EDX=FFFF8070h and edx, a ; // EDX=00000070h or eax, edx ; // EAX=0000077Eh } // simple alternative __asm { mov eax, a ; // EAX=000078F1h xor eax, b ; // EAX=0000077Eh } return 0; }Quelldatei: main.cpp
shl
("Shift logical left") und shr
("Shift logical right") schieben
das Ziel um die angegeben Anzahl an Bits nach links bzw. rechts
shl ziel, anzahl shr ziel, anzahl
sal
("Shift arithmetic left") und sar
("Shift arithmetic right") entsprechen
den Befehlen shl
und shr
. Der einzige Unterschied ist, dass
bei sar
statt einer 0 eine 1 hineingeschoben wirdxchg
("exchange") tauscht den Inhalt der beiden Operanden aus
int main() { __asm { mov eax, 1 ; // EAX=1 mov edx, 2 ; // EDX=2 xchg eax, edx ; // EDX=1, EAX=2 } return 0; }Quelldatei: main.cpp
bt
, bts
, btr
und btc
, kopieren das
durch bitIndex
indizierte Bit ins Carry-Flag und modifizieren dieses Bit in ziel
entsprechend der Semantik der Mnemonik
bt ziel, bitIndex
Befehl | Wirkung auf das Carry cy | Wirkung auf das indizierte Bit |
---|---|---|
bt ("bit test") | cy=ziel[bitIndex] | ziel[bitIndex] unbeeinflusst |
bts ("bit test and set") | cy=ziel[bitIndex] | ziel[bitIndex]=1 |
btr ("bit test and reset") | cy=ziel[bitIndex] | ziel[bitIndex]=0 |
btc ("bit test and complement)") | cy=ziel[bitIndex] | ziel[bitIndex] = not(ziel[bitIndex]) |
clc
("clear carry") und stc
("set carry") löschen bzw. setzen das Carry-Flagint main() { __asm { stc ; // CY=1 clc ; // CY=0 mov ax, 00FFh ; // AX=00FFh bt ax, 0 ; // CY=1 bt ax, 7 ; // CY=1 bt ax, 8 ; // CY=0 bts ax, 8 ; // CY=0, AX=01FFh } return 0; }Quelldatei: main.cpp
nop
("no operation") führt keine Operation ausadd
(Seite 3-31 der
Befehlsreferenz):
r8
, r16
, r32
Operand ist eine 8-, 16-, bzw. 32-Bit-Mehrzweckregisterm8
, m16
, m32
Operand ist eine Speicheradresse (engl. "memory")m/r8
, m/r16
, m/r32
Operand ist ein Register oder eine Speicheradresseimm8
, imm16
, imm32
Operand ist eine konstante vorzeichenbehaftete Zahl (engl. "immediate value")Assemblerbefehl | Beschreibung |
---|---|
ADC ziel, quelle | Addiere mit Übertrag aus vorangegangener Addition |
ADD ziel, quelle | ziel = ziel + quelle |
AND ziel, quelle | Logische Und-Verknüpfung von ziel und quelle |
CMP x, y | Vergleiche x und y |
DEC x | Dekrementiere x |
DIV op | Teile durch op |
IDIV op | Vorzeichenbehaftete, ganzzahlige Division |
IMUL op | Vorzeichenbehaftete, ganzzahlige Multiplikation |
INC x | Inkrementiere x |
JA sprungziel | Springe, wenn größer |
JAE sprungziel | Springe, wenn größer oder gleich |
JB sprungziel | Springe, wenn kleiner |
JBE sprungziel | Springe, wenn kleiner oder gleich |
JECXZ sprungziel | Springe, wenn ECX gleich 0 |
JE sprungziel | Springe, wenn gleich |
JMP sprungziel | Unbedingter Sprung |
Assemblerbefehl | Beschreibung |
---|---|
JO sprungziel | Springe, wenn Überlauf |
JZ sprungziel | Springe, wenn gleich 0 |
LOOP sprungziel | Dekrementiere ECX , springe falls ECX ungleich 0 |
MOV ziel, quelle | Kopiere quelle nach ziel |
MUL op | Multipliziere mit op |
NEG ziel | Negiere Wert in ziel mit Zweierkomplement |
NOT ziel | Logische Negation von ziel |
OR ziel, quelle | Logische Oder-Verknüpfung von ziel und quelle |
POP ziel | Hole obersten Wert vom Stack |
PUSH quelle | Lege Wert aus quelle auf Stack |
SAL ziel, schrittzahl | Arithmetische, bitweise Verschiebung nach links |
SAR ziel, schrittzahl | Arithmetische, bitweise Verschiebung nach rechts |
SHL ziel, schrittzahl | Logische, bitweise Verschiebung nach links |
SHR ziel, schrittzahl | Logische, bitweise Verschiebung nach rechts |
SUB ziel, quelle | ziel = ziel - quelle |
XOR ziel, quelle | Logische XOR-Verknüpfung von ziel und quelle |
Anregungen oder Verbesserungsvorschläge können auch gerne per E-mail an mich gesendet werden: Kontakt