代码之家  ›  专栏  ›  技术社区  ›  Summer_More_More_Tea

什么时候用汇编语言设置进位标志

  •  8
  • Summer_More_More_Tea  · 技术社区  · 16 年前

    在C语言中编写手臂装配模拟器时,我对这个问题感到困惑。我在论坛中发现了一些类似的问题,但没有一个问题能解释如何仅使用两个操作数之间的关系和结果来设置进位标志。

    感谢您的回复。事先谢谢。

    考虑。

    4 回复  |  直到 7 年前
        1
  •  4
  •   AProgrammer    16 年前

    您必须查看参考手册,让处理器知道哪些指令设置了进位标志,以及以何种方式设置。我对ARM的了解还不够,但我在其他处理器上看到了一些变化:

    • 一些逻辑上生成进位的指令可能不会设置进位标志。

    • 有些指令可以将进位标志用作一些附加的隐式操作数或结果,而不与加法/减法连接。

    • 减法后,处理器在设置进位标志的条件下会有所不同(例如,有些处理方法与将第二个倒数相加后的处理方法相同,另一个则将其设置为该操作数的负数)。

    如果您想要的是查看是否应该为C中的加法生成进位的方法,这里有两种方法(第一种方法是直接从定义开始,第二种方法来自无符号的环绕行为):

    unsigned w1, w2, result;
    int carry;
    
    carry = w1 > UINT_MAX-w2;
    
    result = w1 + w2;
    carry = result < w1;
    
        2
  •  6
  •   Paul R    16 年前

    进位标志以正常方式设置,例如,由于产生进位的加法。然后您可以使用 ADC (与进位一起添加)将此进位传播到高位字的指令,例如在执行64位添加时:

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

    在本例中,r4:r5中的64位值等于r0:r1和r2:r3中的64位值之和。

    在ARM的早期版本中,您可以设置进位标志 明确地 这样地:

    ORRS R15,R15,#&20000000
    

    或者像这样:

    TEQP R15,#&20000000
    

    有关详细信息,请参阅本教程: http://www.peter-cockerell.net/aalp/html/ch-3.html

    显然,ARM的新版本将进位标志移到了另一个寄存器(见下面的注释)。

        3
  •  3
  •   leander    16 年前

    退房 ARM Architecture Reference Manual (亲切地称为“手臂”)。这些天你可能需要登录,但他们是免费的(只是在“承诺不起诉我们”协议之后)。

    ARM具有关于何时为每个伪代码形式的指令设置和清除C位的详细信息。在armv5臂中,用于 ADCS 你有

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

    …它们涵盖了手臂和拇指指令集指令。

    (您将注意到,几乎所有的算术拇指模式指令都设置了条件代码标志,包括进位始终;ARM模式的指令通常不设置,除非设置了S标志。)

    (另外,我的信息可能不是最新的;我最熟悉ARMV5TE体系结构。)

        4
  •  3
  •   old_timer    7 年前

    看看你可以在gdb源中找到的armulator。

    对于双操作数加法,可以从操作数的最高位和有进位的结果中分辨出来。也可以编写一个实验性的say 8位加法器,并构建一个真值表。

    编辑:

    
    #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);
    }
    
    

    产生:

    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
    

    显而易见的情况是,当设置第一个操作数的最高位和第二个操作数的最高位时,您将把该位带过来。不太明显的两种情况是,当设置了a的msbit且未设置结果的msbit时,存在进位;同样,当设置了b的msbit且未设置结果的msbit时,存在进位。

    所以

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