Lekce 15 - Assembler - Rejstřík instrukcí procesoru
V minulé lekci, Assembler - Registry procesoru, jsme si ukázali skoro všechny registry procesorů x86 a x64.
Procesor má velké množství instrukcí, ve kterých se není snadné vyznat. Proto si dnes ukážeme jejich stručný přehled, abychom měli představu, co všechno procesor dokáže. Ani zdaleka to není kompletní seznam. Jednotlivé instrukce budou podrobněji vysvětleny v dalších lekcích.
Tato lekce slouží k zopakování instrukcí, které již známe, jako ochutnávka instrukcí nových, a jako záchytný bod, ke kterému se můžete kdykoli vrátit a instrukce si zopakovat.
Přesun dat
Pro přesun dat můžeme použít:
MOV
- přiřazení hodnoty do registru, přesun hodnot mezi dvěma registry nebo mezi registrem a pamětíMOVZX
,MOVSX
- přesun a zároveň rozšíření na větší typ, doplnění nulami nebo znaménkemCMOVcc
- podmíněné přiřazeníLEA
- výpočet adresyPUSH
,POP
- uložení a vyzvednutí hodnoty ze zásobníkuPUSHA
,POPA
- uložení všech registrů na zásobníkXCHG
- prohození dvou hodnot
Větvení programu
Následující instrukce souvisejí s větvením programu:
JMP
- nepodmíněný skokJcc
- podmíněný skok (cc je příznak nebo podmínka, např.C
,Z
,G
,LE
)CALL
- volání funkceRET
,RETN
- návrat z funkce a případně také odstranění parametrů ze zásobníkuINT
- vyvolání přerušeníIRET
- návrat z přerušeníSYSCALL
- volání funkce operačního systémuSYSRET
- návrat z funkce operačního systému
Příznaky
S příznaky pracujeme následujícími instrukcemi:
PUSHF
,POPF
- uložení všech příznaků na zásobníkLAHF
,SAHF
- uložení příznakůSF
,ZF
,AF
,PF
,CF
do registruAH
SETcc
- uložení jednoho příznaku do libovolného registru nebo do pamětiCLC
,STC
,CMC
- vynulování, nastavení nebo změnaCF
(Carry)CLD
,STD
- vynulování nebo nastaveníDF
(Direction)
Aritmetické operace
Pro aritmetické operace máme k dispozici instrukce:
ADD
,ADC
,SUB
,SBB
- sčítání, odčítáníINC
,DEC
- zvětšení o jedna, zmenšení o jednaMUL
,IMUL
,DIV
,IDIV
- násobení, dělení, bez znaménka nebo se znaménkemCMP
- porovnáníNEG
- změna znaménkaCBW
,CWD
,CWDE
,CDQ
- konverzeAL
naAX
,AX
naDX:AX
,AX
naEAX
,EAX
naEDX:EAX
XADD
,CMPXCHG
- součet s výměnou, porovnání s výměnou
Logické operace
Nyní si ukažme, jak voláme logické operace:
AND
,OR
,XOR
,NOT
- logický součin, součet, exkluzivní součet, negaceTEST
- podobné jakoAND
, ale pouze nastaví příznaky
Bitové operace
Pracovat můžeme i s jednotlivými bity:
ROL
,ROR
,RCL
,RCR
- rotace vlevo/vpravo, přes příznakCF
SHL
,SHR
,SAL
,SAR
- posuny vlevo/vpravo, logické/aritmetickéSHLD
,SHRD
- posuny přes dva registryBSF
,BSR
- hledání bitu dopředu/dozaduBT
,BTC
,BTR
,BTS
- testování jednoho bitu, se změnou/vynulováním/nastavením
Práce s řetězci
Pomocí instrukcí můžeme pracovat s textovými řetězci:
REP MOVS
- kopie řetězceREPE CMPS
- porovnání dvou řetězcůREPNE SCAS
- vyhledání znaku v řetězci
Výpočty s reálnými čísly
S desetinnými čísly pracujeme těmito instrukcemi:
FLD
,FILD
- načtení reálného nebo celého čísla z pamětiFSTP
,FISTP
- uložení výsledkuFXCH
- prohození dvou registrůFLDZ
,FLD1
,FLDPI
- konstanty0
,1
, PiFADD
,FSUB
,FMUL
,FDIV
,FDIVR
,FSQRT
- sčítání, odčítání, násobení, dělení, inverzní dělení, druhá odmocninaFSIN
,FCOS
,FPTAN
- goniometrické funkceFABS
,FCHS
,FRNDINT
- absolutní hodnota, změna znaménka, zaokrouhleníFCOM
,FCOMI
,FTST
- porovnání
MMX (Multi Media Extension)
MMX instrukce provádějí výpočty s 64-bitovými registry MM0
až MM7
, z nichž každý může obsahovat několik celých
čísel. Pracujeme tedy s několika čísly současně. Tyto registry jsme si
již popsali v lekci Assembler - Registry
procesoru.
Aritmetické instrukce mají suffixy D
, W
,
B
podle toho, jestli počítají se dvěma 32-bitovými čísly,
čtyřmi 16-bitovými čísly, nebo osmi 8-bitovými čísly:
MOVD
,MOVQ
- přesunyPADD
,PADDS
,PADDUS
,PMADD
,PMULH
,PMULL
,PSUB
,PSUBS
,PSUBUS
- aritmetické operacePAND
,PANDN
,POR
,PXOR
- logické operacePCMPEQ
,PCMPGT
- porovnáníPACKSSDW
,PACKSSWB
,PACKUSWB
,PUNPCKH
,PUNPCKL
- konverzePSLL
,PSRA
,PSRL
- bitové posunyEMMS
- přepnutí z MMX na x87 FPU
SSE (Streaming SIMD Extensions)
SSE instrukce provádějí výpočty se 128-bitovými registry
XMM0
až XMM15
. Na rozdíl od MMX mohou obsahovat
nejen celá čísla, ale také reálná čísla.
Poslední písmeno názvu většiny instrukcí je D
nebo
S
podle toho, jestli počítají se dvěma 64-bitovými reálnými
čísly (Double) nebo se čtyřmi 32-bitovými reálnými čísly (Single).
Předposlední písmeno je P
nebo S
podle toho, jestli
se počítá s vektorem (Packed) nebo s jedinou hodnotou (Single):
MOVSS
,MOVAPS
,MOVUPS
,MOVLPS
,MOVHPS
,MOVLHPS
,MOVHLPS
- přesunyADDSS
,SUBSS
,MULSS
,DIVSS
,RCPSS
,MAXSS
,MINSS
,SQRTSS
,RSQRTSS
- aritmetické operaceCMPSS
,COMISS
,UCOMISS
- porovnáníCVTSI2SS
,CVTSS2SI
,CVTTSS2SI
- konverzeSHUFPS
,UNPCKHPS
,UNPCKLPS
- zamíchání
AVX (Advanced Vector eXtensions)
AVX instrukce pracují s 256-bitovými registry
YMM0
-YMM15
nebo s 512-bitovými registry
ZMM0
-ZMM15
. Instrukce jsou podobné jako u SSE, ale
začínají písmenem V
.
Privilegované instrukce
Tyto instrukce může používat jen operační systém:
STI
,CLI
- povolení a zakázání hardwarových přerušeníLIDT
,LGDT
,LLDT
- nastavení adresy tabulky přerušení, globálních segmentů nebo lokálních segmentůIN
,OUT
- vstup a výstup (komunikace s hardwarem)HLT
- zastavení programuINVD
- vymazání cache
Ostatní instrukce
Ukažme si ještě několik dalších užitečných instrukcí:
BOUND
- test jestli je číslo v daném intervaluBSWAP
- konverze mezi little endian a big endianCPUID
- detekce typu procesoruRDTSC
- počítadlo cyklů (Time-Stamp Counter)NOP
- tato instrukce znamená no operation a nedělá vůbec nic
Nepoužívané instrukce
Následující instrukce jsou v procesoru jen kvůli kompatibilitě se staršími aplikacemi.
V dnešní době se prakticky nepoužívají, protože jsou pomalé.
Zde si pouze ukážeme, jakými jinými instrukcemi je můžeme nahradit:
ENTER
-push rbp; mov rbp,rsp; sub rsp,n
LEAVE
-mov rsp,rbp; pop rbp
LOOP
-dec rcx; jnz label
LOOPZ
-jnz label2; dec rcx; jnz label; label2:
LOOPNZ
-jz label2; dec rcx; jnz label; label2:
XLATB
-mov al,[rbx+rax]
LODSB
-mov al,[rsi]; lea rsi,[rsi+1]
LODSW
-mov ax,[rsi]; lea rsi,[rsi+2]
LODSD
-mov eax,[rsi]; lea rsi,[rsi+4]
LODSQ
-mov rax,[rsi]; lea rsi,[rsi+8]
STOSB
-mov [rdi],al; lea rdi,[rdi+1]
STOSW
-mov [rdi],ax; lea rdi,[rdi+2]
STOSD
-mov [rdi],eax; lea rdi,[rdi+4]
STOSQ
-mov [rdi],rax; lea rdi,[rdi+8]
BCD aritmetika
Zkratka BCD (Binary Coded Decimal) znamená binární kódování
čísel v desítkové soustavě. Ve formátu packed
jsou v každém bajtu dvě číslice. Ve formátu ASCII neboli
unpacked je v každém bajtu pouze jedna číslice (buď hodnota 0
až 9
, nebo hodnoty 30h
až 39h
, což v
ASCII tabulce náleží znakům '0'
až '9'
).
Tyto instrukce v dnešní době nikdo nepoužívá. Prvních šest z nich už dokonce ani nefungují v 64-bitových aplikacích (způsobují výjimku illegal instruction).
Instrukce jsou:
DAA
(Decimal Adjust after Addition) - použije se po instrukciADD
ve formátu packedDAS
(Decimal Adjust after Subtraction) - použije se po instrukciSUB
ve formátu packedAAA
(ASCII Adjust after Addition) - použije se po instrukciADD
ve formátu unpackedAAS
(ASCII Adjust after Subtraction) - použije se po instrukciSUB
ve formátu unpackedAAM
(ASCII Adjust for Multiplication) - použije se po instrukciMUL
ve formátu unpacked, ale je možné takto vynásobit pouze jednociferná číslaAAD
(ASCII Adjust before Division) - použije se před instrukcíDIV
ve formátu unpacked, ale operandy musí být menší než 100FBLD
- z paměti načte10
bajtů, které obsahují 18 číslic. V posledním bajtu je v nejvyšším bitu znaménko. Hodnotu uloží do FPU registruST(0)
.FBSTP
- reálné číslo z registruST(0)
zaokrouhlí a do paměti zapíše10
bajtů ve stejném formátu jako instrukceFBLD
V příští lekci, Funkce v MASM, budeme vytvářet funkce s parametry a lokálními proměnnými.