Programowanie Niskopoziomowe Wykład 10: Arytmetyka całkowitoliczbowa Dr inż. Marek Mika Państwowa Wyższa Szkoła Zawodowa im. Jana Amosa Komeńskiego W Lesznie
Plan Wprowadzenie Instrukcje przesunięcia bitowego Zastosowania instrukcji przesunięcia bitowego Instrukcje mnożenia i dzielenia
Wprowadzenie Operacje przesunięcia bitowego i rotacji użyteczne w sterowaniu urządzeń we/wy, szyfrowaniu danych, implementacji szybkiej grafiki i niektórych przypadkach mnożenia i dzielenia Mnożenie i dzielenie całkowitoliczbowe z podziałem na operacje na liczbach ze znakiem i bez znaku z punktu widzenia języków wysokiego poziomu i optymalizacji kodu maszynowego Operacje arytmetyczne na wielkich liczbach Operacje wykonywane na spakowanych i niespakowanych liczbach dziesiętnych
Instrukcje przesunięcia bitowego i rotacji SHL (SHift Left) przesunięcie bitowe w lewo SHR (SHift Right) przesunięcie bitowe w prawo SAL (SHift Arithmetic Left) arytmetyczne przesunięcie w lewo SAR (SHift Arithmetic Right) arytmetyczne przesunięcie w prawo ROL (ROtate Left) rotacja w lewo ROR (ROtate Right) rotacja w prawo RCL (Rotate Carry Left) rotacja w lewo z przeniesieniem RCR (Rotate Carry Right) rotacja w prawo z przeniesieniem SHLD (SHift Left Double) przesunięcie w lewo z podwójną precyzją SHRD (SHift Right Double) przesunięcie w prawo z podwójną precyzją
Przesunięcie logiczne a przesunięcie arytmetyczne Przesunięcie logiczne nowa pozycja wypełniana zerem, ostatni bit przesuwany do CF Przesunięcie arytmetyczne nowa pozycja uzupełniana bitem znaku (przy przesunięciu w prawo), ostatni bit przesuwany do CF
SHL Logiczne przesunięcie bitowe w lewo najmłodszy bit uzupełniony zerem najstarszy bit przeniesiony do CF poprzednia zawartość CF usuwana pozostałe bity przesuwane w lewo Składnia: SHL cel, licznik cel liczba (zawartość rejestru lub pamięci) licznik liczba bitów, o które ma być wykonane przesunięcie Typowe wywołania: SHL reg, imm8 SHL mem, imm8 SHL reg, CL SHL mem, CL
Przykłady i zastosowania SHL Przykład mov bl, 87h ; BL = 10001111 shl bl, 1 ; CF = 1, BL = 00011110 Wielokrotne przesunięcie mov al, 10000000b shl al, 2 ; CF = 0, AL = 00000000 Mnożenie bitowe mnożenie przez potęgi dwójki 2 licznik mov dl, 10 ; DL = 00001010 = 10 shl dl, 2 ; DL = DL*4 = 00101000 = 40
SHR Logiczne przesunięcie bitowe w prawo najstarszy bit uzupełniony zerem najmłodszy bit przeniesiony do CF poprzednie zawartość CF usuwana pozostałe bity przesuwane w prawo Składnia i typowe wywołania jak w SHL Przykład: mov al, 0D0h ; AL = 11010000 shr al, 1 ; AL = 01101000, CF = 0 Wielokrotne przesunięcie mov al, 00000010b shr al, 2 ; AL = 00000000, CF = 1 Dzielenie bitowe dzielenie przez potęgę dwójki 2 licznik mov al, 0100000b ; AL = 64 shr al, 3 ; dzielenie przez 8, AL= 00001000 = 8
SAL i SAR SAL działa identycznie jak SHL SAR działa jak SHR, ale najstarszy bit jest uzupełniany bitem znaku Składnia i typowe wywołania jak dla SHL i SHR Przykład dla SAR: mov al, 0Fh ; AL = 11110000 = -16 sar al, 1 ; AL = 11111000 = -8 Dzielenie binarne ze znakiem mov dl, -128 ; DL= 10000000 = -128 sar dl, 3 ; AL = 11110000 = -16 Rozszerzenie znakiem AX do EAX mov ax, -128 ; EAX =????FF80h shl eax, 16 ; EAX = FF800000h sar eax, 16 ; EAX = FFFFFF80h
ROL Rotacja bitowa w lewo najmłodszy bit zastępowany najstarszym bitem najstarszy bit skopiowany do CF poprzednia zawartość CF usuwana pozostałe bity przesuwane w lewo Składnia i typowe wywołania jak dla SHL Wielokrotna rotacja (licznik > 1) CF zawiera ostatni bit przesuwany z pozycji MSB Zamiana miejscami grup bitów wielokrotna rotacja z wartością licznika odpowiadającą rozmiarowi grupy bitów np. zamiana zawartości AH i AL mov ax, 1234h ; AH = 12, AL = 34 rol ax, 8 ; AH = 34, AL = 12
ROR Rotacja bitowa w prawo najstarszy bit zastępowany najmłodszym bitem najmłodszy bit skopiowany do CF poprzednia zawartość CF usuwana pozostałe bity przesuwane w prawo Składnia i typowe wywołania jak dla SHL Wielokrotna rotacja (licznik > 1) CF zawiera ostatni bit przesuwany z pozycji LSB
RCL i RCR Rotacja bitowa w lewo (prawo) przez CF najmłodszy (najstarszy) bit przesuwany do CF poprzednia zawartość CF przesuwana na pozycję najstarszego (najmłodszego) bitu pozostałe bity przesuwane w lewo (prawo) RCL i RCR mogą posłużyć do odzyskania bitu przeniesionego poprzednio do CF instrukcją SHL lub SHR
Znacznik OF przy operacjach przesunięcia i rotacji bitowej Znacznik OF jest ustawiany jeśli: w wyniku instrukcji przesunięcia bitowego lub rotacji bitowej nastąpiła zmiana znaku (zmiana wartości MSB) licznik = 1 Znacznik OF jest niezdefiniowana, gdy: licznik >1
SHLD i SHRD Składnia SHLD: SHLD cel, źródło, licznik Działanie SHLD: najstarszy bit przeniesiony do CF poprzednia zawartość CF usuwana pozostałe bity przesuwane w lewo najmłodszy bit uzupełniany najstarszym bitem źródła Typowe wywołania: SHLD reg16, reg16, CL/imm8 SHLD mem16, reg16, CL/imm8 SHLD reg32, reg32, CL/imm8 SHLD mem32, reg32, CL/imm8 Podobnie dla SHRD
SHLD i SHRD przykłady i zastosowania Przykład: mov mov ax, 234Bh dx, 7654h shrd ax,dx,4 ; AX = 4234h Zastosowania manipulowanie obrazami bitmapowymi (przy przesuwaniu obrazu na ekranie) szyfrowanie danych szybkie mnożenie i dzielenie binarne dużych liczb przesuwanie elementów tablicy
Mnożenie binarne Jak mnożyć przez liczbę nie będącą potęgą dwójki? Mnożnik rozbić na sumę potęg dwójki Przykład: EAX * 36 = EAX * (32 +4) = EAX * (2 5 + 2 2 ).code mov eax, 123 mov ebx, eax shl eax, 5 ; mnozenie przez 32 shl ebx, 2 ; mnożenie przez 4 add eax, ebx ; sumowanie wyników
Instrukcje mnożenie i dzielenia MUL mnożenie liczb bez znaku DIV dzielenie liczb bez znaku IMUL mnożenie liczb ze znakiem IDIV dzielenie liczb ze znakiem
Instrukcja MUL Mnożenie liczb całkowitych bez znaku Składnia: MUL MUL MUL reg/mem8 reg/mem16 reg/mem32 operand jest mnożną mnożnikiem jest rejestr AL, AX lub EAX wynik umieszczony w rejestrach AX, DX:AX, EDX:EAX Reguły: mnożna i mnożnik tego samego rozmiaru Znaczniki CF i OF ustawiane jeśli starsza połówka wyniku różna od zera Sprawdzanie znacznika CF po instrukcji MUL pozwala stwierdzić, czy zawartość starszej połówki wyniku można zignorować
Instrukcja IMUL Mnożenie liczb całkowitych ze znakiem Składnia: wersja jednoargumentowa IMUL reg/mem8 IMUL reg/mem16 ; AX = AL * reg/mem8 ; DX:AX = AX * reg/mem16 IMUL reg/mem32 ; EDX:EAX = EAX * reg/mem32 OF i CF ustawiane, gdy starsza połówka nie jest rozszerzeniem znakiem z młodszej połówki wersja dwuargumentowa mnożenie obydwu operandów, wynik zapisany do pierwszego z nich IMUL reg16, reg/mem16 IMUL reg16, imm8 IMUL reg16, imm16 IMUL reg32, reg/mem32 IMUL reg32, imm8 IMUL reg32, imm32 ; reg16 = reg16 * reg/mem16 ; reg16 = reg16 * imm8 ; reg16 = reg16 * imm16 ; reg32 = reg32 * reg/mem32 ; reg32 = reg32 * imm8 ; reg32 = reg32 * imm32 jeśli wynik nie mieści się w operandzie docelowym to jest on obcinany od góry i ustawiane są znaczniki OF i CF
Instrukcja IMUL c.d. Składnia: wersja trójargumentowa mnożenie drugiego i trzeciego operandu wynik zapisany do operandu pierwszego IMUL reg16, reg/mem16, imm8 IMUL reg16, reg/mem16, imm16 IMUL reg32, reg/mem32, imm8 IMUL reg32, reg/mem32, imm32 ; reg16 = reg16 * reg/mem16 * imm8 ; reg16 = reg16 * reg/mem16 * imm16 ; reg32 = reg32 * reg/mem32 * imm8 ; reg32 = reg32 * reg/mem32 * imm32 jeśli wynik nie mieści się w operandzie docelowym to jest on obcinany od góry i ustawiane są znaczniki OF i CF Mnożenie bez znaku przy użyciu IMUL możliwe przy użyciu dwu- i trójargumentowej wersji instrukcji wada OF i CF nie wskazują, czy starsza połówka wyniku jest zerem
IMUL - przykłady Mnożenie 48 * 4 = 192, wynik w AX mov al,48 mov bl,4 imul bl ; AX = 00C0h, OF = 1 Mnożenie -4 * 4 = -16, wynik w AL mov al,-4 mov bl,4 imul bl ; AX = FFF0h, OF = 0 Mnożenie 48 * 4 = 192, wynik w DX:AX mov ax,48 mov bx,4 imul bx ; DX:AX = 000000C0h, OF = 0 Mnożenie 4.823.424 * -423 = -2.040.308.352, wynik w EDX:EAX mov eax,+4823424 mov ebx,-423 imul ebx ; EDX:EAX = FFFFFFFF86635D80h, OF = 0
IMUL przykłady c.d. Wersja dwuargumentowa.data word1 SWORD 4 dword1 SDWORD 4.code mov ax,-16 ; AX = -16 mov bx,2 ; BX = 2 imul bx,ax ; BX = -32 imul bx,2 ; BX = -64 imul bx,word1 ; BX = -256 mov eax,-16 ; EAX = -16 mov ebx,2 ; EBX = 2 imul ebx,eax ; EBX = -32 imul ebx,2 ; EBX = -64 imul ebx,dword1 ; EBX = -256 mov ax,-32000 imul ax,2 ; OF = 1
Porównanie MUL i IMUL do SHL Wczesne procesory rodziny x86 oraz 8086 i 80286 znacząca różnica (do kilkudziesięciu razy) czasów wykonania na korzyść SHL Nowe procesory jednordzeniowe: niewielka różnica (do kilku razy) czasów wykonania na korzyści SHL Nowe procesory wielordzeniowe identyczne czasy wykonania
DIV Dzielenie liczb całkowitych bez znaku Składnia: DIV reg/mem8 DIV reg/mem16 DIV reg/mem32 operand jest dzielnikiem dzielną jest rejestr AX lub para rejestrów DX:AX lub EDX:EAX iloraz umieszczony odpowiednio w rejestrach AL, AX lub EAX reszta umieszczona odpowiednio w rejestrach AH, DX lub EDX Znaczniki niezdefiniowane
IDIV Dzielenie liczb całkowitych ze znakiem Składnia: DIV DIV DIV reg/mem8 reg/mem16 reg/mem32 operand jest dzielnikiem dzielną jest rejestr AX lub para rejestrów DX:AX lub EDX:EAX iloraz umieszczony odpowiednio w rejestrach AL, AX lub EAX reszta umieszczona odpowiednio w rejestrach AH, DX lub EDX Reguły konieczne rozszerzenie starszej części bitem znaku za pomocą instrukcji: CBW (Convert Byte to Word) dla argumentu 8-bitowego CWD (Convert Word to Doubleword) dla argumentu 16-bitowego CDQ (Conwert Doubleword to Quadword) dla argumentu 32- bitowego reszta ma zawsze taki sam znak jak dzielna Znaczniki niezdefiniowane
Błędy dzielenia Błąd przepełnienia: powstaje gdy iloraz nie mieści się w operandzie docelowym objawia się przerwaniem, które zatrzymuje działanie bieżącego programu zapobieganie temu błędowi polega na użyciu operandów o większych rozmiarach (np. 32- bitowych zamiast 16-bitowych) Błąd dzielenia przez zero powstaje przy próbie dzielenia przez zero objawia się wywołaniem przerwania, które zatrzymuje dalsze działanie programu zapobieganie temu błędowi polega na sprawdzeniu wartości dzielnika przed wykonaniem operacji dzielenia
DZIĘKUJĘ ZA UWAGĘ