LAHF (load AH from flags) copies five status flags into AH. SAHF (store AH into flags) goes the other way and sets those five flags from the bits of AH. Neither instruction touches OF, DF, IF or TF. They exist mostly so that 8080 code could be translated to the 8086 line by line: the 8080 flag byte has the same layout.
| AH bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|---|---|---|---|---|---|---|---|---|
| Flag | SF | ZF | - | AF | - | PF | - | CF |
After LAHF, the bits marked - hold no flag; do not rely on their values. SAHF ignores them.
MOV AL, 3CMP AL, 3 ; equal: ZF = 1LAHF ; AH bit 6 = ZFMOV AL, AHMOV CL, 6SHR AL, CLAND AL, 1 ; isolate ZFADD AL, '0' ; digit -> characterMOV DL, ALMOV AH, 02h ; DOS: print DLINT 21hMOV AH, 01000000b ; only bit 6 (ZF) setSAHF ; ZF = 1, SF AF PF CF = 0MOV AL, 0JNZ SKIP1MOV AL, 1 ; JNZ not taken: ZF was setSKIP1:ADD AL, '0' ; digit -> characterMOV DL, ALMOV AH, 02h ; DOS: print DLINT 21h
Uses
Saving a few flags across code that would change them, without using the stack: LAHF, the work, SAHF. Testing flags as data, for instance to print them. Reading the result of an 8087 compare: the coprocessor stores its status word to memory, the program loads its high byte into AH, and SAHF turns the condition bits into CF, PF and ZF so the ordinary jumps can test them.
Pitfalls
OF is not in AH. If you need it, use PUSHF and POPF, which handle the whole flags register. SAHF overwrites all five flags at once, so build the full byte you want rather than one bit. And LAHF overwrites AH: if AH held something, save it first.
Later CPUs
The 80287 can store its status word straight into AX (FSTSW AX), which makes the SAHF step shorter. Some early 64-bit processors dropped LAHF and SAHF in 64-bit mode; 16- and 32-bit code always has them.