Search code examples
assemblymicroprocessors8085carryflag

How Intel 8085 actually performs a subtraction with previous borrow?


My understanding is that in order to evaluate X - Y - borrow, we can either perfrom X - (Y + borrow) or (X - Y) - borrow. Examples in the textbooks depicts the former approach. In that case, what will happen is the subtrahend (Y) is FFH and borrow is set (to 1)?

I tried the following code in GNUSim8085 (http://gnusim8085.srid.ca/) which shows a wrong answer (CY flag is not set). Is it an implementation issue of GNUSim8085 or this actually happens in physical Intel 8085 chip due to the overflow?

STC
MVI A,0FFH
SBI 0FFH
HLT

Whereas, the next code gives the correct answer (A = FFH, CY=1) as expected.

STC
MVI A,00H
SBI 00H
hlt

Solution

  • My understanding is that in order to evaluate X - Y - borrow, we can either perfrom X - (Y + borrow) or (X - Y) - borrow.

    Typically, real CPUs do not perform two operations, but they use an ALU that uses "full adder-subtractors". These circuits perform a subtraction with borrow in one operation.

    Typically, there is one circuit for each bit (e.g. 8 circuits for an 8-bit subtraction).

    The circuit calculating the carry flag also calculates the upper bit (bit 7) of the result; it takes the upper bits (bit 7) of both numbers and an internal flag (which can be 0 or 1) as input. It has no other information!

    We calculate 90h-80h: The result is 10h or 0Fh (depending on the former state of the carry flag) and carry is clear. This means that the circuit will calculate 0 as upper bit of the result and clear carry if the upper bits of both input numbers are 1 and the "internal flag" has a certain state (0 or 1).

    We calculate 80h-90h: The result is 0F0h or 0EFh and carry is set. This means that the circuit will calculate 1 as upper bit of the result and set carry if the upper bits of both input numbers are 1 and the "internal flag" has the other state.

    Calculating 0FFh-0FFh, the upper bits of both input values also set to 1. This means: Depending on the "internal flag", the circuit will either set the upper bit of the output to 0 and clear carry, or set the upper bit of the output to 1 and set carry.

    So a result of A=0xFFh and CY=0 is not possible.

    Is it an implementation issue of GNUSim8085 or this actually happens in physical Intel 8085 chip due to the overflow?

    There are CPUs that do not use a "full-adder" in the lowest bit to calculate a subtraction with borrow.

    However, I doubt that the 8085 is one of those CPUs.

    Having a look at the source code of GNUSim8085, you'll see comments like this (this one is taken from the function that performs SBI):

      /* I'm not sure abt the new code
       * Old code:
    

    Reading such comments, I think that there are still some bugs in that emulator.

    EDIT

    If someone having an actual 8085 kit ...

    A result of CY=0 would definitely be a bug!

    Why? Because a subtraction of a 32-bit constant from a 32-bit number would lead to the wrong result:

    1000FF00h - 0FF01h = 0FFFFFFFh  (if CY=1 in your example)
    1000FF00h - 0FF01h = 1000FFFFh  (if CY=0 in your example)
    

    If Intel really produced some (buggy) 8085 ICs resulting in CY=0, Intel would have corrected this bug in ICs produced later!

    So you will definitely find real 8085 ICs resulting in CY=1, while it is pure speculation that there might also be (buggy) ICs resulting in CY=0.

    By the way: Using the 8085 simulator "sim8085", your example results in CY=1.