Bits: logic, shifts and rotates

Intermediate

The logic instructions work on each bit separately.

InstructionA bit of the result is 1 when...Common use
AND d, sboth bits are 1clear bits: keep only some (a mask)
OR d, seither bit is 1set bits
XOR d, sthe bits differflip bits; XOR AX, AX clears AX
NOT dthe bit was 0flip every bit
TEST d, s(like AND, but only the flags change)is a bit set?

AND, OR, XOR and TEST always clear CF and OF, and set ZF and SF from the result. NOT changes no flags.

Upper and lower case

In ASCII, a lower-case letter is its capital plus 20h: 'a' is 61h and 'A' is 41h. Only bit 5 (value 20h) differs, so:

ToDoMask
upper caseclear bit 5AND AL, 11011111B (0DFh)
lower caseset bit 5OR AL, 00100000B (20h)
the other caseflip bit 5XOR AL, 20H
; Read a letter and print it in the other case.
.MODEL SMALL
.STACK 100H
.CODE
MAIN PROC
    MOV AH, 1
    INT 21H            ; AL = the letter typed
    MOV DL, AL
    XOR DL, 20H        ; flip bit 5: a <-> A
    MOV AH, 2
    INT 21H
    TEST DL, 20H       ; is bit 5 set now? (ZF = 0 means lower case)
    MOV AH, 4CH
    INT 21H
MAIN ENDP
END MAIN

Input used: q

Open in compiler

TEST AL, 1 checks the lowest bit: ZF = 1 means the number is even.

Shifts and rotates

InstructionMoves the bitsThe bit pushed out goes to
SHL d, nleft, 0s come in: × 2ⁿCF
SHR d, nright, 0s come in: ÷ 2ⁿ (unsigned)CF
SAR d, nright, copies of the sign bit come in: ÷ 2ⁿ (signed)CF
ROL d, n / ROR d, nround in a circleCF (and back in at the other end)
RCL d, n / RCR d, nround in a circle through CFCF

On the 8086 the count n is 1 or the register CL: MOV CL, 3 then SHL AX, CL. (StepVioz also accepts a number, as later processors do.)

Shifting left one bit at a time pushes each bit into CF, top bit first: a way to print a number in binary.

; Print a byte in binary: shift each bit into CF, top bit first.
.MODEL SMALL
.STACK 100H
.CODE
MAIN PROC
    MOV BL, 45         ; 45 = 00101101b
    MOV CX, 8          ; eight bits
NEXTBIT:
    MOV DL, '0'
    SHL BL, 1          ; the top bit goes into CF
    ADC DL, 0          ; '0' + CF: '0' or '1'
    MOV AH, 2
    INT 21H
    LOOP NEXTBIT
    MOV AH, 4CH
    INT 21H
MAIN ENDP
END MAIN
Open in compiler

ADC DL, 0 adds CF to DL, turning '0' into '1' when the bit was 1, with no jump needed.

Common mistakes

  • Using AND to set a bit (it can only clear) or OR to clear one (it can only set).
  • Using SHR on a negative number to divide it: use SAR, which keeps the sign.
  • Expecting SHL AX, 3 to work on a real 8086: use MOV CL, 3 and SHL AX, CL.
  • Clearing bit 5 of a character that is not a letter: check that it is between 'a' and 'z' first.

Quick check

1. AL = 'g' (67h). What does AND AL, 0DFH give?
2. AX = 6. What is AX after SHL AX, 1?
3. Which instruction sets the flags without changing its operand?
4. Which shift divides a negative number by 2 correctly?

Practice problems for this lesson

My notes

Write down what you want to remember from this lesson. Notes are saved on this device as you type, and appear on your dashboard.