IT rekvalifikácia. Seniorní programátori zarábajú až 6 000 €/mesiac a rekvalifikácia je prvým krokom. Zisti, ako na to!

11. diel - Assembler - Registre procesora

V minulej lekcii, Assembler - Kombinácia skokov a príznaky , sme sa naučili kombinovať podmienené a nepodmienené skoky, zistili, ako skokové inštrukcie získajú výsledok z CMP a ako porovnávať signed čísla.

V dnešnom ASM tutoriále si ukážeme skoro všetky registre procesorov x86 a x64.

Na registre sme už v našom assembler kurze narazili a vieme, že sú to "premenné", napevno vytvorené priamo v procesore. Sú veľmi rýchle, pretože sa ušetrí cesta medzi procesorom a pamäťou RAM. V miniatúrnom procesora je samozrejme tiež veľmi obmedzené miesto, preto je registrov vytvorených len obmedzené množstvo a majú špecifické určenia. Registre sa tiež výrazne líši podľa architektúry procesora.

V dnešnom ASM tutoriálu si skoro celé registre CPU konečne zmapujeme. Na začiatku kurzu by to pre nás boli príliš vyčerpávajúce informácie, teraz je už však dokážeme využiť.

Všeobecné registre

Pri programovaní najčastejšie pracujeme so všeobecnými registrami (anglicky general-purpose). Do nich možno ukladať celé čísla a alebo adresy (ukazovatele do pamäte). Používajú sa pri výpočtoch, na ukladanie dočasných hodnôt alebo lokálnych premenných.

16-bitové

V ére MS-DOS a Windows 3.X boli registre iba 16-bitové. To komplikovalo nielen výpočty s väčšími číslami, ale hlavne prístupy do pamäti, pretože 64 KB čoskoro prestalo aplikáciám stačiť. V procesora je týchto 8 všeobecných registrov:

  • AX - akumulátor (akumulačné register)
  • BX - bázový register
  • CX - čítač (counter)
  • DX - dátový register
  • SI - index pre zdroj (Source Index)
  • DI - index pre cieľ (Destination Index)
  • BP - ukazovateľ na záznam aktívny procedúry na zásobníku (Base Pointer)
  • SP - ukazovateľ vrcholu zásobníka (Stack Pointer)

Registre BP a SP sa používajú pri volaní funkcií. Ostatné registre sú naozaj všeobecné a môžeme si do nich ukladať, čo chceme. Ich pomenovanie potom slúži k lepšej orientácii v kóde, napr. Do AX uložíme výsledok nejaké aritmetické operácie a do CX budeme ukladať počítadlo cyklu.

S registre AX, BX, CX, DX môžeme pracovať tiež tak, že si ich rozdelíme na dva menšie osembitové registre. Hornej polovice sa označujú AH, BH, CH, DH (High). Dolnej polovice sú potom AL, BL, CL, DL (Low).

Nasledujúci príklad ukazuje, ktorá časť registra AX sa zmení, ak zapíšeme hodnotu do AH alebo AL:

mov ax, 1122h  ;ax=1122h
mov al, 33h    ;ax=1133h
mov ah, 44h    ;ax=4433h

32-bitové

Dostávame sa do čias Windows 95 - XP. Pri rozšírení všetkých 16-bitových registrov na 32-bitové bol k názvu pridaný prefix E (Extended) - EAX, EBX, ECX atď. Do týchto registrov potom môžeme uložiť väčšie čísla. V počítači môžeme mať až 4 GB pamäte.

Keď v 32-bitovej aplikáciu zapíšeme hodnotu do 16-bitového registra, potom sa zmení dolných 16 bitov z 32-bitového registra, zatiaľ čo horných 16 bitov sa nezmení. Ukážme si príklad:

mov eax,12345678h ;eax=12345678h
mov ax,99aah      ;eax=123499aah
mov al,bbh        ;eax=123499bbh
mov ax,cch        ;eax=123400cch

64-bitové

Dostávame sa k súčasným procesorom. V 64-bitových aplikáciách máme dvakrát viac všeobecných registrov.

Rozšírenie pôvodných registrov

Pôvodných 8 registrov bolo rozšírené a majú prefix R - RAX, RBX atď.

Nové registre

K tomu pribudli registre R8R15. K tým možno pridať sufixy D, W a B pre prístup k nižším 32, 16 a 8 bitom. Napr. R8D, R8W, R8B.

V 32-bitových aplikáciách sme mali často nedostatok registrov a lokálne premenné sme museli ukladať do pamäte, čo bolo pomalé. V 64-bitových aplikáciách máme také množstvo registrov, že sa do nich zmestí väčšina lokálnych premenných a odovzdávajú sa v nich aj parametre funkcií.

Nasledujúci príklad ukazuje, ako sa mení register RAX, ak zapisujeme hodnoty do AH, AL, AX, EAX:

mov rax,1111222233334444h ;rax=1111222233334444h
mov ah,55h                ;rax=1111222233335544h
mov al,66h                ;rax=1111222233335566h
mov ax,7777h              ;rax=1111222233337777h
mov eax,88888888h         ;rax=0000000088888888h
mov eax,-1                ;rax=00000000ffffffffh

Všimnite si, že pri zápise 8-bitové alebo 16-bitové hodnoty sa vyššia bajty registra nemení. Ale pri zapísanie 32-bitové hodnoty sa ostatní bajty vynulujú. To môžeme využívať na optimalizáciu. Ak chceme do 64-bitového registra uložiť malé nezáporné číslo, môžeme použiť 32-bitový register.

X87 registre

Pri výpočtoch s reálnymi číslami sa používajú 80-bitové registre ST(0)ST(7). K nim možno pristupovať ako k zásobníku. To znamená, že pri výpočtoch sa môžeme odkazovať na konkrétne registre, ale často nám stačí len pridávať čísla na vrchol zásobníka a vykonávať s nimi matematické operácie.

MMX registre

Registre MM0MM7 sú synonymá pre ST(0)ST(7), ale používajú sa k výpočtom s celými číslami. V dnešnej dobe už nemá zmysel ich používať, pretože SSE je lepšie, viď ďalej.

SSE registre

Do šestnástich 128-bitových registrov XMM0XMM15 môžeme ukladať reálne aj celé čísla. Do každého registra sa zmestí viac čísel naraz (dve 64-bitová čísla alebo štyri 32-bitová). Raz inštrukcií tak možno vykonať operáciu s niekoľkými hodnotami naraz. To sa nazýva SIMD (Single Instruction, Multiple Data). Tejto technológie využijeme pri práci s vektormi alebo spracovanie veľkých dát. Získame tým samozrejme vyšší výkon. Vo 32-bitových aplikáciách je prístupná len polovica registrov (XMM0XMM7).

Okrem dátových registrov existuje ešte stavový a riadiaci register MXCSR.

AVX registre

Novšie procesory majú SSE registre rozšírené na 256 bitov a nazývajú sa YMM0YMM15. Ešte novšie procesory majú 512-bitové registre ZMM0ZMM15 a navyše opmask registre K0K7.

Príznaky - Register EFLAGS

O príznakoch sme si už hovorili v lekcii Assembler - Kombinácia skokov a príznaky. Môžu mať hodnotu buď 0 alebo 1 a označujú nejakú situáciu, ku ktorej pri vykonávaní inštrukcií došlo. Môžeme je nasledujúci inštrukcií prečítať a na stav programu reagovať.

Register EFLAGS teda obsahuje niekoľko jednobitových hodnôt. Niektoré z nich nemôžeme sami v aplikácii meniť a má k nim prístup len operačný systém. Pre nás sú najdôležitejšie aritmetické príznaky CF, ZF, SF a OF, ktoré sme si už popísali.

Dnes si ukážme úplnejší zoznam:

  • 0. CF (Carry) - aritmetické pretečenie s číslami bez znamienka, alebo pri bitových posuvoch a rotáciách
  • 2. PF (Parity) - párne parita, dolná osmice bitov výsledku obsahuje párny počet jednotiek
  • 4. AF (Auxiliary Carry) - pretečeniu medzi 3. a 4. bitom pri BCD aritmetike
  • 6. ZF (Zero) - nulový výsledok
  • 7. SF (Sign) - záporný výsledok
  • 8. TF (Trap) - krokovanie po inštrukciách pri ladení
  • 9. IF (Interruption) - povolená hardvérová prerušenia
  • 10. DF (Direction) - reťazcové inštrukcie v opačnom smere (napr. MOVSB znižuje SI, DI)
  • 11. OF (Overflow) - aritmetické pretečenie s číslami so znamienkom
  • 12-13. IOPL (I / O Privilege Level) - úroveň povolení pre inštrukcie IN / OUT
  • 14. NT (Nested Task) - inštrukcie IRET pri návrate z prerušenia prepne na ďalší proces
  • 16. RF (Resume) - maskuje opakovanie ladiaceho prerušenia
  • 17. VM (Virtual-8086 Mode) - virtualizácia 16-bitových aplikácií v 32-bitovom operačnom systéme
  • 18. AC (Alignment Check) - kontrola zarovnanie, vyvolá prerušenie pri prístupe na adresu, ktorá nie je deliteľné dĺžkou hodnoty
  • 19. VIF (Virtual Interrupt) - príznak IF pri virtualizácii
  • 20. VIP (Virtual Interrupt Pending) - bolo vyvolané prerušenia pri virtualizácii
  • 21. ID (Identification) - ak sa dá nastaviť, je podporovaná inštrukcie CPUID

Segmentové registre

Segmenty sa používali v 16-bitových aplikáciách. Pamäť bola rozdelená na segmenty o veľkostiach 64 KB:

  • CS - segment kódu
  • DS - dátový segment
  • ES - extra segment
  • FS - ďalšie extra segment
  • GS - ďalšie extra segment
  • SS - segment zásobníka (stack)

Ak aplikácia potrebovala viac pamäte, musela si segmenty prepínať. Vo 32-bitových aplikáciách sú segmenty úplne zbytočné, pretože aplikácia môže pristupovať až k 4 GB pamäte. V 64-bitových aplikáciách potom boli úplne zrušené segmenty CS, DS, ES, SS. Zostali iba segmenty FS a GS, pretože operačné systémy ich používajú na ukladanie dát pre bežiaci vlákno (thread local storage) alebo k informáciám o výnimkách (exceptions).

Register IP

Instruction Pointer ukazuje na práve vykonávanú inštrukciu. Hodnotu tohto registra meníme napríklad inštrukciami skoku (JMP, CALL a RET). V 64-bitových aplikáciách môžeme používať register RIP k relatívnemu adresovanie.

Debug registre

Pri ladení môžeme nastavovať až 4 dátové hraničnými na premenné. Program sa potom zastaví, keď sa premenná zmení. V registroch DR0, DR1, DR2, DR3 sú adresy Breakpoint. Podľa stavového registra DR6 sa určí, ktorý z tých 4 Breakpoint bol vyvolaný. V kontrolnom registra DR7 sa nastavuje, ktoré hraničnými sú aktívne, či sú pre zápis alebo pre čítanie a koľko bajtov premenná zaberá.

Kontrolné registre

Registre CR0, CR2, CR3, CR4, CR8 používa operačný systém pri virtualizácii, stránkovanie, nastavenie zabezpečenia alebo prepínanie rôznych režimov procesora. Ich význam je nad rámec tejto lekcie.

V budúcej lekcii, Funkcie v MASM , budeme vytvárať funkcie s parametrami a lokálnymi premennými.


 

Predchádzajúci článok
Assembler - Kombinácia skokov a príznaky
Všetky články v sekcii
Základy assembleri
Preskočiť článok
(neodporúčame)
Funkcie v MASM
Článok pre vás napísal Petr Laštovička
Avatar
Užívateľské hodnotenie:
Ešte nikto nehodnotil, buď prvý!
Autor se věnuje vývoji webových aplikací v ASP.NET a aplikací pro Windows v C++ nebo C#.
Aktivity