and, or, xor, test,and
not; the rotates are
ror, rol, rcr,and
rcl; the shift instructions are
sar. The 80386 and later processors provide an even richer set of operations. These are
bt, bts, btr, btc,
shld, shrd, and the conditional set instructions (
and, not, or,and
xorinstructions do the following:
and dest, source ;dest := dest and source or dest, source ;dest := dest or source xor dest, source ;dest := dest xor source not dest ;dest := not dest The specific variations are and reg, reg and mem, reg and reg, mem and reg, immediate data and mem, immediate data and eax/ax/al, immediate data or uses the same formats as AND xor uses the same formats as AND not register not memExcept
not, these instructions affect the flags as follows:
notinstruction does not affect any flags.
andinstruction sets the zero flag if the two operands do not have any ones in corresponding bit positions (since this would produce a zero result); for example, if the source operand contained a single one bit, then the zero flag will be set if the corresponding destination bit is zero, it will be one otherwise. The
orinstruction will only set the zero flag if both operands contain zero. The
xorinstruction will set the zero flag only if both operands are equal. Notice that the
xoroperation will produce a zero result if and only if the two operands are equal. Many programmers commonly use this fact to clear a sixteen bit register to zero since an instruction of the form
xor reg16, reg16is shorter than the comparable
xorinstructions provide special forms involving the accumulator register and immediate data. These forms are shorter and sometimes faster than the general "register, immediate" forms. Although one does not normally think of operating on signed data with these instructions, the 80x86 does provide a special form of the "reg/mem, immediate" instructions that sign extend a value in the range -128..+127 to sixteen or thirty-two bits, as necessary.
andinstruction to set selected bits to zero in the destination operand. This is known as masking out data; see for more details. Likewise, you can use the
orinstruction to force certain bits to one in the destination operand; see Chapter Nine for the details. You can use these instructions, along with the shift and rotate instructions described next, to pack and unpack data.
salare the same instruction):
sal(shift arithmetic left),
shr(shift right), and
sar(shift arithmetic right). The 80386 and later processors provide two additional shifts:
shl dest, count sal dest, count shr dest, count sar dest, count
Destis the value to shift and
countspecifies the number of bit positions to shift. For example, the
shlinstruction shifts the bits in the destination operand to the left the number of bit positions specified by the
shrdinstructions use the format:
shld dest, source, count shrd dest, source, countThe specific forms for these instructions are
shl reg, 1 shl mem, 1 shl reg, imm (2) shl mem, imm (2) shl reg, cl shl mem, cl sal is a synonym for shl and uses the same formats. shr uses the same formats as shl. sar uses the same formats as shl. shld reg, reg, imm (3) shld mem, reg, imm (3) shld reg, reg, cl (3) shld mem, reg, cl (3) shrd uses the same formats as shld. 2- This form is available on 80286 and later processors only. 3- This form is available on 80386 and later processors only.For 8088 and 8086 CPUs, the number of bits to shift is either "1" or the value in
cl. On 80286 and later processors you can use an eight bit immediate constant. Of course, the value in
clor the immediate constant should be less than or equal to the number of bits in the destination operand. It would be a waste of time to shift left
alby nine bits (eight would produce the same result, as you will soon see). Algorithmically, you can think of the shift operations with a count other than one as follows:
for temp := 1 to count do shift dest, 1There are minor differences in the way the shift instructions treat the overflow flag when the count is not one, but you can ignore this most of the time.
shl, sal, shr,and
sarinstructions work on eight, sixteen, and thirty-two bit operands. The
shrdinstructions work on 16 and 32 bit destination operands only.
salmnemonics are synonyms. They represent the same instruction and use identical binary encodings. These instructions move each bit in the destination operand one bit position to the left the number of times specified by the count operand. Zeros fill vacated positions at the L.O. bit; the H.O. bit shifts into the carry flag:
shl/sal instruction sets the condition code bits as
shlinstruction doesn't affect any flags.
ahthat you want to combine. You could use the following code to do this:
shl ah, 4 ;This form requires an 80286 or later or al, ah ;Merge in H.O. four bits.Of course,
almust contain a value in the range 0..F for this code to work properly (the shift left operation automatically clears the L.O. four bits of
orinstruction). If the H.O. four bits of
alare not zero before this operation, you can easily clear them with an
shl ah, 4 ;Move L.O. bits to H.O. position. and al, 0Fh ;Clear H.O. four bits. or al, ah ;Merge the bits.Since shifting an integer value to the left one position is equivalent to multiplying that value by two, you can also use the shift left instruction for multiplication by powers of two:
shl ax, 1 ;Equivalent to AX*2 shl ax, 2 ;Equivalent to AX*4 shl ax, 3 ;Equivalent to AX*8 shl ax, 4 ;Equivalent to AX*16 shl ax, 5 ;Equivlaent to AX*32 shl ax, 6 ;Equivalent to AX*64 shl ax, 7 ;Equivalent to AX*128 shl ax, 8 ;Equivalent to AX*256 etc.Note that
shl ax, 8is equivalent to the following two instructions:
mov ah, al mov al, 0The
shl/salinstruction multiplies both signed and unsigned values by two for each shift. This instruction sets the carry flag if the result does not fit in the destination operand (i.e., unsigned overflow occurs). Likewise, this instruction sets the overflow flag if the signed result does not fit in the destination operation. This occurs when you shift a zero into the H.O. bit of a negative number or you shift a one into the H.O. bit of a non-negative number.
sarinstruction shifts all the bits in the destination operand to the right one bit, replicating the H.O. bit:
sar instruction sets the flag bits as follows:
sarinstruction doesn't affect any flags.
sarinstruction's main purpose is to perform a signed division by some power of two. Each shift to the right divides the value by two. Multiple right shifts divide the previous shifted result by two, so multiple shifts produce the following results:
sar ax, 1 ;Signed division by 2 sar ax, 2 ;Signed division by 4 sar ax, 3 ;Signed division by 8 sar ax, 4 ;Signed division by 16 sar ax, 5 ;Signed division by 32 sar ax, 6 ;Signed division by 64 sar ax, 7 ;Signed division by 128 sar ax, 8 ;Signed division by 256There is a very important difference between the
idivinstructions. The idiv instruction always truncates towards zero while
sartruncates results toward the smaller result. For positive results, an arithmetic shift right by one position produces the same result as an integer division by two. However, if the quotient is negative,
idivtruncates towards zero while
sartruncates towards negative infinity. The following examples demonstrate the difference:
mov ax, -15 cwd mov bx, 2 idiv ;Produces -7 mov ax, -15 sar ax, 1 ;Produces -8Keep this in mind if you use
sarfor integer division operations.
sar ax, 8instruction effectively copies
aland then sign extends
ax. This is because
sar ax, 8will shift
albut leave a copy of
ah's H.O. bit in all the bit positions of
ah. Indeed, you can use the sar instruction on 80286 and later processors to sign extend one register into another. The following code sequences provide examples of this usage:
; Equivalent to CBW: mov ah, al sar ah, 7 ; Equivalent to CWD: mov dx, ax sar dx, 15 ; Equivalent to CDQ: mov edx, eax sar edx, 31Of course it may seem silly to use two instructions where a single instruction might suffice; however, the
cdqinstructions only sign extend
edx:eax. Likewise, the movsx instruction copies its sign extended operand into a destination operand twice the size of the source operand. The
sarinstruction lets you sign extend one register into another register of the same size, with the second register containing the sign extension bits:
; Sign extend bx into cx:bx mov cx, bx sar cx, 15
shrinstruction shifts all the bits in the destination operand to the right one bit shifting a zero into the H.O. bit:
shr instruction sets the flag bits as follows:
shrinstruction doesn't affect any flags.
alregister, leaving the H.O. nibble in
ahand the L.O. nibble in
al. You could use the following code to do this:
mov ah, al ;Get a copy of the H.O. nibble shr ah, 4 ;Move H.O. to L.O. and clear H.O. nibble and al, 0Fh ;Remove H.O. nibble from alSince shifting an unsigned integer value to the right one position is equivalent to dividing that value by two, you can also use the shift right instruction for division by powers of two:
shr ax, 1 ;Equivalent to AX/2 shr ax, 2 ;Equivalent to AX/4 shr ax, 3 ;Equivalent to AX/8 shr ax, 4 ;Equivalent to AX/16 shr ax, 5 ;Equivlaent to AX/32 shr ax, 6 ;Equivalent to AX/64 shr ax, 7 ;Equivalent to AX/128 shr ax, 8 ;Equivalent to AX/256 etc.Note that
shr ax, 8is equivalent to the following two instructions:
mov al, ah mov ah, 0Remember that division by two using
shronly works for unsigned operands. If
axcontains -1 and you execute
shr ax, 1the result in
axwill be 32767 (7FFFh), not -1 or zero as you would expect. Use the
sarinstruction if you need to divide a signed integer by some power of two.
shrdinstructions provide double precision shift left and right operations, respectively. These instructions are available only on 80386 and later processors. Their generic forms are
shld operand1, operand2, immediate shld operand1, operand2, cl shrd operand1, operand2, immediate shrd operand1, operand2, cl
Operand2 must be a sixteen or thirty-two bit register.
Operand1 can be a register or a memory location. Both operands must be the same size. The immediate operand can be a value in the range zero through n-1, where n is the number of bits in the two operands; it specifies the number of bits to shift.
shldinstruction shifts bits in operand1 to the left. The H.O. bit shifts into the carry flag and the H.O. bit of
operand2 shifts into the L.O. bit of
operand1. Note that this instruction does not modify the value of operand2, it uses a temporary copy of operand2 during the shift. The immediate operand specifies the number of bits to shift. If the count is n, then
shldshifts bit n-1 into the carry flag. It also shifts the H.O. n bits of operand2 into the L.O. n bits of operand1. Pictorially, the
shld instruction sets the flag bits as follows:
mov ax, Value4 ;Get H.O. nibble shld bx, ax, 4 ;Copy H.O. bits of AX to BX. mov ax, Value3 ;Get nibble #2. shld bx, ax, 4 ;Merge into bx. mov ax, Value2 ;Get nibble #1. shld bx, ax, 4 ;Merge into bx. mov ax, Value1 ;Get L.O. nibble shld bx, ax, 4 ;BX now contains all four nibbles.The
shrdinstruction is similar to
shldexcept, of course, it shifts its bits right rather than left. To get a clear picture of the
shrd instruction sets the flag bits as follows:
shrdinstruction doesn't affect any flags.
Operand2 could be a memory location. Intel designed these instructions to allow fast multiprecision (64 bits, or more) shifts.
shrdinstruction is marginally more useful than
shldfor packing data. For example, suppose that
axcontains a value in the range 0..99 representing a year (1900..1999),
bxcontains a value in the range 1..31 representing a day, and
cxcontains a value in the range 1..12 representing a month (see Chapter One). You can easily use the shrd instruction to pack this data into
shrd dx, ax, 7 shrd dx, bx, 5 shrd dx, cx, 4
rcl(rotate through carry left),
rcr(rotate through carry right),
rol(rotate left), and
ror(rotate right). These instructions all take the forms:
rcl dest, count rol dest, count rcr dest, count ror dest, countThe specific forms are
rcl reg, 1 rcl mem, 1 rcl reg, imm (2) rcl mem, imm (2) rcl reg, cl rcl mem, cl rol uses the same formats as rcl. rcr uses the same formats as rcl. ror uses the same formats as rcl. 2- This form is avialable on 80286 and later processors only.
rcl(rotate through carry left), as its name implies, rotates bits to the left, through the carry flag, and back into bit zero on the right:
Note that if you rotate through carry an object n+1 times, where n is
the number of bits in the object, you wind up with your original value.
Keep in mind, however, that some flags may contain different values after
rcl instruction sets the flag bits as follows:
rclsets the overflow flag if the sign changes as a result of the rotate. If the count is not one, the overflow flag is undefined.
rclinstruction does not modify the zero, sign, parity, or auxiliary carry flags.
rcloperation. If you need to test one of these flags after an
rcloperation, test the carry and overflow flags first (if necessary) then compare the result to zero to set the other flags.
rcr(rotate through carry right) instruction is the complement to the
rclinstruction. It shifts its bits right through the carry flag and back into the H.O. bit:
This instruction sets the flags in a manner analogous to
rcrsets the overflow flag if the sign changes (meaning the values of the H.O. bit and carry flag were not the same before the execution of the instruction). However, if the count is not one, the value of the overflow flag is undefined.
rcrinstruction does not affect the zero, sign, parity, or auxiliary carry flags.
rolinstruction is similar to the
rclinstruction in that it rotates its operand to the left the specified number of bits. The major difference is that
rolshifts its operand's H.O. bit, rather than the carry, into bit zero.
Rolalso copies the output of the H.O. bit into the carry flag:
rol instruction sets the flags identically to
Other than the source of the value shifted into bit zero, this instruction
behaves exactly like the
rcl instruction. Don't forget the
warning about the flags!
rol instruction is often useful
for packing and unpacking data. For example, suppose you want to extract
bits 10..14 in
ax and leave these bits in bits 0..4. The following
code sequences will both accomplish this:
shr ax, 10 and ax, 1Fh rol ax, 6 and ax, 1Fh
rorinstruction relates to the
rcrinstruction in much the same way that the
rolinstruction relates to
rcl. That is, it is almost the same operation other than the source of the input bit to the operand. Rather than shifting the previous carry flag into the H.O. bit of the destination operation,
rorshifts bit zero into the H.O. bit:
ror instruction sets the flags identically to
Other than the source of the bit shifted into the H.O. bit, this instruction
behaves exactly like the
rcr instruction. Don't forget the
warning about the flags!