I didn’t see anyone post this clever way to save and restore flags in interrupt for the
8008.
This is from
https://stevemorse.org/8086history/8086history.pdf
APPENDIX 1 SAVING AND RESTORING FLAGS IN THE 8008
Interrupt routines must leave all processor flags and registers unaltered so as not to
contaminate the processing that was interrupted. This is most simply done by having the
interrupt routine save all flags and registers on entry and restore them prior to exiting.
The 8008, unlike its successors, has no instruction for directly saving or restoring
flags.
Thus 8008 interrupt routines that alter flags (practically every routine does) must
conditionally test each flag to obtain its value and then save that value.
Since there are no instructions for directly setting or clearing flags, the flag values
must be restored by
executing code that will put the flags in the saved state.
The 8008 flags can be restored very efficiently if they are saved in the following format
in a byte in memory.
Most significant bit = bit 7
bit 7 = original value of CARRY
bit 6 = original value of SIGN
bit 5 = original value of SIGN
bit 4 = 0
bit 3 = 0
bit 2 = complement of original value of ZERO
bit 1 = complement of original value of ZERO
bit 0 = complement of original value of PARITY
With the information saved in the above format in a byte called FLAGS, the following two
instructions will restore all the saved flag values:
LDA FLAGS ;load saved flags into accumulator
ADD A ;add the accumulator to itself
This instruction sequence loads the saved flags into the accumulator and then doubles the
value, thereby moving each bit one position to the left.
This causes each flag to be set to its original value, for the following reasons:
The original value of the CARRY flag, being in the leftmost bit, will be moved out of the
accumulator and wind up in the CARRY flag.
The original value of the SIGN flag, being in bit 6, will wind up in bit 7 and will become
the sign of the result.
The new value of the SIGN flag will reflect this sign.
The complement of the original value of the PARITY flag will wind up in bit 1, and it
alone will determine the parity of the result (all other bits in the result are paired up
and have no net effect on parity).
The new setting of the PARITY flag will be the complement of this bit (the flag denotes
even parity) and therefore will take on the original value of the PARITY flag.
Whenever the ZERO flag is 1, the SIGN flag must be 0 (zero is a positive two's-
complement number) and the PARITY flag must be 1 (zero has even parity). Thus an original
ZERO flag value of 1 will cause all bits of FLAGS, with the possible exception of bit 7,
to be 0. After the ADD instruction is executed, all bits of the result will be 0 and the
new value of the ZERO flag will therefore be 1.
An original ZERO flag value of 0 will cause two bits in FLAGS to be 1 and will wind up
in the result as well. The new value of the ZERO flag will therefore be 0.
The above algorithm relies on the fact that flag values are always consistent, i.e., that
the
SIGN flag cannot be a 1 when the ZERO flag is a 1.
This is always true in the 8008, since the flags come up in a consistent state whenever
the processor is reset and flags can only be modified by instructions which always leave
the flags in a consistent state.
The 8080 and its derivatives allow the programmer to modify the flags in an arbitrary
manner by popping a value of his choice off the stack and into the flags. Thus the above
algorithm will not work on those processors.
A code sequence for saving the flags in the required format is as follows:
MVI A,0 ; move zero in accumulator
JNC L1 ; jump if CARRY not set
ORA 80H ; OR accumulator with 80 hex (set bit 7)
L1: JZ L3 ; jump if ZERO set (and SIGN not set and PARITY set)
ORA 06H ; OR accumulator with 06 hex (set bits 1 and 2)
JM L2 ; jump if negative (SIGN set)
ORA 60H ; OR accumulator with 60 hex (set bits 5 and 6)
L2: JPE L3 ; jump if parity even (PARITY set)
ORA 01H ; OR accumulator with 01 hex (set bit 0)
L3: STA FLAGS ; store accumulator in FLAGS