Search code examples
assemblycpu-architecturecpu-registersx86-16status-register

How many bits are actually used on the Status Register (8086)


Asked this in class, I think I understand it but not sure so I wanted to confirm.

The Status Register has 16 bits, with each bit having a flag. However, the image provided in our lecture slides shows otherwise?

Status register

The image shows that only certain bits actually have flags. Does this mean that only those bits are actually being used? That the rest of the bits are just fodder?

I'm sorry if my question is unclear, I can attempt to explain more if anyone asks.

Currently, I'm thinking that only 9 bits are actually being used?


Solution

  • In the documentation, it is shown as a «16 bit register» because it is a logical size for a register.

    In the actual implementation (the way the processor was created) it is often that they will only have the 9 bits. The other "bits" are lines directly connected to the Ground pin (or +1.2V or whatever the voltage would have been there.) This is because memory is expensive and if you can save a few bits, the hardware is cheaper (think about saving 5 bits x 10 million processors...)

    In newer implementation, I would imagine they do not bother as much, although computers do things like that automatically, so there would again be no reason to have a real bit of memory if it is to keep it to 0 all the time.

    So as a programmer, as far as you are concerned, it is 16 bits. For a hardware engineer, it is likely just 9 bits. You just have to make sure that you can still push the flags on the stack properly (that the other 5 bits will always be a known value, in most cases that will be zero).


    Further Details:

    To access the flag register, as a programmer, you use PUSHF and POPF.

    ; read to AX
    PUSHF
    POP AX
    
    ; write from AX
    PUSH AX
    POPF
    

    (As a side note in regard to FUZxxl comments above, the old PUSHF and POPF instructions are 16 bits, the newer versions are 32 or 64 bits. This is important to keep the stack properly aligned.)

    As mentioned by Ped7g, although you can put any random value in AX and do a PUSH + POPF, it is not good practice. Usually, when you want to change a flag for which there is no instruction, you do:

    PUSHF
    POP AX
    OR 10h       ; set flag A to 1
    PUSH AX
    POPF
    

    The other ways to change a flag is by using certain instructions. This is defined in the instruction directly. There are a few instructions such as CLD and STC which directly clear or set of flag. And there are others such as SBB that will tweak the borrow and ADC that tweak the carry (and N, Z, V flags...)

    Finally, there are ways to check the basic flags with branch instructions. In many cases, this is used with the CMP instruction (on newer processor, there are MANY reasons why a flag might change...) This allows you to compare a register against another value and branch if it is smaller, larger, equal, smaller or equal, larger or equal, generates an overflow. So an instruction such as JC reads the C flag and jumps if true (set to 1).

    In older processors, most of the flags where in link with branches. The 8086 added the A flag for "Arithmetic" operations (doing additions and subtractions in decimal) and the D flag for "Direction" (see LOOPCX, MOVB).

    Later it added many other flags for so many things that I won't list them here. Some of these were useful to know whether a certain instruction existed, and since then we have a CPUID instruction for extensions, everything you need to know about the CPU and it can even be patched at runtime.