Ensamblaje x86: indicador de desbordamiento e instrucción INC y DEC

En el ensamblaje x86, el indicador de desbordamiento se establece cuando se desborda una operación de add o sub en un entero con signo, y el indicador de acarreo se establece cuando se desborda una operación en un entero sin signo.

Sin embargo, cuando se trata de las instrucciones inc y dec , la situación parece ser algo diferente. Según este sitio web , la instrucción inc no afecta en absoluto a la bandera de acarreo.

Pero no puedo encontrar ninguna información sobre cómo inc y dec afectan el indicador de desbordamiento, en todo caso.

¿ inc o dec establece el indicador de desbordamiento cuando se produce un desbordamiento de entero? ¿Y este comportamiento es el mismo para los enteros con signo y sin signo?

============================= EDIT ==================== =========

De acuerdo, esencialmente, el consenso aquí es que INC y DEC deben comportarse de la misma manera que ADD y SUB, en términos de establecer banderas, con la excepción de la bandera carry. Esto es también lo que dice el manual de Intel.

El problema es que en realidad no puedo reproducir este comportamiento en la práctica, cuando se trata de enteros sin signo.

Considere el siguiente código de ensamblaje (usar el ensamblaje en línea de GCC para facilitar la impresión de los resultados).

 int8_t ovf = 0; __asm__ ( "movb $-128, %%bh;" "decb %%bh;" "seto %b0;" : "=g"(ovf) : : "%bh" ); printf("Overflow flag: %d\n", ovf); 

Aquí decrementamos un valor de 8 bits firmado de -128. Dado que -128 es el valor más pequeño posible, es inevitable un desbordamiento. Como se esperaba, esto se imprime: Overflow flag: 1

Pero cuando hacemos lo mismo con un valor sin signo , el comportamiento no es el que esperaba:

 int8_t ovf = 0; __asm__ ( "movb $255, %%bh;" "incb %%bh;" "seto %b0;" : "=g"(ovf) : : "%bh" ); printf("Overflow flag: %d\n", ovf); 

Aquí incremento un valor de 8 bits sin firmar de 255. Dado que 255 es el valor más grande posible, es inevitable un desbordamiento. Sin embargo, esto se imprime: Overflow flag: 0 .

Eh ¿Por qué no estableció la bandera de desbordamiento en este caso?

El indicador de desbordamiento se establece cuando una operación causaría un cambio de signo. Tu código está muy cerca. Pude establecer la marca OF con el siguiente código (VC ++):

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

Cuando BH se incrementa, el MSB cambia de 0 a 1, lo que hace que se configure el OF.

Esto también establece el OF:

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

Tenga en cuenta que el procesador no distingue entre números firmados y no firmados. Cuando usa la aritmética de complemento de 2, puede tener un conjunto de instrucciones que manejen ambas. Si desea realizar una prueba de desbordamiento sin firmar, debe utilizar el indicador de acarreo. Como INC / DEC no afecta el indicador de acarreo, debe usar ADD / SUB para ese caso.

Manuales de desarrollador de software de architectures Intel® 64 e IA-32

Mire el manual de referencia del conjunto de instrucciones apropiado , AM . Cada instrucción está documentada con precisión.

Aquí está la sección INC en las banderas afectadas:

La bandera CF no se ve afectada. Los indicadores OF, SZ, ZF, AZ y PF se configuran de acuerdo con el resultado.

intente cambiar su prueba para pasar el número en lugar de codificarlo, luego tenga un bucle que pruebe los 256 números para encontrar el que, si alguno, afecta a la bandera. O haga que el asm realice el bucle y salga cuando toque la bandera y o cuando se ajuste al número con el que comenzó (comience con algo distinto a 0x00, 0x7f, 0x80 o 0xFF).

EDITAR

 .globl inc
 Cía:
     mov $ 33,% eax

 parte superior:
     inc% al
     jo hecho
     jmp top

 hecho:
     jubilado

 .globl dec
 dic:
     mov $ 33,% eax

 topx:
     dec% al
     jo donex
     jmp topx

 donex:
     jubilado

Inc se desborda cuando va de 0x7F a 0x80. dec se desborda cuando va de 0x80 a 0x7F, sospecho que el problema está en la forma en que está utilizando un ensamblador en línea.

Como muchas de las otras respuestas han señalado, INC y DEC no afectan la CF , mientras que ADD y SUB sí lo hacen.

Sin embargo, lo que aún no se ha dicho es que esto podría hacer una diferencia de rendimiento. No es que normalmente te moleste a menos que estés tratando de optimizar el infierno fuera de una rutina, pero esencialmente no establecer el CF significa que INC / DEC solo escribe en parte del registro de banderas, lo que puede causar un registro parcial de bandera parada , consulte el Manual de referencia de optimización de architectures Intel 64 y IA-32 o los manuales de optimización de Agner Fog .

Excepto por el indicador de acarreo, inc establece los indicadores de la misma manera que lo haría el operando 1.

El hecho de que inc no afecta a la bandera de acarreo es muy importante.

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

Lo que hace el procesador es establecer los indicadores apropiados para los resultados de estas instrucciones (agregar, adc, dec, inc, sbb, sub) para los casos firmados y no firmados, es decir, dos resultados de indicadores diferentes para cada operación. La alternativa sería tener dos conjuntos de instrucciones donde uno establece indicadores relacionados con la firma y el otro los relacionados sin firmar. Si el comstackdor emisor utiliza variables sin signo en la operación, probará acarreo y cero (jc, jnc, jb, jbe, etc.), si está firmado, comprueba el desbordamiento, el signo y el cero (jo, jno, jg, jng, jl, jle, etc. ).

La CPU / ALU solo es capaz de manejar números binarios sin firmar, y luego usa OF, CF, AF, SF, ZF, etc., para permitirle decidir si usarlo como un número firmado (OF), un número sin signo (CF) o un número BCD (AF).



Sobre su problema, recuerde considerar los números binarios en sí mismos, como sin firmar.

Además, el desbordamiento y el OF requieren 3 números: el número de entrada, un segundo número para usar en la aritmética y el número del resultado.

El desbordamiento se activa solo si los números primero y segundo tienen el mismo valor para el bit de signo (el bit más significativo) y el resultado tiene un signo diferente. Al igual que en, la adición de 2 números negativos dio lugar a un número positivo, o la adición de 2 números positivos dio lugar a un número negativo:

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


Para su primer problema, está usando -128 como el primer número. El segundo número es implícitamente -1 , utilizado por la instrucción DEC. Así que realmente tenemos los números binarios 0x80 y 0xFF . Ambos tienen el bit de signo establecido en 1. El resultado es 0x7F , que es un número con el bit de signo establecido en 0. Obtuvimos 2 números iniciales con el mismo signo y un resultado con un signo diferente, por lo que indicamos un desbordamiento . -128-1 dio -128-1 resultado 127 y, por lo tanto, el indicador de desbordamiento se establece para indicar un resultado con firma incorrecta.





Para su segundo problema, está utilizando 255 como primer número. El segundo número es implícitamente 1 , utilizado por la instrucción INC. Así que realmente tenemos los números binarios 0xFF y 0x01 . Ambos tienen un bit de signo diferente, por lo que no es posible obtener un desbordamiento (solo es posible desbordar cuando se agregan básicamente 2 números del mismo signo, pero nunca es posible desbordar con 2 números de un signo diferente porque Nunca llevará a ir más allá del posible valor firmado). El resultado es 0x00 y no establece el indicador de desbordamiento porque 255+1 , o más exactamente, -1+1 da 0, lo que obviamente es correcto para la aritmética firmada.

Recuerde que para establecer el indicador de desbordamiento, los 2 números que se agregan / restan necesitan tener el bit de signo con el mismo valor, y luego el resultado debe tener un bit de signo con un valor diferente al de ellos.