Integer Arithmetic and Shifting Instructions
We will discuss
- operations requiring only one operand
- operations requiring two operands
- operations requiring special operands
Overview of the Machine instruction categories
Arithmetic - 2 byte and 4 byte
addS operand1, operand2add op1 to op2
subS operand1, operand2subtract op1 from op2
imulS operand1, operand2*multiply op2 by op1
idivS operand*divide by operand
incS operandincrement the operand
decS operanddecrement the operand
negSoperandnegate the operand
Shift
salS k,regshift arithmetic left
sarS k,regshift arithmetic right
shlS k,regshift logical left
shrS k,regshift logical right
Load Effective Address - load the address instead of the value from an address
leaS source, dest
Note: S is the size and must be one of
bbyte (1 byte)
wword (2 bytes)
llong (4 bytes)
qquad words (8 bytes)
W for word is based on the old machines where a word was 2 bytes. / Examples:
addl 4(%ebp), %edx#Adds the value at the address computed by #an offset of 4 from the value of ebp to #the value of edx. The result is stored #in edx.
incw %dx#Increment the 2 byte value in dx
leal lresult,%edx#Move the address of lresult to edx
sarl $3, %edx#Arithmetic shift of the long value in edx #3 bits to the right
Operations Requiring Only One Operand
The operand can be a register or a memory reference.
incS operand increment the value of length S in the destination. This does not changeCF.
decS operand decrement the value of length S in the destination. This does not change CF.
notS operanddo a ones' comp on the value in the destination
negS operanddo a two's comp on the value in the destination. Sets CF to 1 unless the operand's value is zero. / Assume the following assembly language snippet:
iValA:
.long0xA
iValB:
.long 0x40
…
movl iValA,%edx#iValA -> edx
incl %edx#edx ++
incl iValB#iValB ++
mov1 $iValA,%eax
incl 4(%eax)#Increment the value at addr(iValA)+4
not1 iValB#1's comp iValB placing the result in iValB
Operations Requiring Two Operands
These operations use the value of the second operand and store the result in the second operand.
Add and Subtract
addS operand1, operand2add op1 to op2. This can change OF, ZF, and/or SF.
subS operand1, operand2subtract op1 from op2. This can change OF, ZF, and/or SF.
Shift
salS k,regshift arithmetic left
sarS k,regshift arithmetic right
shlS k,regshift logical left
shrS k,regshift logical right
Operations Requiring Special Operands - Multiply
Some registers are implicitly used. imulS also sets OF.
For S=w (2 bytes)
- multiplicand must be %ax
- multiplier can be a reg or memory reference for a 2 byte int
- product (the result) will be in %dx(high order) and
%ax (low order)
- multiplicand must be %eax
- multiplier can be a reg or memory reference for a long
- product (the result) will be in %edx(high order) and
%eax (low order)
Why are two registers needed for the result? / Example M-1:4-byte multiply 0x12345 by 0x1000
movl $0x12345, %eax
movl $0x1000, %ebx
imull %ebx
The result in %edx:%eax is 00000000 0x12345000 and OF=0.
Example M-2:2-byte multiply 0x2000 by 0x0100
Assume val1 is 0x2000 and val2 is 0x0100.
movw val1, %ax
imulw val2
The result is %dx:%ax is 0020 0000 and OF=1
Example M-3:2-byte multiply 0x40 by -100
Assume val1 is 0x40 and val2 is -100 (decimal).
movW val1, %ax
imulW val2
What is %dx:%ax?
- -100 is -(0x0064) = FF9C
- 0xFF9C * 0x0040 = FFFFE700 and OF=0 since the sign propagated
Operations Requiring Special Operands - Divide
Some registers are implicitly used. idivS also sets OF.
For S=w (2 bytes)
- dividend must be %dx (high order) and %ax (low order)
- divisor can be a reg or memory reference for a long
- quotient is in %ax and remainder is in %dx
- dividend must be%edx (high order) and %eax (low order)
- divisor can be a reg or memory reference for a long
- quotient is in %eax and remainder is in %edx
Since the dividend is two registers, we must be able to propagate the sign from eax to edx (and ax to dx):
cwtdconvert word to double word propagates the sign in %ax to%dx
cltdconvert long to double long propagates he sign in %eax to %edx
Division examples / Example D-1: 2-byte divide 0x4007 by 0x100
movw $0x4007, %ax #load the low end of dividend
movw 0, %dx #clear the high end of dividend
idivw $0x100 #divide by 0x100
Quotient (%ax) is 0x0040. Remainder (%dx) is 0x0007.
Example D-2: 2-byte divide shTotalCnt by shCourseCnt
movw shTotalCnt, %ax#load the low end of dividend
cwtd #propagate sign to high end
idivw shCourseCnt#divide by shCOurseCnt
Example D-3: 4-byte divide lTotal by 0x200
movllTotal, %eax#load the low end of dividend
cltd#propagate sign to high end
idivl$0x200#divide by 0x200
Quotient will be in %eax and remainder in %edx.