Po co nam assembler?
Czy znajomość asemblera jest potrzebna?

Zalety assemblera

Zastosowania asemblera

Myśleć niskopoziomowo, pisać wysokopoziomowo.


Literatura
Historia 80x86
Historia 80x86


Rejestry
Przykładowe operacje na rejestrach
MOV AX, 89            ; prześlij do rejestru AX liczbę 89
MOV DX, 10            ; prześlij do rejestru DX liczbę 10
ADD AX, DX            ; dodaj 89 i 10, a wynik prześlij do AX

Przykładowy rejestr RAX

|--------------------------RAX------------------------------------|
|                               |------------EAX------------------|
|                               |                |-------AX-------|

00000000000000000000000000000000|0000000000000000|00000000|00000000

                                                 |   AH   |  AL   |


Rejestry ogólnego użytku

GPR = General Purpose Registers


Opreacje arytmetyczne

 
Name    Comment                     Syntax
ADD     Add                         ADD Dest,Source
ADC     Add with Carry              ADC Dest,Source
SUB     Subtract                    SUB Dest,Source
SBB     Subtract with borrow        SBB Dest,Source
DIV     Divide (unsigned)           DIV Op
IDIV    Signed Integer Divide       IDIV Op
MUL     Multiply (unsigned)         MUL Op
IMUL    Signed Integer Multiply     IMUL Op
INC     Increment                   INC Op
DEC     Decrement                   DEC Op
 
CMP     Compare                     CMP Op1,Op2
 
SAL     Shift arithmetic left       SAL Op,Quantity
SAR     Shift arithmetic right      SAR Op,Quantity
RCL     Rotate left through Carry   RCL Op,Quantity
RCR     Rotate right through Carry  RCR Op,Quantity
ROL     Rotate left                 ROL Op,Quantity
ROR     Rotate right                ROR Op,Quantity


Mnożenie
Zestawy parametrów i wyniki instrukcji MUL (pierwsze 3 wiersze) i IMUL
 dest  source  source1  Akcja
   reg/mem8    AX = AL*source
   reg/mem16    DX:AX = AX*source
   reg/mem32    EDX:EAX = EAX*source
   reg/mem64    RDX:RAX = RAX*source
 reg16  reg/mem16    dest *= source
 reg32  reg/mem32    dest *= source
 reg16  immed8    dest *= immed8
 reg32  immed8    dest *= immed8
 reg16  immed16    dest *= immed16
 reg32  immed32    dest *= immed32
 reg16  reg/mem16  immed8  dest = source*source1
 reg32   reg/mem32  immed8  dest = source*source1
 reg16  reg/mem16  immed16  dest = source*source1
 reg32   reg/mem32  immed32  dest = source*source1

Przykład mnożenia

mul cl          ; AX = AL*CL
mul bx          ; DX:AX = AX*BX
mul esi         ; EDX:EAX = EAX*ESI
mul rdi         ; RDX:RAX = RAX*RDI
 
imul eax        ; EDX:EAX = EAX*EAX
imul ebx,ecx,2  ; EBX = ECX*2
imul ebx,ecx    ; EBX = EBX*ECX
imul si,5       ; SI = SI*5


Operacje logiczne

LOGIC
 
Name    Comment                 Syntax
NEG     Negate (two-complement) NEG Op
NOT     Invert each bit         NOT Op
AND     Logical and             AND Dest,Source
OR      Logical or              OR Dest,Source
XOR     Logical exclusive or    XOR Dest,Source
SHL     Shift logical left      SHL Op,Quantity
SHR     Shift logical right     SHR Op,Quantity
 
MISCELLANEOUS
 
Name    Comment                 Syntax
NOP     No operation            NOP
LEA     Load effective adress   LEA Dest,Source
INT     Interrupt               INT Nr

Instrukcje sterujące
JMP

Instrukcja skoku bezwarunkowego

jmp etykieta
 ...
 etykieta: 
może generować różne instrukcje maszynowe w zależności od długości skoku.
Przeważnie krótsze skoki generują krótszy kod maszynowy.

short1 bajt-128 ... +128
near2 bajty-32 768 ... +32 768
domyślny 4 bajty-2 147 483 648 ... +2 147 483 648


CMP

Aby porównać wartości całkowitoliczbowe 80x86 dostarcza funkcji

cmp x, y
Funkcja oblicza x - y i ustawia odpowiednie flagi (wynik odejmowania nie jest dostępny).
x = y : ZF = 1

Dla liczb bez znaku

x < y : ZF = 0, CF = 1  ; odejmowanie z pożyczką
x > y : ZF = 0, CF = 0

Dla liczb ze znakiem

x < y : ZF = 0, OF != SF  
x > y : ZF = 0, OF = SF
Sprawdzenie samej flagi znaku nie wystarcza, bo przy przepełnieniu znak jest zmieniony na przeciwny.


TEST

Aby sprawdzić czy dany rejestr np. EAX jest równy zero można użyć instrukcji

test eax, eax
Jest ona szybsza i krótsza od cmp eax, 0

W ogólności

test x, y
wykonuje bitowe and i ustawia flagę ZF w zależności od tego czy wynik jest zerem.


Proste skoki warunkowe

Wykonanie skoku zależy tylko od jednej z flag procesora

;Skok   jeżeli     w ostatniej operacji 
JZ      ZF = 1    ; był wynik 0
JNZ     ZF = 0
 
JO      OF = 1    ; było przepełnienie   
JNO     OF = 0
 
JS      SF = 1    ; wynik był ujemny 
JNS     SF = 0
 
JC      SF = 1    ; przepełnienie lub niedomiar 
JNC     SF = 0    ; dla liczb bez znaku
 
JP      PF = 1    ; najmłodszy bajt ma parzystą liczbę jedynek 
JNP     PF = 0
 


Skoki warunkowe

Bezpośrednio po wykonaniu

cmp x, y
możemy użyć następujących instrukcji skoku warunkowego
liczby ze znakiem      liczby bez znaku       skok jeżeli
JE,  JZ                JE,  JZ                x = y             
JNE, JNZ               JNE, JNZ               x != y         
JL,  JNGE              JB,  JNAE              x < y           
JLE, JNG               JBE, JNA               x <= y
JG,  JNLE              JA,  JNBE              x > y
JGE, JNL               JAE, JNB               x >= y

Instrukcja loop