0% found this document useful (0 votes)
10 views

ASM - Notes 3 (Integer Arithmetic)

The document discusses assembly language concepts like bit shifting, rotation, and integer arithmetic. It covers shift and rotate instructions, logical vs arithmetic shifts, and how shifts can be used to perform multiplication, division, and other operations on integers.

Uploaded by

hworld1202
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
10 views

ASM - Notes 3 (Integer Arithmetic)

The document discusses assembly language concepts like bit shifting, rotation, and integer arithmetic. It covers shift and rotate instructions, logical vs arithmetic shifts, and how shifts can be used to perform multiplication, division, and other operations on integers.

Uploaded by

hworld1202
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 17

Govt.

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

Computer Organization & Assembly Language

16-Bit
Processor
NASM
64-Bit
&
Processor
DOSBox
Assembly
Language
Programming
MASM
& AFD
VS 2017
32-Bit
Processor

Assembly Language gives you direct control of the system's


resources. The involves setting processor registers, accessing
memory locations, and interfacing with other hardware elements.
This requires a significantly deeper understanding of exactly how
the processor and memory work.

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.

Shift and Rotate Instructions


Bit shifting means to move bits right and left inside an operand. x86 processors provide a
particularly rich set of instructions in this table, all affecting the Overflow and Carry flags.

Shift and Rotate Instructions


SHL Shift Left
SHR Shift Right
SAL Shift Arithmetic Left
SAR Shift Arithmetic Right
ROL Rotate Left
ROR Rotate Right
RCL Rotate Carry Left
RCR Rotate Carry Right
SHLD Double-Precision Shift Left
SHRD Double-Precision Shift Right

Logical Shifts and Arithmetic Shifts


There are two ways to shift an operand’s bits. The first, logical shift, fills the newly created
bit position with zero. In the following illustration, a byte is logically shifted one position to
the right. In other words, each bit is moved to the next lowest bit position. Note that bit 7 is
assigned 0:

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

The lowest bit (LSB) is shifted into the Carry flag:

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:

If you shift 11001111 left by 1 bit, it becomes 10011110:

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

The following lists the types of operands permitted by this instruction:


SHL reg, imm8
SHL mem, imm8
SHL reg, CL
SHL mem, CL
x86 processors permit imm8 to be any integer between 0 and 255. Alternatively, the CL
register can contain a shift count. Formats shown here also apply to the SHR, SAL, SAR, ROR,
ROL, RCR, and RCL instructions.
SHL Examples
In the following instructions, BL is shifted once to the left. The highest bit is copied into the
Carry flag and the lowest bit position is assigned zero:
mov bl, 8Fh ; BL = 10001111b
shl bl, 1 ; CF = 1, BL = 00011110b
When a value is shifted leftward multiple times, the Carry flag contains the last bit to be
shifted out of the most significant bit (MSB). In the following example, bit 7 does not end up
in the Carry flag because it is replaced by bit 6 (a zero):
mov al, 10000000b
shl al, 2 ; CF = 0, AL = 00000000b
Similarly, when a value is shifted rightward multiple times, the Carry flag contains the last bit
to be shifted out of the least significant bit (LSB).
Bitwise Multiplication
Bitwise multiplication is performed when you shift a number’s bits in a leftward direction
(toward the MSB). For example, SHL can perform multiplication by powers of 2. Shifting any
operand left by n bits multiplies the operand by 2n. For example, shifting the integer 5 left by
1 bit yields the product of 5 x 21 = 10:
mov dl, 5
shl dl, 1
If binary 00001010 (decimal 10) is shifted left by two bits, the result is the same as multiplying
10 by 22:
mov dl, 10 ; before: 00001010
shl dl, 2 ; after: 00101000

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:

SHR uses the same instruction formats as SHL.


SHR Examples
In the following example, the 0 from the lowest bit in AL is copied into the Carry flag, and the
highest bit in AL is filled with a zero:
mov al, D0h ; AL = 11010000b
shr al, 1 ; AL = 01101000b, CF = 0
In a multiple shift operation, the last bit to be shifted out of position 0 (the LSB) ends up in
the Carry flag:
mov al, 00000010b
shr al, 2 ; AL = 00000000b, CF = 1
Bitwise Division (Unsigned Division with SHR)
Bitwise division is accomplished when you shift a number’s bits in a rightward direction
(toward the LSB). Shifting an unsigned integer right by n bits divides the operand by 2n. In
the following statements, we divide 32 by 21, producing 16:
mov dl, 32
shr dl, 1
In the following example, 64 is divided by 23:
mov al, 01000000b ; AL = 64
shr al, 3 ; divide by 8, AL = 00001000b
Division of signed numbers by shifting is accomplished using the SAR instruction because it
preserves the number’s sign bit.

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

Bitwise Division (Signed Division with SAR)


You can divide a signed operand by a power of 2, using the SAR instruction.
In the following example, –128 is divided by 23. The quotient is –16:
mov dl, -128 ; DL = 10000000b
sar dl, 3 ; DL = 11110000b

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

SHLD and SHRD Instructions


Self-Research (Optionally)

Shift Instructions Application


Binary Multiplication
Sometimes programmers squeeze every performance advantage they can into integer
multiplication by using bit shifting rather than the MUL instruction. The SHL instruction
performs unsigned multiplication when the multiplier is a power of 2. Shifting an unsigned
integer n bits to the left multiplies it by 2n. Any other multiplier can be expressed as the sum
of powers of 2.
For example, to multiply unsigned EAX by 36, we can write 36 as 25 + 22 and use the
distributive property of multiplication:
EAX * 36 = EAX * (25 + 22)
= EAX * (32 + 4)
= (EAX * 32) + (EAX * 4)
The following figure shows the multiplication 123 * 36, producing 4428, the product:

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

Multiplication and Division Instructions


In 32-bit mode, integer multiplication can be performed as a 32-bit, 16-bit, or 8-bit operation.
In 64-bit mode, you can also use 64-bit operands. The MUL and IMUL instructions perform
unsigned and signed integer multiplication, respectively. The DIV instruction performs
unsigned integer division, and IDIV performs signed integer division.

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

Multiplicand Multiplier Product


AL reg/mem8 AX
AX reg/mem16 DX:AX
EAX reg/mem32 EDX:EAX

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

Using MUL in 64-Bit Mode


In 64-bit mode, you can use 64-bit operands with the MUL instruction. A 64-bit register or
memory operand is multiplied against RDX, producing a 128-bit product in RDX:RAX. In the
following example, each bit in RAX is shifted one position to the left when RAX is multiplied
by 2. The highest bit of RAX spills over into the RDX register, which equals 0000000000000001
hexadecimal:
mov rax, 0FFFF0000FFFF0000h
mov rbx, 2
mul rbx ; RDX:RAX = 0000000000000001FFFE0001FFFE0000
In the next example, we multiply RAX by a 64-bit memory operand. The value is being
multiplied by 16, so each hexadecimal digit is shifted one position to the left (a 4-bit shift is
the same as multiplying by 16).
.data
multiplier QWORD 10h
.code
mov rax, 0AABBBBCCCCDDDDh
mul multiplier ; RDX:RAX = 00000000000000000AABBBBCCCCDDDD0h

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:

Dividend Divisor Quotient Remainder


AX reg/mem8 AL AH
DX:AX reg/mem16 AX DX
EDX:EAX reg/mem32 EAX EDX

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 16-bit unsigned division (8003h/100h), producing a


quotient of 80h and a remainder of 3. DX contains the high part of the dividend, so it must
be cleared before the DIV instruction executes:
mov dx, 0 ; clear dividend, high
mov ax, 8003h ; dividend, low
mov cx, 100h ; divisor
div cx ; AX = 0080h, DX = 0003h
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

mov edx, DWORD PTR dividend + 4 ; high doubleword


mov eax, DWORD PTR dividend ; low doubleword
div divisor ; EAX = 08003000h, EDX = 00000020h
The following diagram illustrates the movement between registers:

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

Implementing Arithmetic Expressions


Example 1
Implement the following C# statement in assembly language, using unsigned 32-bit integers:
var4 = (var1 + var2) * var3;
This is a straightforward problem because we can work from left to right (addition, then
multiplication). After the second instruction, EAX contains the sum of var1 and var2. In the
third instruction, EAX is multiplied by var3 and the product is stored in EAX:
mov eax, var1
add eax, var2
mul var3 ; EAX = EAX * var3
mov var4, eax
Example 2
Implement the following C# statement, using unsigned 32-bit integers:
var4 = (var1 * 5) / (var2 - 3);
In this example, there are two subexpressions within parentheses. The left side can be
assigned to EDX:EAX, so it is not necessary to check for overflow. The right side is assigned to
EBX, and the final division completes the expression:
mov eax, var1 ; left side
mov ebx, 5
mul ebx ; EDX:EAX = product
mov ebx, var2 ; right side
sub ebx, 3
div ebx ; final division
mov var4, eax

Extended Addition and Subtraction


Extended precision addition and subtraction is the technique of adding and subtracting
numbers having an almost unlimited size. In C++, for example, no standard operator permits
you to add two 1024-bit integers. But in assembly language, the ADC (add with carry) and SBB
(subtract with borrow) instructions are well suited to this type of operation.
Self-Research (Optionally)

Best of Luck 😊

17

You might also like