ASM - Notes 3 (Integer Arithmetic)
ASM - Notes 3 (Integer Arithmetic)
Postgraduate College of Science, Faisalabad BS-CS 3rd & 5th Semesters - ASM
&
M.Rizwan
Computer Lecturer
1
Govt. Postgraduate College of Science, Faisalabad BS-CS 3rd & 5th Semesters - ASM
16-Bit
Processor
NASM
64-Bit
&
Processor
DOSBox
Assembly
Language
Programming
MASM
& AFD
VS 2017
32-Bit
Processor
2
Govt. Postgraduate College of Science, Faisalabad BS-CS 3rd & 5th Semesters - ASM
Integer Arithmetic
These notes introduce the fundamental binary shift and rotation techniques, playing to one
of the great strengths of assembly language. In fact, bit manipulation is an intrinsic part of
computer graphics, data encryption, and hardware manipulation. Instructions that do this are
powerful tools, and are only partially implemented by high-level languages, and somewhat
obscured by their need to be platform-independent. I show quite a few ways you can apply
bit shifting, including optimized multiplication and division.
Arithmetic with arbitrary-length integers is not supported by all high-level languages. But
assembly language instructions make it possible to add and subtract integers of virtually any
size. You will also be exposed to specialized instructions that perform arithmetic on packed
decimal integers and integer strings.
The following illustration shows a single logical right shift on the binary value 11001111,
producing 01100111.
3
Govt. Postgraduate College of Science, Faisalabad BS-CS 3rd & 5th Semesters - ASM
Another type of shift is called an arithmetic shift. The newly created bit position is filled with
a copy of the original number’s sign bit:
Binary 11001111, for example, has a 1 in the sign bit. When shifted arithmetically 1 bit to the
right, it becomes 11100111:
SHL Instruction
The SHL (shift left) instruction performs a logical left shift on the destination operand, filling
the lowest bit (LSB) with 0. The highest bit (MSB) is moved to the Carry flag, and the bit that
was in the Carry flag is discarded:
The first operand in SHL is the destination and the second is the shift count:
SHL destination, count
4
Govt. Postgraduate College of Science, Faisalabad BS-CS 3rd & 5th Semesters - ASM
5
Govt. Postgraduate College of Science, Faisalabad BS-CS 3rd & 5th Semesters - ASM
SHR Instruction
The SHR (shift right) instruction performs a logical right shift on the destination operand,
replacing the highest bit with a 0. The lowest bit (LSB) is moved to the Carry flag, and the bit
that was previously in the Carry flag is lost:
6
Govt. Postgraduate College of Science, Faisalabad BS-CS 3rd & 5th Semesters - ASM
SAL Instruction
The SAL (shift arithmetic left) instruction works the same as the SHL instruction. For each shift
count, SAL shifts each bit in the destination operand to the next highest bit position. The
lowest bit is assigned 0. The highest bit is moved to the Carry flag, and the bit that was in the
Carry flag is discarded:
If you shift binary 11001111 to the left by one bit, it becomes 10011110:
SAR Instruction
The SAR (shift arithmetic right) instruction performs a right arithmetic shift on its destination
operand:
Binary 11001111, for example, has a 1 in the sign bit. When shifted arithmetically 1 bit to the
right, it becomes 11100111:
The operands for SAL and SAR are identical to those for SHL and SHR. The shift may be
repeated, based on the counter in the second operand:
SAR destination, count
The following example shows how SAR duplicates the sign bit. AL is negative before and after
it is shifted to the right:
mov al, F0h ; AL = 11110000b (-16)
sar al, 1 ; AL = 11111000b (-8), CF = 0
7
Govt. Postgraduate College of Science, Faisalabad BS-CS 3rd & 5th Semesters - ASM
ROL Instruction
Bitwise rotation occurs when you move the bits in a circular fashion. In some versions, the bit
leaving one end of the number is immediately copied into the other end. Another type of
rotation uses the Carry flag as an intermediate point for shifted bits.
The ROL (rotate left) instruction shifts each bit to the left. The highest bit is copied into the
Carry flag and the lowest bit position. The instruction format is the same as for SHL:
Bit rotation does not lose bits. A bit rotated off one end of a number appears again at the
other end.
ROL Examples
Note in the following example how the high bit is copied into both the Carry flag and bit
position 0:
mov al, 40h ; AL = 01000000b
rol al, 1 ; AL = 10000000b, CF = 0
rol al, 1 ; AL = 00000001b, CF = 1
rol al, 1 ; AL = 00000010b, CF = 0
When using a rotation count greater than 1, the Carry flag contains the last bit rotated out of
the MSB position:
mov al, 00100000b
rol al, 3 ; CF = 1, AL = 00000001b
Exchanging Groups of Bits
You can use ROL to exchange the upper (bits 4–7) and lower (bits 0–3) halves of a byte. For
example, 26h rotated four bits in either direction becomes 62h:
mov al, 26h
rol al, 4 ; AL = 62h
8
Govt. Postgraduate College of Science, Faisalabad BS-CS 3rd & 5th Semesters - ASM
When rotating a multibyte integer by four bits, the effect is to rotate each hexadecimal digit
one position to the right or left. Here, for example, we repeatedly rotate 6A4Bh left four bits,
eventually ending up with the original value:
mov ax, 6A4Bh
rol ax, 4 ; AX = A4B6h
rol ax, 4 ; AX = 4B6Ah
rol ax, 4 ; AX = B6A4h
rol ax, 4 ; AX = 6A4Bh
ROR Instruction
The ROR (rotate right) instruction shifts each bit to the right and copies the lowest bit into the
Carry flag and the highest bit position. The instruction format is the same as for SHL:
In the following examples, note how the lowest bit is copied into both the Carry flag and the
highest bit position of the result:
mov al, 01h ; AL = 00000001b
ror al, 1 ; AL = 10000000b, CF = 1
ror al, 1 ; AL = 01000000b, CF = 0
Multiple Rotations When using a rotation count greater than 1, the Carry flag contains the
last bit rotated out of the LSB position:
mov al, 00000100b
ror al, 3 ; AL = 10000000b, CF = 1
RCL Instruction
The RCL (rotate carry left) instruction shifts each bit to the left, copies the Carry flag to the
LSB, and copies the MSB into the Carry flag:
If we imagine the Carry flag as an extra bit added to the high end of the operand, RCL looks
like a rotate left operation. In the following example, the CLC instruction clears the Carry
flag. The first RCL instruction moves the high bit of BL into the Carry flag and shifts the other
9
Govt. Postgraduate College of Science, Faisalabad BS-CS 3rd & 5th Semesters - ASM
bits left. The second RCL instruction moves the Carry flag into the lowest bit position and
shifts the other bits left:
clc ; CF = 0
mov bl, 88h ; CF, BL = 0 10001000b
rcl bl, 1 ; CF, BL = 1 00010000b
rcl bl, 1 ; CF, BL = 0 00100001b
RCR Instruction
The RCR (rotate carry right) instruction shifts each bit to the right, copies the Carry flag into
the MSB, and copies the LSB into the Carry flag:
As in the case of RCL, it helps to visualize the integer in this figure as a 9-bit value, with the
Carry flag to the right of the LSB.
The following code example uses STC to set the Carry flag; then, it performs a rotate carry
right operation on the AH register:
stc ; CF = 1
mov ah, 10h ; AH, CF = 00010000 1
rcr ah, 1 ; AH, CF = 10001000 0
Signed Overflow
The Overflow flag is set if the act of shifting or rotating a signed integer by one-bit position
generates a value outside the signed integer range of the destination operand. To put it
another way, the number’s sign is reversed. In the following example, a positive integer
(+127) stored in an 8-bit register becomes negative (-2) when rotated left:
mov al, +127 ; AL = 01111111b
rol al, 1 ; OF = 1, AL = 11111110b
Similarly, when –128 is shifted one position to the right, the Overflow flag is set. The result
in AL (+64) has the opposite sign:
mov al, -128 ; AL = 10000000b
shr al, 1 ; OF = 1, AL = 01000000b
The value of the Overflow flag is undefined when the shift or rotation count is greater than 1.
10
Govt. Postgraduate College of Science, Faisalabad BS-CS 3rd & 5th Semesters - ASM
It is interesting to note that bits 2 and 5 are set in the multiplier (36), and the integers 2 and
5 are also the required shift counters. Using this information, the following code snippet
multiplies 123 by 36, using SHL and ADD instructions:
mov eax, 123
mov ebx, eax
shl eax, 5 ; multiply by 25
shl ebx, 2 ; multiply by 22
add eax, ebx ; add the products
11
Govt. Postgraduate College of Science, Faisalabad BS-CS 3rd & 5th Semesters - ASM
MUL Instruction
In 32-bit mode, the MUL (unsigned multiply) instruction comes in three versions: The first
version multiplies an 8-bit operand by the AL register. The second version multiplies a 16-bit
operand by the AX register, and the third version multiplies a 32-bit operand by the EAX
register. The multiplier and multiplicand must always be the same size, and the product is
twice their size. The three formats accept register and memory operands, but not immediate
operands:
MUL reg/mem8
MUL reg/mem16
MUL reg/mem32
The single operand in the MUL instruction is the multiplier. Table 7-2 shows the default
multiplicand and product, depending on the size of the multiplier. Because the destination
operand is twice the size of the multiplicand and multiplier, overflow cannot occur. MUL sets
the Carry and Overflow flags if the upper half of the product is not equal to zero. The Carry
flag is ordinarily used for unsigned arithmetic, so we’ll focus on it here. When AX is multiplied
by a 16-bit operand, for example, the product is stored in the combined DX and AX registers.
That is, the high 16 bits of the product are stored in DX, and the low 16 bits are stored in AX.
The Carry flag is set if DX is not equal to zero, which lets us know that the product will not fit
into the lower half of the implied destination operand.
MUL Operands
A good reason for checking the Carry flag after executing MUL is to know whether the upper
half of the product can safely be ignored.
MUL Examples
The following statements multiply AL by BL, storing the product in AX. The Carry flag is clear
(CF = 0) because AH (the upper half of the product) equals zero:
12
Govt. Postgraduate College of Science, Faisalabad BS-CS 3rd & 5th Semesters - ASM
mov al, 5h
mov bl, 10h
mul bl ; AX = 0050h, CF = 0
The following diagram illustrates the movement between registers:
The following statements multiply the 16-bit value 2000h by 0100h. The Carry flag is set
because the upper part of the product (located in DX) is not equal to zero:
.data
val1 WORD 2000h
val2 WORD 0100h
.code
mov ax, val1 ; AX = 2000h
mul val2 ; DX:AX = 00200000h, CF = 1
The following statements multiply 12345h by 1000h, producing a 64-bit product in the
combined EDX and EAX registers. The Carry flag is clear because the upper half of the
product in EDX equals zero:
mov eax, 12345h
mov ebx, 1000h
mul ebx ; EDX:EAX = 0000000012345000h, CF = 0
The following diagram illustrates the movement between registers:
13
Govt. Postgraduate College of Science, Faisalabad BS-CS 3rd & 5th Semesters - ASM
IMUL Instruction
Self-Research (Optionally)
DIV Instruction
In 32-bit mode, the DIV (unsigned divide) instruction performs 8-bit, 16-bit, and 32-bit
unsigned integer division. The single register or memory operand is the divisor. The formats
are
DIV reg/mem8
DIV reg/mem16
DIV reg/mem32
The following table shows the relationship between the dividend, divisor, quotient, and
remainder:
14
Govt. Postgraduate College of Science, Faisalabad BS-CS 3rd & 5th Semesters - ASM
In 64-bit mode, the DIV instruction uses RDX:RAX as the dividend, and it permits the divisor
to be a 64-bit register or memory operand. The quotient is stored in RAX, and the remainder
in RDX.
DIV Examples
The following instructions perform 8-bit unsigned division (83h/2), producing a quotient of
41h and a remainder of 1:
mov ax, 0083h ; dividend
mov bl, 2 ; divisor
div bl ; AL = 41h, AH = 01h
The following diagram illustrates the movement between registers:
The following instructions perform 32-bit unsigned division using a memory operand as the
divisor:
.data
dividend QWORD 0000000800300020h
divisor DWORD 00000100h
.code
15
Govt. Postgraduate College of Science, Faisalabad BS-CS 3rd & 5th Semesters - ASM
The following 64-bit division produces the quotient (0108000000003330h) in RAX and the
remainder (0000000000000020h) in RDX:
.data
dividend_hi QWORD 0000000000000108h
dividend_lo QWORD 0000000033300020h
divisor QWORD 0000000000010000h
.code
mov rdx, dividend_hi
mov rax, dividend_lo
div divisor ; RAX = 0108000000003330
; RDX = 0000000000000020
Notice how each hexadecimal digit in the dividend was shifted 4 positions to the right,
because it was divided by 64. (Division by 16 would have moved each digit only one position
to the right.)
IDIV Instruction
Self-Research (Optionally)
Tip: There are two easy ways to view assembly code generated by a C++ compiler: While
debugging in Visual Studio, right-click in the debug window and select Go to Disassembly.
Alternatively, to generate a listing file, select Properties from the Project menu. Under
Configuration Properties, select Microsoft Macro Assembler. Then select Listing File. In the
dialog window, set Generate Preprocessed Source Listing to Yes, and set List All Available
Information to Yes.
16
Govt. Postgraduate College of Science, Faisalabad BS-CS 3rd & 5th Semesters - ASM
Best of Luck 😊
17