2010-10-13 210 views
13

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

Sin embargo, cuando se trata de las instrucciones inc y dec, la situación parece ser algo diferente. De acuerdo con este website, 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, si es que lo hace.

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

============================= EDITAR ============== ===============

Bien, esencialmente el consenso aquí es que INC y DEC deberían comportarse igual que ADD y SUB, en términos de indicadores de configuración, con la excepción de la bandera de llevar. Esto también es lo que dice en el manual de Intel.

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

Consideremos el siguiente código de montaje (usando GCC ensamblado en línea para que sea más fácil para imprimir los resultados.)

int8_t ovf = 0; 

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

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

Aquí disminuir un valor de 8 bits con signo de -128. Como -128 es el valor más pequeño posible, un desbordamiento es inevitable. Como era de esperar, esto imprime: Overflow flag: 1

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

int8_t ovf = 0; 

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

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

Aquí Valor mínimo de un valor sin signo de 8 bits de 255. Dado que 255 es el mayor valor posible, un desbordamiento es inevitable. Sin embargo, esto se imprime: Overflow flag: 0.

¿Huh? ¿Por qué no configuró el indicador de desbordamiento en este caso?

Respuesta

15

El indicador de desbordamiento se establece cuando una operación causaría un cambio de signo. Tu código está muy cerca. Yo era capaz de establecer el de bandera 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 un 0 a un 1, haciendo que el DE a establecer.

Esto también establece el DE:

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 los números con y sin signo. Cuando utiliza la aritmética de complemento de 2, puede tener un conjunto de instrucciones que manejen ambas. Si desea realizar una prueba para el desbordamiento sin firmar, debe usar el indicador de acarreo. Como INC/DEC no afecta al indicador de acarreo, debe usar ADD/SUB para ese caso.

2

Excepto por el indicador de acarreo inc establece las banderas del mismo modo que el operando de agregar 1.

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

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

+0

Excepto 'add' también establece el indicador de desbordamiento si ocurre un desbordamiento de enteros, pero hasta donde puedo ver,' inc' no hace lo mismo. Ver mi pregunta editada para el código de ensamblaje que demuestra esto. – Channel72

+3

@ Channel72 entiende banderas incorrectamente. CF significa llevar a cabo MSB (byte más significativo) como '1111 1111 + 1 = 1 | 0000 0000' CF aquí. CF significa operación inválida (desbordamiento) sin firmar. (porque es 256, que no puede caber en 'byte'). Pero es una operación firmada bastante válida (-1 + 1 = 0). OF es cuando carry es a MSB, como '0111 1111 + 1 = 1000 0000' Esto significa op firmado y no firmado válido firmado (127 + 8 = -128 ups, esto es desbordamiento en caso de firmarse, porque el rango es -128; 127) – Andrey

3

Intel® 64 and IA-32 Architectures Software Developer's Manuals

Mira el manual de Instruction Set Reference, A-M apropiada. Cada instrucción está documentada con precisión.

Aquí es la sección de indicadores afectados INC:

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

+0

Sí, eso fue lo que entendí también. Sin embargo, en la práctica esto no parece suceder realmente. Ver mi pregunta editada para el código de ensamblaje que demuestra esto. – Channel72

3

intente cambiar la prueba para pasar el número en lugar de codificarlo, luego tenga un ciclo que intente los 256 números para encontrar uno que afecte a la bandera. O haga que el asm ejecute el ciclo y salga cuando toque el indicador o cuando se ajuste al número con el que comenzó (comience con algo que no sea 0x00, 0x7f, 0x80 o 0xFF).

EDITAR

 
.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 desbordamientos cuando pasa de 0x7F 0x80. dec desbordamientos cuando va de 0x80 a 0x7F, sospecho que el problema está en la forma en que está usando el ensamblador en línea.

+0

Los enteros con y sin signo son normalmente una manifestación de los lenguajes de programación y no se reflejan en el hardware. No hay un inc. Firmado y un inc. No firmado, es apenas un tipo, universal. Es por eso que OF existe para esta instrucción. Algunos procesadores normalmente no son tan agradables y no proporcionan una forma de detectar resultados sin signo frente a firmado. Me sorprendió ver esta característica en realidad. –

+0

Bueno, hay 'mul' contra' imul' y 'div' contra' idiv' con el conjunto de instrucciones x86 – Channel72

+0

bueno ... normalmente agregar y restar, inc, dec, etc. no se basan en signos porque no tiene sentido. –

3

Como muchas de las otras respuestas han señalado, INCDEC y no afectan a la CF, mientras que ADD y SUB lo hacen.

Lo que no se ha dicho aún, sin embargo, es que esto podría hacer una diferencia en el rendimiento. No es que a usted le moleste eso a menos que intente optimizar una rutina, pero esencialmente no configurar CF significa que INC/DEC solo escribe en parte del registro de banderas, lo que puede causar una bandera parcial puesto de registro, vea Intel 64 and IA-32 Architectures Optimization Reference Manual o Agner Fog's optimisation manuals.

0

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 indicador diferentes para cada operación. La alternativa sería tener dos conjuntos de instrucciones donde uno establece indicadores relacionados con firmas y el otro relacionado con unsigned. Si el compilador emisor está utilizando variables sin firmar en la operación, probará carry y zero (jc, jnc, jb, jbe, etc.), si está firmado, prueba overflow, sign y zero (jo, jno, jg, jng, jl, jle, etc.)

0

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



acerca de su problema, recuerde tener en cuenta los números binarios a sí mismos, como sin signo.

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 de resultado.

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

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


Para su primer problema, que está utilizando -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 como resultado 127, y por lo tanto, el indicador de desbordamiento está configurado para indicar un resultado firmado incorrecto.





Para su segundo problema, que está utilizando 255 como el 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 desbordarse 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 conducirá 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, que obviamente es correcto para la aritmética con signo.

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.

Cuestiones relacionadas