CH 7
CH 7
Shift and rotate instructions are key in assembly language for moving bits left or right within a
number. They affect the Carry Flag (CF) and Overflow Flag (OF).
1. Logical Shift
Two types:
o SHL (Shift Left): Moves bits left, fills rightmost bit with 0.
o SHR (Shift Right): Moves bits right, fills leftmost bit with 0.
Example (SHR):
Original: 11001111
After 1 right shift: 01100111 (CF = 1, because the last shifted bit was 1).
2. Arithmetic Shift
SAR (Shift Arithmetic Right): Copies the sign bit into the new leftmost bit.
Example (SAR):
Effects:
Example:
assembly
Copy
Download
Uses:
Effects:
Example:
assembly
Copy
Download
Uses:
Example:
assembly
Copy
Download
Uses:
Key Takeaways
Instructio
Type Effect Use Case
n
Multiply unsigned
SHL Logical Shift Left Left shift, CF = last shifted bit
numbers
Arithmetic Shift
SAR Right shift, keeps sign bit Divide signed numbers
Right
SAL Arithmetic Shift Left Same as SHL Rarely used (same as SHL)
Remember:
Extra Notes
Highest bit moves into Carry Flag (CF) AND the lowest bit.
assembly
Copy
Download
Uses:
Swapping upper/lower nibbles (e.g., ROL AL, 4 turns 26h into 62h).
Multibyte rotation: Shifts hex digits (e.g., 6A4Bh → A4B6h after ROL AX,4).
Example:
assembly
Copy
Download
Example:
assembly
Copy
Download
clc ; CF = 0
Example:
assembly
Copy
Download
stc ; CF = 1
Key Use:
Recovering a shifted bit (e.g., use RCL to undo a SHR if CF was set).
Examples:
assembly
Copy
Download
.data
.code
Example:
assembly
Copy
Download
Uses:
RCL Rotate Left Through Carry Includes CF in rotation Recover lost bits
Instruction Type Effect Use Case
SHLD Double Shift Left Fills from source’s MSBs Bitmap operations
SHRD Double Shift Right Fills from source’s LSBs Long integer math
Final Notes
1. Which instruction shifts left and copies the highest bit into CF and the lowest bit?
How it works: Bits move left, the highest bit goes to CF and the lowest bit.
Example:
assembly
Copy
Download
2. Which instruction shifts right, copies the lowest bit into CF, and puts CF into the highest bit?
How it works: Bits move right, the lowest bit goes to CF, and CF fills the highest bit.
Example:
assembly
Copy
Download
stc ; Set CF = 1
Why?
Answer:
Example:
assembly
Copy
Download
5. Challenge: Shift AX’s lowest bit into BX’s highest bit without SHRD
Solution:
Code:
assembly
Copy
Download
mov cx, 16 ; Number of bits to shift (for 16-bit registers)
; Without SHRD:
; With SHRD:
shrd bx, ax, 1 ; Directly shift AX's LSB into BX's MSB
Goal: Count the number of 1 bits in EAX and set PF (Parity Flag) if the count is even.
Steps:
Code:
assembly
Copy
Download
CountBits:
loop CountBits
; Else, PF = 0 (odd)
Summary Table
Questio
Answer Key Idea
n
Problem: How to shift a big number (stored in multiple bytes/words) left or right.
Solution: Use SHR/SHL + RCR/RCL to chain shifts across bytes.
1. Shift the highest byte ([ESI+2]) right → Its LSB goes to Carry Flag (CF).
assembly
Copy
Download
2. Rotate middle byte ([ESI+1]) right → Fill MSB with CF, new LSB to CF.
assembly
Copy
Download
Copy
Download
Final Result:
Copy
Download
[ESI+2]: 01001100
[ESI+1]: 11001100
[ESI]: 11001100
Key Idea:
Use RCR for remaining shifts (to carry bits between bytes).
o 36 = 32 (2⁵) + 4 (2²)
assembly
Copy
Download
Why It Works:
Copy
Download
= 3936 + 492
= 4428
Key Takeaways
Chain SHR + RCR to shift large SHR byte3,1 → RCR byte2,1 → RCR
Multi-byte Shift
numbers. byte1,1
Goal: Convert a 32-bit binary number (like EAX = 1101...) into a readable ASCII string (like "1101...").
How It Works:
2. Shift left (SHL) to move the highest bit into the Carry Flag (CF).
3. Check CF:
Code Example:
BinToAsc PROC
push esi
mov ecx, 32 ; 32 bits to process
pop ecx
ret
BinToAsc ENDP
Example Output:
If EAX = 3 (000...0011), the buffer becomes:
"00000000000000000000000000000011"
Goal: Extract day, month, and year from a packed 16-bit date stamp (like DX in MS-DOS).
Step-by-Step Extraction:
assembly
Copy
Download
assembly
Copy
Download
Use DH (bits 8-15), shift right 1 bit (since year starts at bit 9), then add 1980:
assembly
Copy
Download
Key Takeaways
Get month Shift right 5 + mask 00001111b shr ax,5 → and al, 00001111b
Get year Shift DH right 1 + add 1980 shr al,1 → add ax, 1980
Review 2
1. Write assembly language instructions that calculate EAX * 24 using binary multiplication.
To multiply EAX by 24, we can use a combination of shifting and adding. Multiplying by 24 is the
same as multiplying by 16 (2^4) and then adding the result of multiplying by 8 (2^3).
asm
CopyEdit
Explanation:
The shl eax, 4 instruction shifts the bits of EAX left by 4 positions, effectively multiplying it by
16.
The add eax, eax instruction doubles EAX, which is the same as multiplying by 2.
2. Write assembly language instructions that calculate EAX * 21 using binary multiplication.
To multiply EAX by 21, we can use the same approach as before, utilizing shifts and adds. Multiplying
by 21 can be broken down as multiplying by 16 (2^4) and adding the result of multiplying by 4 (2^2)
and 1 (2^0).
asm
CopyEdit
Explanation:
The mov ebx, eax saves the current value of EAX (which is already multiplied by 16).
Finally, the add eax, ebx adds the value of EBX (EAX * 4) to EAX (EAX * 16), resulting in EAX *
21.
3. What change would you make to the BinToAsc procedure in Section 7.2.3 in order to display the
binary bits in reverse order?
To reverse the order of the binary bits displayed by the BinToAsc procedure, you would need to
modify the loop where the binary bits are extracted and printed. Instead of printing the bits in the
order they are extracted (starting from the most significant bit), you would start from the least
significant bit.
Here is an approach to modify the procedure to display the bits in reverse order:
asm
CopyEdit
xor edx, edx ; Clear the EDX register for the remainder
reverse_loop:
shl ebx, 1 ; Shift left to bring the next bit into the carry flag
call PrintChar
jmp next_bit
print_bit:
call PrintChar
next_bit:
Explanation:
The shl ebx, 1 instruction shifts the bits to the left, effectively moving the next bit into the
carry flag.
The jc print_bit checks if the carry flag is set, which indicates that the current bit is 1. If not, it
prints 0.
This process prints the least significant bit first and works its way to the most significant bit,
reversing the order.
4. The time stamp field of a file directory entry uses bits 0 through 4 for the seconds, bits 5 through
10 for the minutes, and bits 11 through 15 for the hours. Write instructions that extract the
minutes and copy the value to a byte variable named bMinutes.
Assuming the timestamp is stored in a 2-byte variable timestamp (or WORD), here are the
instructions to extract the minutes (bits 5 through 10) and store them in bMinutes:
asm
CopyEdit
and ax, 3Fh ; Mask out everything except the lower 6 bits (the minutes)
Explanation:
The mov ax, [timestamp] instruction loads the timestamp into the AX register.
The shr ax, 5 instruction shifts the timestamp right by 5 bits, discarding the seconds portion
(bits 0 through 4).
The and ax, 3Fh instruction masks out the upper bits and keeps only the lower 6 bits, which
correspond to the minutes.
Finally, the mov [bMinutes], al instruction stores the result (lower byte of AX) into the
bMinutes variable.
In Assembly language, you can do multiplication and division using special instructions. These work
with 8-bit, 16-bit, 32-bit, and (in 64-bit mode) even 64-bit numbers.
The MUL instruction is used to multiply unsigned numbers (only positive values). It works differently
depending on the size of the numbers you use:
You do not give two operands. You only give one, and the CPU already knows what to multiply it
with (like AL, AX, or EAX).
✅ Key Points:
You can multiply a register or memory value, but not an immediate value (like a direct
number).
The result (product) is always twice the size of the numbers being multiplied.
o Carry Flag (CF) and Overflow Flag (OF) are set if the upper half of the result is not
zero.
💡 Example (16-bit): If you multiply AX (16-bit) by another 16-bit value, the result is stored in DX:AX:
AX × value = DX:AX
The IMUL instruction is used when multiplying signed numbers (positive or negative). Unlike MUL, it
keeps track of the sign in the result.
IMUL extends the sign bit (the leftmost bit) to make sure the result keeps the correct sign.
The result (product) is twice the size of the number being multiplied.
📌 3 Formats of IMUL Instruction:
🔹 1. Single-Operand Format:
You give only one operand. The other value is already assumed (like in MUL).
Operand Size Multiplier (you give) Multiplicand (already known) Product (Result)
✅ Overflow is not a problem here because the result space is big enough.
🔸 Flags:
Carry Flag (CF) and Overflow Flag (OF) are set if the upper half is not just a sign-extension of
the lower half. This helps you check if the upper half can be ignored.
Here, you give two values — the destination and the multiplier:
assembly
Copy code
The second operand is the number you multiply it with (can be a register, memory, or
immediate value).
Programmers often want to compare the speed of different parts of their code. To do that, they
measure how long a procedure or block of code takes to run.
The Irvine32 library (used in Assembly programming for Windows) has a handy tool called
GetMseconds, which:
4. Subtract the first time from the second to get the elapsed time.
🧠 Example Code:
assembly
Copy code
.data
startTime DWORD ?
procTime1 DWORD ?
procTime2 DWORD ?
.code
call GetMseconds
call FirstProcedureToTest
call GetMseconds
assembly
Copy code
call GetMseconds
call GetMseconds
⚠️Note:
Yes, calling GetMseconds takes a tiny bit of time, but it's so small that it doesn't affect your
comparison much. When comparing two procedures, this overhead is usually the same for both —
so it's okay.
When dividing signed integers (numbers that can be negative), the process is similar to unsigned
division — but with one big difference:
Before doing signed division, the dividend (number you're dividing) must be sign-extended.
It's needed to make sure the computer knows the number is negative when converting it to
a bigger register (like from AX to EAX).
assembly
Copy code
idiv bx ; divide by 2
assembly
Copy code
🔁 Summary:
Now that we’ve learned how to use multiplication (MUL, IMUL) and division (DIV, IDIV), we can start
writing full arithmetic expressions in Assembly, just like we do in high-level languages like C++.
✅ You’ll be able to add extra error checking that many compilers skip (e.g., check for
overflow).
✅ You’ll know how to use flags (Carry and Overflow) to detect problems like when a
multiplication result doesn’t fit in 32 bits.
📌 Important Tip:
High-level compilers (like C++) often ignore the upper 32 bits when multiplying 32-bit values.
o Right-click → Go to Disassembly
o Go to: Project > Properties > Configuration Properties > Microsoft Macro Assembler
o Set:
cpp
Copy code
assembly
Copy code
That wraps up 7.3.6 — you now know how to build arithmetic expressions in Assembly with full
control and safety!
📘 7.3.7 Section Review – Questions and Answers (Easy Wording)
1. Q: Why can’t overflow happen when MUL and one-operand IMUL instructions are used?
A: Because the result (product) is stored in two registers, which gives double the space. So, even if
the numbers are big, the result fits without overflow.
3. Q: When does the one-operand IMUL set the Carry and Overflow flags?
A: If the upper half of the result is not a copy of the sign bit (not a correct sign extension), the flags
are set. This means the result is too big to fit in the lower part alone.
7. Q: Show an example of sign extending before using IDIV with a 16-bit number.
A:
assembly
Copy code
Here, cwd makes sure the sign of AX is correctly extended into DX, which is needed for signed
division.
Notes on Extended Addition and Subtraction
Overview: Extended addition and subtraction in assembly language allows for operations on integers
that exceed the processor's native word size, such as adding and subtracting integers larger than 32-
bits (e.g., 64-bit integers). This is achieved using the ADC (Add with Carry) and SBB (Subtract with
Borrow) instructions, which work across multiple bytes or words.
Definition:
Extended addition and subtraction refer to adding or subtracting numbers of very large sizes
(e.g., 1024-bit integers), which cannot be handled by standard operators in high-level
languages like C++. Assembly language provides low-level instructions (ADC and SBB) that
enable such operations.
Purpose:
The ADC instruction adds the source operand along with the Carry flag to the destination
operand.
It supports addition of multi-byte values (e.g., adding 64-bit integers) by adding each
byte/word individually and taking the carry from one operation to the next.
Format:
nginx
Copy code
assembly
Copy code
assembly
Copy code
mov edx, 0
Extended_Add Procedure: The Extended_Add procedure adds two extended integers stored as
arrays of bytes. It uses a loop to add the corresponding bytes, incorporating the carry from each
addition into the next one.
Procedure Breakdown:
assembly
Copy code
Extended_Add PROC
pushad
L1:
adc al, [edi] ; Add corresponding byte from second integer + carry
adc byte ptr [ebx], 0 ; Add any remaining carry to high byte
popad
ret
Extended_Add ENDP
Steps:
o Save the result and move the pointers to the next byte.
3. If a carry is generated from the high-order byte, it is added to the sum's extra byte.
Example Use:
assembly
Copy code
.data
.code
main PROC
call Extended_Add
; Display sum
call Display_Sum
call Crlf
main ENDP
Purpose:
The SBB instruction performs subtraction while considering the Carry flag as a borrow. It is
used in a similar way to ADC for multi-byte subtraction.
Example:
assembly
Copy code
mov edx, 7
mov eax, 1
1. The lower 32-bits (EAX) are subtracted first, setting the Carry flag.
2. The SBB instruction subtracts from the upper 32-bits (EDX), including the Carry flag.
o The Carry flag (CF) plays a crucial role in extended addition and subtraction. It is
carried over between iterations and may be added or subtracted from each byte of
the operands.
3. Endianess:
Conclusion:
Extended Addition: Uses the ADC instruction to add multi-byte integers while managing
carries between operations.
Extended Subtraction: Uses the SBB instruction to subtract multi-byte integers while
managing borrows.
The procedures for extended arithmetic are designed to handle arbitrary-sized integers by
processing each byte or word individually while correctly managing carries and borrows
across multiple steps.
Section review 4
Describe the ADC instruction:
The ADC (Add with Carry) instruction adds two values along with the Carry flag. The Carry flag stores
whether a previous addition or subtraction resulted in a carry or borrow. When you use ADC, it not
only adds the two operands (like a regular addition) but also considers the Carry flag, adding it to the
result. This is used in operations like extended precision arithmetic, where multiple bytes are added
one after another, ensuring the Carry flag is correctly handled in each step.
Example:
If you have a Carry flag from a previous addition, the ADC instruction will add that Carry flag value (1
or 0) to the result of the current addition.
The SBB (Subtract with Borrow) instruction subtracts a value along with the Carry flag from a
destination operand. It is the opposite of ADC, meaning it considers whether a previous subtraction
resulted in a borrow. If the Carry flag is set, it subtracts 1 in addition to the source operand.
Example:
If you're subtracting two values, and a borrow occurred during a previous subtraction, SBB will
subtract that borrow (1 or 0) from the result.
3. What will be the values of EDX:EAX after the following instructions execute?
asm
Copy code
Execution:
EAX = 0A0000000h + 20000000h = C0000000h
Since there’s no Carry from the ADD instruction (the result doesn't exceed the maximum
value of EAX), ADC doesn't add anything to EDX.
Final values:
EAX = C0000000h
4. What will be the values of EDX:EAX after the following instructions execute?
asm
Copy code
Execution:
EAX = 80000000h - 90000000h = FFFFFFFFh (because the result is negative, we get a borrow).
The SBB instruction then subtracts 1 (because of the borrow) from EDX.
Final values:
EAX = FFFFFFFFh
5. What will be the contents of DX after the following instructions execute (STC sets the Carry
flag)?
asm
Copy code
mov dx, 5 ; DX = 5
Execution:
DX = 5
Since the Carry flag is set (because STC was used), ADC adds both AX and the Carry flag (1).