Search code examples
assemblyarm

How to do hexadecimal subtraction and how does it affect the arm flags


I am new to ARM.

So I have this following instruction

SUBS R2, R4, R3
Initial condition N = 0, Z = 0, C = 1, V = 0, Q = 0

values in register are signed

R2 = 0000 0000 H
R3 = 7FFF FFFE H 
R4 = 8000 0002 H

One way I learned was to directly subtract


  8000 0002 H
- 7FFF FFFE H 
-------------
  0000 0004 H

but using two complement -7FFF FFFE H --> +8000 0002

  8000 0002 H
+ 8000 0000 H 
-------------
1 0000 0004 H

But this doesn't make any sense since 8000 0002 H is a negative number subtracted by 7FFF FFFE H is a positive number which should give me a big negative number. Is it an overflow, is the carry from the initial condition affected?

Because in the solution book, I'm getting C=0 and no overflow.


Solution

  • Using subtraction you have to borrow, you forgot to borrow off the top bit

    For example in base 10.

     500
    -600
    ====
    

    we cross out the 5 and borrow from the zero next to it (infinitely)

    1400
    
    • 600 =========

    If you want to subtract in base 2 you also have to actually borrow.

     000
    -100
    =====
    
    1000
    -100
    =====
    

    correcting your subtraction:

     1
      8000 0002 H
    - 7FFF FFFE H 
    -------------
      0000 0004 H
    

    Using twos complement (as a processor would see it)

              1
      8000 0002
    + 8000 0001
    ==============
    
    
     1000000001
      8000 0002
    + 8000 0001
    ==============
      0000 0004
    

    Twos complement does not break math, that is the point it works nicely with base two logic implementation converting a subtract into an add which is simpler logic (well some may debate it being simpler, I think you need a carry in/out and a separate borrow in/out for subtract but for add just the carry)

    The register is limited to 32 bits you cannot magically add bits to the register to make it 33 bits.

    You can do experiments to see if you think arm is one that inverts the carry in and carry out for a subtract. Some architectures do, some do not.

    Never assume that carry FLAG = carry OUT (for compare/subtract), always confirm.