English 中文(简体)
x86程序集:INC和DEC指令和溢出标志
原标题:x86 Assembly: INC and DEC instruction and overflow flag

在x86程序集中,当对有符号整数的addsub操作溢出时,会设置溢出标志;当对无符号整数的操作溢出时会设置进位标志。

然而,当谈到inc和dec指令时,情况似乎有所不同。据此网站inc指令根本不影响进位标志。

但我找不到任何关于inc和dec如何影响溢出标志的信息。

当发生整数溢出时,inc或dec是否设置溢出标志?有符号整数和无符号整数的这种行为相同吗?

=========================编辑=============================

好吧,基本上,这里的共识是INC和DEC在设置标志方面应该与ADD和SUB相同,除了进位标志。这也是英特尔手册中所说的。

问题是,当涉及到无符号整数时,我实际上无法在实践中重现这种行为。

考虑以下程序集代码(使用GCC内联程序集可以更容易地打印结果)

int8_t ovf = 0;

__asm__
(
    "movb $-128, %%bh;"
    "decb %%bh;"
    "seto %b0;"
    : "=g"(ovf)
    :
    : "%bh"
);

printf("Overflow flag: %d
", ovf);

这里我们递减一个带符号的8位值-128。由于-128是可能的最小值,因此溢出是不可避免的。正如预期的那样,这会打印出:溢出标志:1

但是,当我们对<em>unsigned</em>值执行相同操作时,行为与我预期的不同:

int8_t ovf = 0;

__asm__
(
    "movb $255, %%bh;"
    "incb %%bh;"
    "seto %b0;"
    : "=g"(ovf)
    :
    : "%bh"
);

printf("Overflow flag: %d
", ovf);

这里我增加一个无符号的8位值255。由于255是可能的最大值,因此溢出是不可避免的。但是,这会打印出:溢出标志:0

嗯?为什么在这种情况下不设置溢出标志?

最佳回答

溢出标志是在操作将导致符号更改时设置的。您的代码非常接近。我能够用以下(VC++)代码设置OF标志:

char ovf = 0;

_asm {
    mov bh, 127
    inc bh
    seto ovf
}
cout << "ovf: " << int(ovf) << endl;

当BH递增时,MSB从0变为1,从而设置OF。

这也设置了OF:

char ovf = 0;

_asm {
    mov bh, 128
    dec bh
    seto ovf
}
cout << "ovf: " << int(ovf) << endl;

请记住,处理器不会区分有符号数字和无符号数字。当您使用2的补码算术时,您可以有一组处理这两种情况的指令。如果要测试无符号溢出,则需要使用进位标志。由于INC/DEC不会影响进位标志,因此在这种情况下需要使用ADD/SUB。

问题回答

英特尔®;64与IA-32体系结构软件开发人员手册

查看相应的手册指令集参考,A-M。每条指令都有精确的文档记录。

以下是INC关于受影响标志的部分:

CF标志不受影响。根据结果设置OF、SZ、ZF、AZ和PF标志。

尝试将测试更改为通过数字而不是硬编码,然后进行一个循环,尝试所有256个数字,以找到影响标志的数字(如果有的话)。或者让asm执行循环,并在它碰到标志时退出,或者当它绕到它开始的数字时退出(从0x00、0x7f、0x80或0xFF以外的数字开始)。

编辑

.globl inc
inc:
    mov $33, %eax

top:
    inc %al
    jo done
    jmp top

done:
    ret

.globl dec
dec:
    mov $33, %eax

topx:
    dec %al
    jo donex
    jmp topx

donex:
    ret

Inc从0x7F变为0x80时溢出。dec从0x80到0x7F时溢出,我怀疑问题出在使用内联汇编程序的方式上。

正如许多其他答案所指出的,INCDEC不会影响CF,而ADDSUB会影响。

然而,还没有说的是,这可能会对性能产生影响。这并不是说你通常会为此烦恼,除非你试图优化例程,但基本上不设置CF意味着INC/DEC只写入部分标志寄存器,这可能会导致部分标志寄存器停滞,请参阅《英特尔64与IA-32体系结构优化参考手册》Agner Fog的优化手册

CPU/ALU只能处理无符号二进制数,然后它使用of、CF、AF、SF、ZF等来决定是将其用作有符号数(of)、无符号数(CF)还是BCD数(AF)。


关于你的问题,记得把二进制数本身看作是无符号的。

**此外,溢出和OF需要3个数字:输入数字、运算中使用的第二个数字和结果数字。

只有当第一个和第二个数字的符号位(最高有效位)的值相同,并且结果的符号不同时,才会激活溢出。如中所示,加2个负数会得到正数,或加2个正数会得到负数:

if( (Sign_Num1==Sign_Num2) && (Sign_Result!=Sign_Num1) ) OF=1;
else OF=0;

对于第一个问题,您使用-128作为第一个数字。第二个数字是隐含的-1,由DEC指令使用。所以我们真的有二进制数0x800xFF。它们都将符号位设置为1。结果是0x7F,这是一个符号位设置为0的数字。我们得到了两个具有相同符号的初始数字,以及一个具有不同符号的结果,因此我们指示溢出-128-1导致127,因此溢出标志被设置为指示错误的签名结果。


对于第二个问题,您使用255作为第一个数字。第二个数字是隐含的1,由INC指令使用。所以我们真的有二进制数0xFF0x01。它们都有不同的符号位,因此不可能发生溢出(只有在基本上加上两个相同符号的数字时才可能发生溢出,但永远不可能用两个不同符号的数字进行溢出,因为它们永远不会超过可能的有符号值)结果是0x00,并且它没有设置溢出标志,因为255+1或者更确切地说,-1+1

请记住,对于要设置的溢出标志,要加/减的2个数字需要具有相同值的符号位,然后结果必须具有与它们不同值的符号位数。

除了进位标志inc之外,它设置标志的方式与加法操作数1相同。

inc不影响进位标志这一事实非常重要。

http://oopweb.com/Assembly/Documents/ArtOfAssembly/Volume/Chapter_6/CH06-2.html#HEADING2-117

处理器所做的是为这些指令的结果设置适当的标志(add、adc、dec、inc、sbb、sub),用于有符号和无符号情况,即每个操作都有两个不同的标志结果。另一种方法是使用两组指令,其中一组设置有符号相关标志,另一组设置无符号相关标志。如果发布编译器在操作中使用无符号变量,则它将测试进位和零(jc、jnc、jb、jbe等),如果有符号,则它测试溢出、符号和零(jo、jno、jg、jng、jl、jle等)。





相关问题
Fastest method for running a binary search on a file in C?

For example, let s say I want to find a particular word or number in a file. The contents are in sorted order (obviously). Since I want to run a binary search on the file, it seems like a real waste ...

Print possible strings created from a Number

Given a 10 digit Telephone Number, we have to print all possible strings created from that. The mapping of the numbers is the one as exactly on a phone s keypad. i.e. for 1,0-> No Letter for 2->...

Tips for debugging a made-for-linux application on windows?

I m trying to find the source of a bug I have found in an open-source application. I have managed to get a build up and running on my Windows machine, but I m having trouble finding the spot in the ...

Trying to split by two delimiters and it doesn t work - C

I wrote below code to readin line by line from stdin ex. city=Boston;city=New York;city=Chicago and then split each line by ; delimiter and print each record. Then in yet another loop I try to ...

Good, free, easy-to-use C graphics libraries? [closed]

I was wondering if there were any good free graphics libraries for C that are easy to use? It s for plotting 2d and 3d graphs and then saving to a file. It s on a Linux system and there s no gnuplot ...

Encoding, decoding an integer to a char array

Please note that this is not homework and i did search before starting this new thread. I got Store an int in a char array? I was looking for an answer but didn t get any satisfactory answer in the ...