Conditional Processing in Assembly Language
Chapter Overview
- Boolean and Comparison Instructions
- Conditional Jumps
- Conditional Loop Instructions
- Conditional Structures
- Application: Finite-State Machines
- Conditional Control Flow Directives
Boolean and Comparison Instructions
- CPU Status Flags
- AND Instruction
- OR Instruction
- XOR Instruction
- NOT Instruction
- Applications
- TEST Instruction
- CMP Instruction
Status Flags - Review
- The Zero flag is set when the result of an operation equals zero.
- The Carry flag is set when an instruction generates a result that is too large (or too small) for the destination operand.
- The Sign flag is set if the destination operand is negative, and it is clear if the destination operand is positive.
- The Overflow flag is set when an instruction generates an invalid signed result (bit 7 carry is XORed with bit 6 Carry).
- The Parity flag is set when an instruction generates an even number of 1 bits in the low byte of the destination operand.
- The Auxiliary Carry flag is set when an operation produces a carry out from bit 3 to bit 4
AND Instruction
- Performs a Boolean AND operation between each pair of matching bits in two operands
- Syntax:
AND destination, source
(same operand types as MOV)
OR Instruction
- Performs a Boolean OR operation between each pair of matching bits in two operands
- Syntax:
OR destination, source
XOR Instruction
- Performs a Boolean exclusive-OR operation between each pair of matching bits in two operands
- Syntax:
XOR destination, source
- XOR is a useful way to toggle (invert) the bits in an operand.
NOT Instruction
- Performs a Boolean NOT operation on a single destination operand
- Syntax: NOT destination
Bit-Mapped Sets
- Binary bits indicate set membership
- Efficient use of storage
- Also known as bit vectors
Bit-Mapped Set Operations
- Set Complement
assembly
mov eax,SetX
not eax
- Set Intersection
assembly
mov eax,setX
and eax,setY
- Set Union
assembly
mov eax,setX
or eax,setY
Applications
- (1 of 5)
- Task: Convert the character in AL to upper case.
- Solution: Use the AND instruction to clear bit 5.
assembly
mov al,'a' ; AL = 01100001b
and al,11011111b ; AL = 01000001b
- (2 of 5)
- Task: Convert a binary decimal byte into its equivalent ASCII decimal digit.
- Solution: Use the OR instruction to set bits 4 and 5. The ASCII digit '6' = 00110110b
assembly
mov al,6 ; AL = 00000110b
or al,00110000b ; AL = 00110110b
- (3 of 5)
- Task: Turn on the keyboard CapsLock key
- Solution: Use the OR instruction to set bit 6 in the keyboard flag byte at 0040:0017h in the BIOS data area. This code only runs in Real-address mode, and it does not work under Windows NT, 2000, or XP.
assembly
mov ax,40h ; BIOS segment
mov ds,ax
mov bx,17h ; keyboard flag byte
or BYTE PTR [bx],01000000b ; CapsLock on
- (4 of 5)
- Task: Jump to a label if an integer is even.
- Solution: AND the lowest bit with a 1. If the result is Zero, the number was even. JZ (jump if Zero) is covered in Section 6.3.
assembly
mov ax,wordVal
and ax,1 ; low bit set?
jz EvenValue ; jump if Zero flag set
- (5 of 5)
- Task: Jump to a label if the value in AL is not zero.
- Solution: OR the byte with itself, then use the JNZ (jump if not zero) instruction. ORing any number with itself does not change its value.
assembly
or al,al
jnz IsNotZero ; jump if not zero
TEST Instruction
- Performs a nondestructive AND operation between each pair of matching bits in two operands
- No operands are modified, but the Zero flag is affected.
- Example: jump to a label if either bit 0 or bit 1 in AL is set.
assembly
test al,00000011b
jnz ValueFound
- Example: jump to a label if neither bit 0 nor bit 1 in AL is set.
assembly
test al,00000011b
jz ValueNotFound
CMP Instruction
- (1 of 3)
- Compares the destination operand to the source operand
- Nondestructive subtraction of source from destination (destination operand is not changed)
- Syntax:
CMP destination, source
- Example: destination == source
assembly
mov al,5
cmp al,5 ; Zero flag set
- Example: destination < source
assembly
mov al,4
cmp al,5 ; Carry flag set
- (2 of 3)
- Example: destination > source
assembly
mov al,6
cmp al,5 ; ZF = 0, CF = 0 (both the Zero and Carry flags are clear)
- (3 of 3)
- Example: destination > source
assembly
mov al,5
cmp al,-2 ; Sign flag == Overflow flag
The comparisons shown here are performed with signed integers. - Example: destination < source
assembly
mov al,-1
cmp al,5 ; Sign flag != Overflow flag
Boolean Instructions in 64-Bit Mode
- 64-bit boolean instructions, for the most part, work the same as 32-bit instructions
- If the source operand is a constant whose size is less than 32 bits and the destination is the lower part of a 64-bit register or memory operand, all bits in the destination operand are affected
- When the source is a 32-bit constant or register, only the lower 32 bits of the destination operand are affected
Conditional Jumps
- Jumps Based On . . .
- Specific flags
- Equality
- Unsigned comparisons
- Signed Comparisons
- Applications
- Bit Test (BT) Instruction
Jcond Instruction
- A conditional jump instruction branches to a label when specific register or flag conditions are met
- Specific jumps:
JB, JC
- jump to a label if the Carry flag is setJE, JZ
- jump to a label if the Zero flag is setJS
- jump to a label if the Sign flag is setJNE, JNZ
- jump to a label if the Zero flag is clearJECXZ
- jump to a label if ECX = 0
Jcond Ranges
- Prior to the 386:
- jump must be within –128 to +127 bytes from current location counter
- x86 processors:
- 32-bit offset permits jump anywhere in memory
Jumps Based on Specific Flags
JZ
: Jump if zero, ZF = 1JNZ
: Jump if not zero, ZF = 0JC
: Jump if carry, CF = 1JNC
: Jump if not carry, CF = 0JO
: Jump if overflow, OF = 1JNO
: Jump if not overflow, OF = 0JS
: Jump if signed, SF = 1JNS
: Jump if not signed, SF = 0JP
: Jump if parity (even), PF = 1JNP
: Jump if not parity (odd), PF = 0
Jumps Based on Equality
JE
: Jump if equal (leftOp = rightOp)JNE
: Jump if not equal (leftOp != rightOp)JCXZ
: Jump if CX=0JECXZ
: Jump if ECX=0
Jumps Based on Unsigned Comparisons
JA / JNBE
: Jump if above (if leftOp > rightOp)JAE / JNB
: Jump if above or equal (if leftOp >= rightOp)JB / JNAE
: Jump if below (if leftOp < rightOp)JBE / JNA
: Jump if below or equal (if leftOp <= rightOp)
Jumps Based on Signed Comparisons
JG / JNLE
: Jump if greater (if leftOp > rightOp)JGE / JNL
: Jump if greater than or equal (if leftOp >= rightOp)JL / JNGE
: Jump if less (if leftOp < rightOp)JLE / JNG
: Jump if less than or equal (if leftOp <= rightOp)
Applications
- (1 of 5)
- Task: Jump to a label if unsigned EAX is greater than EBX
- Solution: Use CMP, followed by JA
assembly
cmp eax,ebx
ja Larger
- Task: Jump to a label if signed EAX is greater than EBX
- Solution: Use CMP, followed by JG
assembly
cmp eax,ebx
jg Greater
- (2 of 5)
- Jump to label L1 if unsigned EAX is less than or equal to Val1
assembly
cmp eax,Val1
jbe L1 ; below or equal
- Jump to label L1 if signed EAX is less than or equal to Val1
assembly
cmp eax,Val1
jle L1
- (3 of 5)
- Compare unsigned AX to BX, and copy the larger of the two into a variable named Large
assembly
mov Large,bx
cmp ax,bx
jna Next
mov Large,ax
Next:
- Compare signed AX to BX, and copy the smaller of the two into a variable named Small
assembly
mov Small,ax
cmp bx,ax
jnl Next
mov Small,bx
Next:
- (4 of 5)
- Jump to label L1 if the memory word pointed to by ESI equals Zero
assembly
cmp WORD PTR [esi],0
je L1
- Jump to label L2 if the doubleword in memory pointed to by EDI is even
assembly
test DWORD PTR [edi],1
jz L2
- (5 of 5)
- Task: Jump to label L1 if bits 0, 1, and 3 in AL are all set.
- Solution: Clear all bits except bits 0, 1,and 3. Then compare the result with 00001011 binary.
assembly
and al,00001011b ; clear unwanted bits
cmp al,00001011b ; check remaining bits
je L1 ; all set? jump to L1
Encrypting a String
- The following loop uses the XOR instruction to transform every character in a string into a new value.
assembly
KEY = 239 ; can be any byte value
BUFMAX = 128
.data
buffer BYTE BUFMAX+1 DUP(0)
bufSize DWORD BUFMAX
.code
mov ecx,bufSize; loop counter
mov esi,0; index 0 in buffer
L1:
xor buffer[esi],KEY; translate a byte
inc esi; point to next byte
loop L1
String Encryption Program
- Tasks:
- Input a message (string) from the user
- Encrypt the message
- Display the encrypted message
- Decrypt the message
- Display the decrypted message
- Sample output:
text
Enter the plain text: Attack at dawn.
Cipher text: «¢¢Äîä-Ä¢-ïÄÿü-Gs
Decrypted: Attack at dawn.
BT (Bit Test) Instruction
- Copies bit n from an operand into the Carry flag
- Syntax:
BT bitBase, n
bitBase
may be r/m16
or r/m32
n
may be r16
, r32
, or imm8
- Example: jump to label L1 if bit 9 is set in the AX register:
assembly
bt AX,9 ; CF = bit 9
jc L1 ; jump if Carry
Conditional Loop Instructions
- LOOPZ and LOOPE
- LOOPNZ and LOOPNE
LOOPZ and LOOPE
- Syntax:
LOOPE destination
LOOPZ destination
- Logic:
ECX ¬ ECX – 1
- if
ECX > 0
and ZF=1
, jump to destination
- Useful when scanning an array for the first element that does not match a given value.
- In 32-bit mode, ECX is the loop counter register. In 16-bit real-address mode, CX is the counter, and in 64-bit mode, RCX is the counter.
LOOPNZ and LOOPNE
- LOOPNZ (LOOPNE) is a conditional loop instruction
- Syntax:
LOOPNZ destination
LOOPNE destination
- Logic:
ECX ¬ ECX – 1;
- if
ECX > 0
and ZF=0
, jump to destination
- Useful when scanning an array for the first element that matches a given value.
LOOPNZ Example
- The following code finds the first positive value in an array:
assembly
.data
array SWORD -3,-6,-1,-10,10,30,40,4
sentinel SWORD 0
.code
mov esi,OFFSET array
mov ecx,LENGTHOF array
next:
test WORD PTR [esi],8000h; test sign bit
pushfd; push flags on stack
add esi,TYPE array
popfd; pop flags from stack
loopnz next; continue loop
jnz quit; none found
sub esi,TYPE array; ESI points to value
quit:
Conditional Structures
- Block-Structured IF Statements
- Compound Expressions with AND
- Compound Expressions with OR
- WHILE Loops
- Table-Driven Selection
Block-Structured IF Statements
- Assembly language programmers can easily translate logical statements written in C++/Java into assembly language. For example:
c++
if( op1 == op2 )
X = 1;
else
X = 2;
assembly
mov eax,op1
cmp eax,op2
jne L1
mov X,1
jmp L2
L1:
mov X,2
L2:
Compound Expression with AND
- (1 of 3)
- When implementing the logical AND operator, consider that HLLs use short-circuit evaluation
- In the following example, if the first expression is false, the second expression is skipped:
c++
if (al > bl) AND (bl > cl)
X = 1;
- (2 of 3)
- This is one possible implementation . . .
assembly
cmp al,bl ; first expression...
ja L1
jmp next
L1:
cmp bl,cl ; second expression...
ja L2
jmp next
L2:
; both are true
mov X,1 ; set X to 1
next:
;...
- (3 of 3)
- But the following implementation uses 29% less code by reversing the first relational operator. We allow the program to "fall through" to the second expression:
assembly
cmp al,bl ; first expression...
jbe next ; quit if false
cmp bl,cl ; second expression...
jbe next ; quit if false
mov X,1 ; both are true
next:
;...
Compound Expression with OR
- (1 of 2)
- When implementing the logical OR operator, consider that HLLs use short-circuit evaluation
- In the following example, if the first expression is true, the second expression is skipped:
c++
if (al > bl) OR (bl > cl)
X = 1;
- (2 of 2)
- We can use "fall-through" logic to keep the code as short as possible:
assembly
cmp al,bl ; is AL > BL?
ja L1 ; yes
cmp bl,cl ; no: is BL > CL?
jbe next ; no: skip next statement
L1:
mov X,1 ; set X to 1
next:
;...
WHILE Loops
c++
while( eax < ebx)
eax = eax + 1;
- A WHILE loop is really an IF statement followed by the body of the loop, followed by an unconditional jump to the top of the loop. Consider the following example:
assembly
top:
cmp eax,ebx ; check loop condition
jae next ; false? exit loop
inc eax ; body of loop
jmp top ; repeat the loop
next:
;...
Table-Driven Selection
- (1 of 4)
- Table-driven selection uses a table lookup to replace a multiway selection structure
- Create a table containing lookup values and the offsets of labels or procedures
- Use a loop to search the table
- Suited to a large number of comparisons
- (2 of 4)
- Step 1: create a table containing lookup values and procedure offsets:
assembly
.data
CaseTable BYTE 'A' ; lookup value
DWORD Process_A ; address of procedure
EntrySize = ($ - CaseTable)
BYTE 'B'
DWORD Process_B
BYTE 'C'
DWORD Process_C
BYTE 'D'
DWORD Process_D
NumberOfEntries = ($ - CaseTable) / EntrySize
- (4 of 4)
- Step 2: Use a loop to search the table. When a match is found, call the procedure offset stored in the current table entry:
assembly
mov ebx,OFFSET CaseTable ; point EBX to the table
mov ecx,NumberOfEntries ; loop counter
L1:
cmp al,[ebx] ; match found?
jne L2 ; no: continue
call NEAR PTR [ebx + 1] ; yes: call the procedure
call WriteString ; display message
call Crlf
jmp L3 ; and exit the loop
L2:
add ebx,EntrySize ; point to next entry
loop L1 ; repeat until ECX = 0
L3:
;...
Application: Finite-State Machines
- A finite-state machine (FSM) is a graph structure that changes state based on some input. Also called a state-transition diagram.
- We use a graph to represent an FSM, with squares or circles called nodes, and lines with arrows between the circles called edges.
Finite-State Machines
- A FSM is a specific instance of a more general structure called a directed graph.
- Three basic states, represented by nodes:
- Start state
- Terminal state(s)
- Nonterminal state(s)
Finite-State Machine
- Accepts any sequence of symbols that puts it into an accepting (final) state
- Can be used to recognize, or validate a sequence of characters that is governed by language rules (called a regular expression)
- Advantages:
- Provides visual tracking of program's flow of control
- Easy to modify
- Easily implemented in assembly language
Finite-State Machine Examples
- FSM that recognizes strings beginning with 'x', followed by letters 'a'..'y', ending with 'z':
- FSM that recognizes signed integers:
Implementing an FSM
- The following is code from State A in the Integer FSM:
assembly
StateA:
call Getnext ; read next char into AL
cmp al,'+' ; leading + sign?
je StateB ; go to State B
cmp al,'-' ; leading - sign?
je StateB ; go to State B
call IsDigit ; ZF = 1 if AL = digit
jz StateC ; go to State C
call DisplayErrorMsg ; invalid input found
jmp Quit
IsDigit Procedure
assembly
IsDigit PROC
cmp al,'0' ; ZF = 0
jb ID1
cmp al,'9' ; ZF = 0
ja ID1
test ax,0 ; ZF = 1
ID1:
ret
IsDigit ENDP
- Receives a character in AL. Sets the Zero flag if the character is a decimal digit.
Flowchart of State A
- State A accepts a plus or minus sign, or a decimal digit.
Creating IF Statements
- Runtime Expressions
- Relational and Logical Operators
- MASM-Generated Code
.REPEAT
Directive.WHILE
Directive
Runtime Expressions
.IF
, .ELSE
, .ELSEIF
, and .ENDIF
can be used to evaluate runtime expressions and create block-structured IF statements.- Examples:
assembly
.IF eax > ebx
mov edx,1
.ELSE
mov edx,2
.ENDIF
- MASM generates "hidden" code for you, consisting of code labels, CMP and conditional jump instructions.
assembly
.IF eax > ebx && eax > ecx
mov edx,1
.ELSE
mov edx,2
.ENDIF
Relational and Logical Operators
expr1 == expr2
: Returns true when expr1 is equal to expr2.expr1 != expr2
: Returns true when expr1 is not equal to expr2.expr1 > expr2
: Returns true when expr1 is greater than expr2.expr1 >= expr2
: Returns true when expr1 is greater than or equal to expr2.expr1 < expr2
: Returns true when expr1 is less than expr2.expr1 <= expr2
: Returns true when expr1 is less than or equal to expr2.! expr
: Returns true when expr is false.expr1 && expr2
: Performs logical AND between expr1 and expr2.expr1 || expr2
: Performs logical OR between expr1 and expr2.expr1 & expr2
: Performs bitwise AND between expr1 and expr2.CARRY?
: Returns true if the Carry flag is set.OVERFLOW?
: Returns true if the Overflow flag is set.PARITY?
: Returns true if the Parity flag is set.SIGN?
: Returns true if the Sign flag is set.ZERO?
: Returns true if the Zero flag is set.
Signed and Unsigned Comparisons
- MASM automatically generates an unsigned jump (JBE) because val1 is unsigned.
assembly
.data
val1 DWORD 5
result DWORD ?
.code
mov eax,6
.IF eax > val1
mov result,1
.ENDIF
Generated code:
assembly
mov eax,6
cmp eax,val1
jbe @C0001
mov result,1
@C0001:
- MASM automatically generates a signed jump (JLE) because val1 is signed.
assembly
.data
val1 SDWORD 5
result SDWORD ?
.code
mov eax,6
.IF eax > val1
mov result,1
.ENDIF
Generated code:
assembly
mov eax,6
cmp eax,val1
jle @C0001
mov result,1
@C0001:
- MASM automatically generates an unsigned jump (JBE) when both operands are registers . . .
assembly
.data
result DWORD ?
.code
mov ebx,5
mov eax,6
.IF eax > ebx
mov result,1
.ENDIF
Generated code:
assembly
mov ebx,5
mov eax,6
cmp eax,ebx
jbe @C0001
mov result,1
@C0001:
- . . . unless you prefix one of the register operands with the SDWORD PTR operator. Then a signed jump is generated.
assembly
.data
result SDWORD ?
.code
mov ebx,5
mov eax,6
.IF SDWORD PTR eax > ebx
mov result,1
.ENDIF
Generated code:
.REPEAT Directive
- Executes the loop body before testing the loop condition associated with the .UNTIL directive.
- Example:
- Display integers 1 – 10:
assembly
mov eax,0
.REPEAT
inc eax
call WriteDec
call Crlf
.UNTIL eax == 10
.WHILE Directive
- Tests the loop condition before executing the loop body
- The .ENDW directive marks the end of the loop.
- Example:
- Display integers 1 – 10:
assembly
mov eax,0
.WHILE eax < 10
inc eax
call WriteDec
call Crlf
.ENDW
Summary
- Bitwise instructions (AND, OR, XOR, NOT, TEST)
- manipulate individual bits in operands
- CMP – compares operands using implied subtraction
- Conditional Jumps & Loops
- equality: JE, JNE
- flag values: JC, JZ, JNC, JP, …
- signed: JG, JL, JNG, …
- unsigned: JA, JB, JNA, …
- LOOPZ, LOOPNZ, LOOPE, LOOPNE
- Flowcharts – logic diagramming tool
- Finite-state machine – tracks state changes at runtime