3

Quick question, I am reading the textbook entitled "Introduction to 80x86 Assembly Language and Computer Architecture" by Richard C. Detmer and on page 21 and 22 it talks about the concept of what a borrow is, but it doesnt really describe what it really is. Here is the text:

In a computer, subtraction a - b of numbers a and b is usually performed by taking the 2's complement of b and adding the result to a. This corresponds to adding the negation of b. For example, for the decimal subtraction 195 - 618 = -423,

00C3 - 026A

is changed to addition of FD96, the 2's complement of 026A.

00C3 + FD96 = FE59

The hex digits FE59 represent -423. Looking at the previous addition in binary, you have

0000 0000 1100 0011 + 1111 1101 1001 0110 = 1111 1110 0101 1001

Notice that there was no carry in the addition. However, this subtraction did involve a borrow. A borrow occurs in the subtraction a - b when b is larger than a as unsigned numbers. Computer hardware can detect a borrow in subtraction by looking at whether a carry occurred in the corresponding addition. If there is no carry in the addition, then there is a borrow in the subtraction. If there is a carry in the addition, then there is no borrow in the subtraction. (Remember that "carry" by itself means "carry out.")

Here is one more example. Doing the decimal subtraction 985 - 411 = 574 using word-length 2's complement representations,

03D9 - 019B

is changed to addition of FE65, the 2's complement of 019B.

03D9 + FE65 = 1023E

0000 0011 1101 1001 + 1111 1110 0110 0101 = 1 0000 0010 0011 1110

Discarding the extra 1, the hex digits 023E represent 574. This addition has a carry, so there is no borrow in the corresponding subtract.

What really is a borrow with subtraction? I thought when for example 00C3 - 026A, the A is bigger than the 3, so we must "borrow" from the corresponding C by making it a B and making it now 13 (base 16) minus A. That we can do, but a "borrow" occured. In this particular example a borrow in the contexts of the book did occur. But when we look at the next example they gave us 03D9 - 019B, the B is bigger than the 9 so we must "borrow" from the D by making it a C and making the 9 a 19 (base 16) minus B. That we can do, and a "borrow" occured but the book stated that a borrow did not happen.

What is a borrow? I know you know if one occurred by whether a carry happened in the addition but doing raw subtraction, what is really a borrow. When can I identify if one occurred?

For example you know a carry occurred because there is an extra hex digit. The length went out of the length of your two hex numbers (length desired to stay within).

Thank you.

-Dan

SSteve
  • 10,550
  • 5
  • 46
  • 72
Code Doggo
  • 2,146
  • 6
  • 33
  • 58
  • Books are not always 100% error-free, and even if they are, they can be read incorrectly. Borrow is the same as carry. It's not a big deal. – Mike Dunlavey Feb 18 '14 at 19:38
  • @MikeDunlavey Then why call it a borrow? Why not just call it a carry? – Code Doggo Feb 19 '14 at 13:02
  • Because we learned addition and subtraction with carry and borrow in grade school. In a computer, A-B is just A+(-B), so first it negates B and then it adds, using carry, but it you want to think of it as subtraction, it's a borrow.. – Mike Dunlavey Feb 19 '14 at 13:09
  • @MikeDunlavey But if you saw my last example, a borrow never occurred in the actual problem but the author stated that a borrow did occur. And plus, if a borrow is a carry then why does he state that if a carry happens a borrow does not happen and vice versa. Can you give an example to show more clearly? I understand what you said, its just the last example shows a borrow happen but a "traditional" borrow does not happen – Code Doggo Feb 19 '14 at 15:12

2 Answers2

4

In the book, what he is calling a borrow is different from the conventional definition of a borrow. He is saying that borrows only occur when the outcome of the ENTIRE subtraction is negative (in other words, b > a), not necessarily that of the individual digits.

mcwayliffe
  • 386
  • 2
  • 10
  • Why he would define it like that, though, I've no idea – mcwayliffe Feb 18 '14 at 19:43
  • 4
    Because it's the thing you find in the C flag – harold Feb 18 '14 at 19:46
  • Aha! That explains that, then. Thanks @harold – mcwayliffe Feb 18 '14 at 19:47
  • @harold Then why call it a borrow? Borrow means you are "taking" something from somewhere else. I get what he was saying, but in regards to what borrow really means was what I was trying to get at. Is there a bit borrowed somewhere? etc? – Code Doggo Feb 19 '14 at 13:06
  • @DanielH it borrows out of nowhere, but that doesn't really matter does it? It's just a signal that comes out of a circuit. – harold Feb 19 '14 at 13:09
  • @harold Borrows out of nowhere? I know the explanation might be technical but what? Like in my example at the end of my post I stated that you know a carry happened when another hex digit was added to increase the overall size of the hex number. Life if you had a byte, another digit added would cause it to become a word. But during subtract what happens that makes the word "borrow" take hold? I know that if a carry happened a borrow didn't happen and vice versa, which shows us the carry is not the same as a borrow. – Code Doggo Feb 19 '14 at 13:16
  • @DanielH well, suppose you looked at the individual borrows out of all the bits. There is a last bit (the most significant bit), and that borrow doesn't affect any further bits (because there are none). That borrow out of the last bit is called "The Borrow" because it's the borrow out of the entire thing. Or from a different angle, suppose the number you're subtracting from has an imaginary 1 in front of it, "The Borrow" indicates that the subtraction turned the imaginary 1 into an imaginary 0. – harold Feb 19 '14 at 13:42
  • @Harold Can you show an example? How can you magically make a 1 appear? If you had the number 0110 (base 2) and then suddenly put a 1 at the left most bit making it 10110 (base 2), the number has just changed. – Code Doggo Feb 19 '14 at 15:16
  • 1
    @DanielH it's imaginary, you just imagine it to be there. It doesn't matter that it's there, it doesn't affect anything. It can't appear in the result (by definition, it's one beyond the last place of the result, so it can never fit). It's just an imaginary construct to work around the issue of "borrowing out of nowhere" (which is not an issue, because you don't borrow *from*, you borrow *to* - a borrow signal is an output that affects the calculation of the next bit). – harold Feb 19 '14 at 15:50
  • 1
    Like the carry flag for addition, a borrow flag can be used with a subtract with borrow to allow you to cascade operations to make a wider subtraction. A 16 bit addition with 8 bit registers you do an add then an adc (add with carry). If your instruction sets supports it you can do a sub then sbb or whatever you call it. That borrow flag (held in the carry flag) is used to borrow from the next operation. Instead of invert and add 1, for the borrow if you need to borrow then you dont invert and add 1 on the sbb, you invert and add 0, – old_timer Feb 19 '14 at 18:03
  • Thank you, it all finally clicked. Thank you for all the help you have all delivered for me. :) Thank you! – Code Doggo Feb 20 '14 at 19:38
2

Take some 4 bit numbers to make it easier, number of bits doesnt matter 32 bits works the same way just more columns...

We dont actually subtract we add the negative number a - b = a + (-b) and we know that for twos complement the negative of a number you "invert and add one".

So to subtract 7 - 5 we want to add 0111 + ((~0101) + 1)

     1 plus one
  0111
+ 1010 inverted 0101
=======

we invert the second operand 0101 becomes 1010 and the carry in of the first column is a one.

finish the math

 11111
  0111
+ 1010 
=======
  0010

so the answer is 0010 which is 2 decimal. Which is the right answer. Now if the raw carry out bit is a 1 that means THERE WAS NO BORROW. I saw raw because some architectures, if the operation was a subtract will invert the raw carry out when placing it in the processor status register carry flag. Some architectures do, some, dont, so long as you know how it works and can create a simple test you dont have to memorize...

Now go the other way 5 - 7.

 00011
  0101
+ 1000 (inverted 0111)
=======
  1110

So the answer is negative two and the RAW carry out is a 0 indicating there was a borrow. If your architecture inverts the carry out then you would see this as a 1 for borrow...

What comes out of the carry for an ADD operation needs to match what goes in as the carry in for an add with carry operation. What comes out for a SUB operation needs to go back in as a subtract with borrow operation if your architecture has that instruction.

Where the borrow comes into play is this 5-7=-2 case think of the 4 bit subtract as being

  10101  0101 plus a fifth bit there to borrow from if we need it
 - 0111
========
   1110

if you subtract 0x1A - 0x7 on a calculator you get 0xE. We needed that bit to borrow from, it is an exercise to the reader to try to do binary subtraction by hand (very easy), its just not how hardware does it though...perhaps now you see why we use twos complement...

So in general subtract means use the add operation, but ones complement invert the second operand on the way into the adder. Either force the carry in to be a 1 or invert the carry in (invert carry in and invert second operand). Some invert the carry out (invert carry in invert second operand invert carry out if subtract).

Reading your other questions. Lets take our four bit system and cascade it into two two bit systems so lets say for example we want to subtract 4 bit numbers 5 - 3. 0101 - 0011 but we only have two bit registers and a two bit adder. We have to start with the low order two bits first 01 - 11 = 01 + (-01) = 01 + ((~01) + 1)

setup like this, a subtract

   1
  01
+ 00
=====

then finish the math

 011
  01
+ 00
=====
  10

so the low two bits of our answer is 10, now we have to cascade the carry out as a carry in to the next operation a subtract with borrow the operands are 01 and 00 (upper bits of 0101 - 0011)

  110 carry out from lower order operation
   01
+  11 inverted operand
=======
   00

so our whole answer is 0010 and the carry out is a 1 so no borrow. 5-3=2 that worked.

Lets see it this way as a four bit

setup

     1
  0101
+ 1100 
=======

execute

 11011
  0101
+ 1100 
=======
  0010

in order to split that into two bit operations we literally split it at two bit intervals starting from the right

 110  011
  01   01
+ 11   00 
====   ===
  00   10

the right most, low order operation is a normal subtract with a fixed 1 as a carry in. the subtract with borrow is used for any further operations for other upper bits and the carry out of the prior operation is the carry in of the current subtract with borrow.

THAT is why the final carry out is what is important not individual ones along the way, because when we use the processor to do bigger operations that carry out is the one that goes inverted or not into the carry flag in our psr, and then is used as the carry in (inverted or not) in the subtract with borrow (if your processor has one).

We can do one where the carry is a one as well... 5 - 1

four bit setup

     1
  0101
+ 1110
=======

four bit execute

 11111
  0101
+ 1110
=======
  0100

then literally split that into two bit operations to see how it would look if we had 2 bit registers and an alu rather than a four bit.

 111  111
  01   01
+ 11   10
====   ===
  01   00

the carry out of the sub on the right becomes the carry in of the subtract with borrow. if your processor architecture inverts that raw carry out when it goes to the carry bit in the psr, then that architecture will also invert it on the way into the subtract with borrow.

Sometimes the processor documentation is such that you can tell from the signed and unsigned branch if less than or greater than, etc whether or not the carry flag is inverted. Sometimes it is easier just to do an experiment.

old_timer
  • 69,149
  • 8
  • 89
  • 168
  • the borrow means that if you had done this as a traditional subtraction the top number is smaller and you would keep borrowing from a number to the left but you run out of digits, so you do a virtual borrow off the left end of the top number in order to make it all work out. for this four bit thing think of 5 - 7 instead of 0101 - 0111 but instead 10101 - 0111 so that you have a bit up there to borrow from – old_timer Feb 18 '14 at 19:55
  • When you inverted the 0101 number in your first example you never added one to it. You first invert to 1010, which is A in hex, and then add one and you get 1011, which is B in hex. Why didn't you add one? In addition why would architecture invert the bit when dealing with subtraction? I am still confused on that whole reason – Code Doggo Feb 18 '14 at 22:05
  • I did add one to it the carry in of one is the "add one" that is how you an adder in logic to do subtract, you invert the second operand on the way into the adder and you place a 1 as the carry in as the "add one". See the 1 up there on the top in the first example that is the carry in bit on the first bit column. – old_timer Feb 18 '14 at 22:27
  • Invert and add one makes for a negative a - b = a + (-b) to get -b we invert and add one. the operand gets the "invert" the carry in of one is the "add one" then we do an "add" alu operation. result = a + (-b) – old_timer Feb 18 '14 at 22:29
  • Okay okay I understand that now, but you editing your original message and you added the word "massage" which isn't, I dont believe, the correct word. This word distracts from the mean of your overall point and I have trouble following you. What do you mean when you say "Some dont massage the carry out and a 1" & "Just like you have to massage the second operand on the way in and the carry in bit". Thank you. :) – Code Doggo Feb 19 '14 at 13:05
  • Thank you! :) I got it. After going though many examples it finally hit home with me. Thank you for exampling it in such depth with many examples! – Code Doggo Feb 20 '14 at 19:35