开发者

When should carry flag be set in assembly language

开发者 https://www.devze.com 2022-12-30 10:16 出处:网络
I\'m puzzled by this problem when writting an ARM assembly simulator in C. I\'ve found some similar questions in the forum, but none of them explain how to set the carry flag just using the relationsh

I'm puzzled by this problem when writting an ARM assembly simulator in C. I've found some similar questions in the forum, but none of them explain how to set the carry flag just using the relationship between two operands and t开发者_如何学JAVAhe result.

Any reply is appreciated. Thanks in advance.

Regard.


The carry flag gets set in the normal way, e.g. as the result of an addition which generates a carry. You can then use an ADC (add with carry) instruction to propagate this carry into a high order word, e.g. when doing a 64 bit add:

ADDS    r4, r0, r2    ; add least significant words
ADC     r5, r1, r3    ; add most significant words with carry

In this example the 64 bit value in r4:r5 is equal to the sum of the 64-bit values in r0:r1 and r2:r3.

On early versions of ARM you could set the carry flag explicitly like this:

ORRS R15,R15,#&20000000

or like this:

TEQP R15,#&20000000

See this tutorial for more info: http://www.peter-cockerell.net/aalp/html/ch-3.html

Apparently newer versions of ARM have moved the carry flag to a different register (see comments below).


You have to check the reference manual for the processor to know which instructions set the carry flags and in which way. I don't know enough about ARM, but I've seen some variations in other processors:

  • some instructions which logically generates a carry may not set the carry flag

  • some instructions may use the carry flag with as some additional implicit operand or result without having a connection with addition/subtraction

  • after a subtraction, processors vary in which condition the carry flag is set (i.e some do it in the same way as after the addition of an inversed second operand, the other set it to the negation of that)

If what you want is a way to see if a carry should be generated for an addition in C, here are two ways (the first is straight from definition, the second comes from wrap around behavior of unsigned):

unsigned w1, w2, result;
int carry;

carry = w1 > UINT_MAX-w2;

result = w1 + w2;
carry = result < w1;


Check out the ARM Architecture Reference Manual (affectionately referred to as the "ARM ARM"). You may need a login these days, but they're free (just behind a "promise not to sue us" agreement).

The ARM ARMs have detailed information about when the C bit is set and cleared for each instruction in pseudocode form. In the ARMv5 ARM, for ADCS, you have e.g.

C Flag = CarryFrom(Rn + shifter_operand + C Flag)

...and they cover both ARM and Thumb instruction set instructions.

(You'll note that almost all arithmetic Thumb-mode instructions set the condition code flags including the carry bit always; the ARM-mode ones mostly don't unless they have the S flag set.)

(Also, my info might not be current; I'm most familiar with the ARMv5TE architecture.)


look at the armulator which you can find in the gdb sources.

For a two operand add you can tell from the msbits of the operands and the result if there was a carry. Or you can write an experimental say 8 bit adder, and build a truth table.

EDIT:



#include <stdio.h>

#define BITS 2
#define MASK ((1<<BITS)-1)

unsigned int ra,rb,rc;

int main ( void )
{

    for(ra=0;ra<=MASK;ra++)
    {
        for(rb=0;rb<=MASK;rb++)
        {
            rc=ra+rb;
            printf("%u + %u = %u : %u %u %u : %u\n",ra,rb,rc,((ra>>(BITS-1))&1),((rb)>>(BITS-1))&1,((rc>>(BITS-1))&1),rc>>BITS);
        }
    }
    return(0);
}

Which produces:

0 + 0 = 0 : 0 0 0 : 0
0 + 1 = 1 : 0 0 0 : 0
0 + 2 = 2 : 0 1 1 : 0
0 + 3 = 3 : 0 1 1 : 0
1 + 0 = 1 : 0 0 0 : 0
1 + 1 = 2 : 0 0 1 : 0
1 + 2 = 3 : 0 1 1 : 0
1 + 3 = 4 : 0 1 0 : 1
2 + 0 = 2 : 1 0 1 : 0
2 + 1 = 3 : 1 0 1 : 0
2 + 2 = 4 : 1 1 0 : 1
2 + 3 = 5 : 1 1 0 : 1
3 + 0 = 3 : 1 0 1 : 0
3 + 1 = 4 : 1 0 0 : 1
3 + 2 = 5 : 1 1 0 : 1
3 + 3 = 6 : 1 1 1 : 1

The obvious case is when the msbit of the first operand and the msbit of the second operand are set you are going to carry that bit over. The two less obvious cases are when the msbit of a is set and the msbit of the result is not set, there was a carry, likewise when the msbit of b is set and the msbit of the result is not set, there was a carry.

So

carry=0
if((MSB(A))&&(MSB(B))) carry=1
if((MSB(A))&&(!MSB(ANS))) carry=1
if((MSB(B))&&(!MSB(ANS))) carry=1
0

精彩评论

暂无评论...
验证码 换一张
取 消