| Autor: | Wojciech Muła |
|---|---|
| Dodany: | 2002 |
CPU potrafi przeprowadzać operacje arytmetyczne tylko na rejestrach o tych samych rozmiarach. Dlatego też operacje na operandach o różnych rozmiarach trzeba poprzedzić poszerzeniem zakresu operandu o mniejszej liczbie bitów.
Rozszerzenie zakresu polega na zapisaniu tej samej wartości w słowie o większej liczbie bitów. Dla liczb bez znaku, zapisanych w naturalnym kodzie binarnym, jest to bardzo proste — wystarczy nowe, „dodane” bity wyzerować.
Np. 8-bitowa liczba 166=10100110b po rozszerzeniu na 32 bity ma postać:
00000000 00000000 00000000 10100110
Dla liczb ze znakiem jest to trochę trudniejsze — nowe bity należy wypełnić bitem znaku.
Np. 8-bitowa liczba -100 = 10011100b po rozszerzeniu na 32 bity ma postać:
11111111 11111111 11111111 10100110
Poniższe sposoby można stosować dla dowolnych rejestrów.
extend_x86.asm:
; al -> ax
xor ah, ah ; wyzeruj ah
and ax, 0x00ff ; j.w.
movzx ax, al
; al -> eax
and eax, 0x000000ff
movzx eax, al
extend_mmx.asm:
; packed byte -> packed word
; mm0 -> mm1:mm0
; mm0 = 0x10ff200faabbccdd
pxor mm2, mm2 ; mm2 = 0x0000000000000000
movq mm1, mm0 ; mm1 = 0x0000000000000000
punpcklbw mm0, mm2 ; mm0 = 0x00aa00bb00cc00dd
punpckhbw mm1, mm2 ; mm1 = 0x001000ff0020000f
Lub inaczej:
extend_mmx.asm:
; packed byte -> packed word ; mm0 -> mm1:mm0 movq mm1, mm0 punpcklbw mm0, mm0 punpckhbw mm1, mm1 psrlw mm0, 8 psrlw mm1, 8
Poniższe rozkazy działają tylko dla akumulatora (al, ax, eax).
extend_stdx86:
cbw ; al -> ax cwd ; ax -> eax cwde ; eax -> edx:eax
A te już dla dowolnych rejestrów i pamięci.
extend_u2.asm:
; al -> ax
mov ah, al
sar ah, al
; al -> eax
; eax = |xxxxxxxx|xxxxxxxx|xxxxxxxx|shhhllll|
shr eax, 24 ; eax = |shhhllll|00000000|00000000|00000000|
sar eax, 24 ; eax = |ssssssss|ssssssss|ssssssss|shhhllll|
; eax -> edx:eax
mov edx, eax
sar edx, eax
; lub troszkę dłuższy kod
xor edx, edx
cmp eax, 0
setge dl
sub edx, 1
extend_u2mmx.asm:
; packed signed byte -> packed signed word ; mm0 -> mm1:mm0 movq mm1, mm0 punpcklbw mm0, mm0 punpcklbw mm1, mm1 psraw mm0, 8 psraw mm1, 8