程序集8086中的状态标志

时间:2014-12-08 03:42:39

标签: assembly flags

我现在正在参加集会的本科课程。我对TA如何评分我的任务有一些不符之处。我只是测试进位,零,符号和溢出标志的状态。

这是我出错的状态标志问题之一:

mov ah, 255
mov al, -1
cmp ah, al 

我的解决方案:CF=0, ZF=1, SF=0, OF=0

他的解决方案:CF=0, ZF=0, SF=1, OF=1

有人可以帮我验证哪个是正确的?我不认为我的错了,但如果可以,你能解释一下答案是否正确?

2 个答案:

答案 0 :(得分:2)

你的答案确实是正确的。


Intel Software Developer’s Manual的第1卷描述了每个标志:

  

CF(位0)进位标志 - 设置算术运算是否从结果的最高有效位产生进位或借位;否则清除。该标志表示无符号整数运算的溢出条件。

     

ZF(第6位)零标志 - 如果结果为零则设置;否则就清楚了。

     

SF(第7位)符号标志 - 设置等于结果的最高有效位,即有符号整数的符号位。 (0表示正值,1表示负值。)

     

OF(第11位)溢出标志 - 设置整数结果是否过大,正数或过小的负数(不包括符号位)以适合目标操作数;否则清除。该标志表示有符号整数(二进制补码)算术的溢出条件。

代码中的标志由cmp指令设置,指令集参考卷2表示:

  

比较第一个源操作数和第二个源操作数并设置   根据结果​​,EFLAGS寄存器中的状态标志。比较是   通过从第一个操作数中减去第二个操作数然后设置来执行   状态标志的方式与SUB指令相同。

     

SUB指令执行整数减法。它评估两者的结果   有符号和无符号整数操作数,并设置OF和CF标志以指示   分别在有符号或无符号结果中溢出。 SF标志表示符号   已签名的结果。

首先,我们发现alah都具有相同的值:所有八位都是1

由于CMP设置了SUB之类的标记,我们只评估0xFF - 0xFF,这当然是零。

OF,CF - 没有溢出,因此OF=0CF=0

ZF - 答案是零,所以ZF=1

SF - 答案为零,所以SF=0


只是为了确认,这是一些测试代码(对于GCC):

<强> flags.c

#include <stdio.h>

__attribute__((noinline))
static long test(void)
{
    long ret;

    asm ("mov   $255, %%ah\n\t"
         "mov   $-1,  %%al\n\t"
         "cmp   %%ah, %%al\n\t"

         "pushf\n\t"
         "pop   %0\n\t"
        : "=r" (ret)    /* output  */
        :               /* input   */
        : "%eax"        /* clobber */
    );

    return ret;

}

static void describe_EFLAGS(long flags)
{
    printf("EFLAGS: 0x%X\n", flags);
    printf("    CF: %d\n", (flags & (1<<0)) > 0);
    printf("    PF: %d\n", (flags & (1<<2)) > 0);
    printf("    AF: %d\n", (flags & (1<<4)) > 0);
    printf("    ZF: %d\n", (flags & (1<<6)) > 0);
    printf("    SF: %d\n", (flags & (1<<7)) > 0);
    printf("    TF: %d\n", (flags & (1<<8)) > 0);
    printf("    IF: %d\n", (flags & (1<<9)) > 0);
    printf("    DF: %d\n", (flags & (1<<10)) > 0);
    printf("    OF: %d\n", (flags & (1<<11)) > 0);
}

int main(void)
{
    long flags = test();

    describe_EFLAGS(flags);

    return 0;
}

<强>输出:

$ gcc flags.c && ./a.out
EFLAGS: 0x246
    CF: 0
    PF: 1
    AF: 0
    ZF: 1
    SF: 0
    TF: 0
    IF: 1
    DF: 0
    OF: 0

<强>参考:

答案 1 :(得分:1)

这是我在VC 2013上运行的内容(在C ++中的警告,32位内联汇编)

在3条指令之前,标志是:

OV = 0 UP = 0 EI = 1 PL = 0 ZR = 0 AC = 0 PE = 0 CY = 0 

3条指令后

OV = 0 UP = 0 EI = 1 PL = 0 ZR = 1 AC = 0 PE = 1 CY = 0 

标志寄存器的位置为defined here

解释为奇偶校验集,进位未设置,零置位,未设置符号,未设置溢出。

这似乎证实了您的解决方案。 我得到的反汇编:

__asm {
    mov ah, 255
00FC13CE  mov         ah,0FFh  
    mov al, -1
00FC13D0  mov         al,0FFh  
    cmp ah, al
00FC13D2  cmp         ah,al  
}

我的8086非常生锈,但FWIW:

  • 如果没有算术,移位或逻辑运算,Sign Flag不太可能被设置。请参阅@ Jonathon的回答。
  • mov在文字-1(255)和255上完成,它不会触发溢出(没有设置标志)。
  • 如果8位寄存器中255-1相等,则应设置零标志。

所以我猜测TA可能会在某个地方粘贴错误的答案吗?