Usando el ensamblador en línea [gcc, intel, c], cómo verificar si el indicador de acarreo se establece después de una operación?compruebe si el indicador de acarreo está establecido
Respuesta
Con saltos condicionales jc
(jump if carry) o jnc
(jump if not carry).
O puede almacenar la bandera de acarreo,
;; Intel syntax
mov eax, 0
adc eax, 0 ; add with carry
ah ok, no conocía los comandos jc, jnc, adc. Thx – hans
Warnin, GCC usa la sintaxis de AT & T. Esta es la sintaxis de Intel ... –
@Fififox, gracias. Edité mi respuesta. –
sbb %eax,%eax
almacenará -1 en eax si se establece el indicador de acarreo, 0 si está claro. No es necesario borrar previamente eax a 0; restar eax de sí mismo hace eso por ti. Esta técnica puede ser muy poderosa ya que puede usar el resultado como máscara de bits para modificar los resultados de los cálculos en lugar de usar saltos condicionales.
Debe tener en cuenta que solo es válido para probar la bandera de acarreo si fue establecida por aritmética realizada DENTRO del bloque de asas en línea. No se puede realizar una prueba de un cálculo que se realizó en código C porque hay muchas formas en que el compilador puede optimizar/reordenar cosas que marcarían la bandera de acarreo.
Sin embargo, el ensamblador x86 está dedicado rápido ALU indica las instrucciones de la prueba denominadas SETcc donde se desea el cc ALU. Por lo tanto se puede escribir:
setc AL //will set AL register to 1 or clear to 0 depend on carry flag
or
setc byte ptr [edx] //will set memory byte on location edx depend on carry flag
or even
setc byte ptr [CarryFlagTestByte] //will set memory variable on location CarryFlagTestByte depend on carry flag
Con SETcc de instrucciones que puede probar banderas como equipaje, cero, señal, desbordamiento o la paridad, algunos SETcc instrucciones permiten poner a prueba dos banderas a la vez.
EDIT: prueba simple Añadido hace en Delphi para desaparecer a dudas sobre plazo rápida
procedure TfrmTest.ButtonTestClick(Sender: TObject);
function GetCPUTimeStamp: int64;
asm
rdtsc
end;
var
ii, i: int64;
begin
i := GetCPUTimeStamp;
asm
mov ecx, 1000000
@repeat:
mov al, 0
adc al, 0
mov al, 0
adc al, 0
mov al, 0
adc al, 0
mov al, 0
adc al, 0
loop @repeat
end;
i := GetCPUTimeStamp - i;
ii := GetCPUTimeStamp;
asm
mov ecx, 1000000
@repeat:
setc al
setc al
setc al
setc al
loop @repeat
end;
ii := GetCPUTimeStamp - ii;
caption := IntToStr(i) + ' ' + IntToStr(ii));
end;
El bucle (iteraciones 1M) wich usando la instrucción fcolor es más de 5 veces más rápido que bucle con adc instriuction.
EDITAR: Se agregó una segunda prueba cuyo resultado de prueba se almacenó en el registro AL comulativo en el registro CL para ser un caso más realista.
procedure TfrmTestOtlContainers.Button1Click(Sender: TObject);
function GetCPUTimeStamp: int64;
asm
rdtsc
end;
var
ii, i: int64;
begin
i := GetCPUTimeStamp;
asm
xor ecx, ecx
mov edx, $AAAAAAAA
shl edx, 1
mov al, 0
adc al, 0
add cl, al
shl edx, 1
mov al, 0
adc al, 0
add cl, al
shl edx, 1
mov al, 0
adc al, 0
add cl, al
shl edx, 1
mov al, 0
adc al, 0
add cl, al
shl edx, 1
mov al, 0
adc al, 0
add cl, al
shl edx, 1
mov al, 0
adc al, 0
add cl, al
shl edx, 1
mov al, 0
adc al, 0
add cl, al
shl edx, 1
mov al, 0
adc al, 0
add cl, al
end;
i := GetCPUTimeStamp - i;
ii := GetCPUTimeStamp;
asm
xor ecx, ecx
mov edx, $AAAAAAAA
shl edx, 1
setc al
add cl, al
shl edx, 1
setc al
add cl, al
shl edx, 1
setc al
add cl, al
shl edx, 1
setc al
add cl, al
shl edx, 1
setc al
add cl, al
shl edx, 1
setc al
add cl, al
shl edx, 1
setc al
add cl, al
shl edx, 1
setc al
add cl, al
end;
ii := GetCPUTimeStamp - ii;
caption := IntToStr(i) + ' ' + IntToStr(ii);
end;
parte Rutina con la instrucción SETcc es todavía más rápido alrededor del 20%.
¿Tiene una cita para llamarlos rápido? No me he mantenido actualizado con la última versión de las últimas generaciones, pero durante mucho tiempo se consideraron lentos códigos de operación. –
@R .. No hay duda: ¡estás equivocado! Verifique la prueba superior! –
@R .. Sí, el SETcc es una instrucción antigua, pero es mucho más rápido que ADC o utiliza saltos cinditional como JC o JNC. –
La primera función realiza la suma sin signo y luego prueba el desbordamiento usando la bandera de acarreo (CF). Los volátiles deben permanecer. De lo contrario, el optimizador reorganizará las instrucciones, lo que garantiza un resultado incorrecto. He visto el optimizador cambiar el jnc
a un jae
(que también se basa en CF).
/* Performs r = a + b, returns 1 if the result is safe (no overflow), 0 otherwise */
int add_u32(uint32_t a, uint32_t b, uint32_t* r)
{
volatile int no_carry = 1;
volatile uint32_t result = a + b;
asm volatile
(
"jnc 1f ;"
"movl $0, %[xc] ;"
"1: ;"
: [xc] "=m" (no_carry)
);
if(r)
*r = result;
return no_carry;
}
La siguiente función es para los enteros con signo. El mismo uso de volátil se aplica. Tenga en cuenta que la matemática entera con signo salta en el indicador OF a través del jno
. He visto el optimizador cambiar esto a jnb
(que también se basa en OF).
/* Performs r = a + b, returns 1 if the result is safe (no overflow), 0 otherwise */
int add_i32(int32_t a, int32_t b, int32_t* r)
{
volatile int no_overflow = 1;
volatile int32_t result = a + b;
asm volatile
(
"jno 1f ;"
"movl $0, %[xo] ;"
"1: ;"
: [xo] "=m" (no_overflow)
);
if(r)
*r = result;
return no_overflow;
}
En la imagen grande, puede utilizar las funciones de la siguiente manera.En el mismo cuadro grande, muchas personas probablemente rechazar el trabajo extra y estética no-belleza hasta PWN'D por un desbordamiento/abrigo/desbordamiento
int r, a, b;
...
if(!add_i32(a, b, &r))
abort(); // Integer overflow!!!
...
El montaje de GCC en línea está disponible en GCC 3.1 y superior. Consulte Assembler Instructions with C Expression Operands, o busque 'Conjunto extendido GCC'.
Por último, el mismo en Visual Studio sería el siguiente (no hay mucha diferencia en la generación de código), pero la sintaxis es mucho más fácil ya MASM le permite saltar a una etiqueta C:
/* Performs r = a + b, returns 1 if the result is safe (no overflow), 0 otherwise */
int add_i32(__int32 a, __int32 b, __int32* r)
{
volatile int no_overflow = 1;
volatile __int32 result = a + b;
__asm
{
jno NO_OVERFLOW;
mov no_overflow, 0;
NO_OVERFLOW:
}
if(r)
*r = result;
return no_overflow;
}
En la parte negativa lado, el código MASM anterior solo es aplicable para el ensamblaje x86. Para el ensamblaje x64, no hay alineación, por lo que deberá codificarlo en ensamblaje (en un archivo separado) y utilizar MASM64 para compilar.
Puede usar la extensión goto para saltar a una etiqueta C usando, por ejemplo, asm volátil goto ("ja% l [clabel]"::: "memoria": clabel) ;, donde clabel es C etiqueta –
Leer debajo de la respuesta por @R .. parece invalidar su función. 'Debe tener en cuenta que solo es válido para probar la bandera de acarreo si fue establecida por aritmética realizada DENTRO del bloque de asas en línea. ¿Está seguro de esto? –
@DrBeco - sí, para GCC, depende. GCC garantizará la "consecutividad" de las instrucciones en su bloque, pero puede insertar/intercalar sus propias instrucciones. Si las instrucciones de GCC no modifican CC, entonces todo estará bien. El ensamblador en línea de Microsoft no sufre las limitaciones de GCC. – jww
- 1. sobre el ensamblaje CF (acarreo) y el indicador OF (desbordamiento)
- 2. GetOpenFileName() con el indicador OFN_ALLOWMULTISELECT establecido
- 3. Compruebe si el archivo ya está abierto
- 4. compruebe si NSNumber está vacío
- 5. Compruebe si "exec" está deshabilitado
- 6. Compruebe si $ _POST-value está vacío
- 7. WP7 compruebe si Internet está disponible
- 8. compruebe si la 1ª opción está seleccionada
- 9. AS3: compruebe si un diccionario está vacío
- 10. Compruebe si el tiempo frontal está habilitado en el dispositivo
- 11. OSX: compruebe si la pantalla está bloqueada
- 12. Compruebe si la cadena está vacía
- 13. Compruebe si una matriz está vacía
- 14. Compruebe si un puerto está abierto
- 15. Compruebe de forma programática si el monitor está apagado
- 16. Compruebe si el objeto está en una lista de objetos
- 17. Compruebe si el sistema de archivos Android está encriptado
- 18. Compruebe si el cliente de SQL Server está instalado
- 19. Compruebe si el parámetro de función está configurado
- 20. compruebe si el archivo de entrada archivado está vacío jquery
- 21. Compruebe si un archivo está abierto
- 22. Compruebe si OpenCV está compilado con TBB
- 23. Compruebe si la consola está presente
- 24. Funciones de listado con indicador de depuración establecido en R
- 25. Compruebe si el socket está escuchando en C
- 26. Compruebe si jQuery está incluido en el encabezado (Joomla)
- 27. Django compruebe si el campo está en blanco?
- 28. Compruebe si un usuario está desconectado en el dispositivo
- 29. Compruebe si la ventana está perdiendo el foco
- 30. Compruebe si la dirección IP está en el rango privado
¿Desea probar esto dentro de un bloque de asm o desea pasar el estado de la bandera de acarreo a algo en el código C en el que su asm está incrustado? –
probando dentro de un bloque de asm es suficiente. repartirlo no debería ser tan difícil. – hans