assembly performance xor cpu-registers x86-16

assembly x86



Forma más eficiente de configurar el registro en 1 o(-1) (4)

Estoy tomando un curso de asamblea ahora, y el chico que revisa nuestras asignaciones es un fanático de la optimización de la vieja escuela. Por ejemplo, deduce el 10% si ve:

mov ax, 0

en lugar de:

xor ax,ax

incluso si solo se usa una vez

No soy un principiante en la programación de montaje, pero no soy un experto en optimización, por lo que necesito su ayuda en algo (podría ser una pregunta muy estúpida, pero lo haré de todos modos): si necesito establecer un valor de registro en 1 o (-1) es mejor usar:

mov ax, 1

o haz algo como:

xor ax,ax inc ax

Realmente necesito una buena calificación, así que estoy tratando de optimizarla lo más posible. (Necesito optimizar el tiempo y el tamaño del código)


Dependiendo de sus circunstancias, es posible que pueda salirse con la suya ...

sbb ax, ax

El resultado será 0 si la bandera de acarreo no está establecida o -1 si la bandera de acarreo está establecida.

Sin embargo, si el ejemplo anterior no es aplicable a su situación, recomendaría el

xor ax, ax inc ax

método. Debería satisfacer a tu profesor por el tamaño. Sin embargo, si su procesador emplea algún revestimiento de tubos, esperaría que haya un retraso similar a un acoplamiento entre las dos instrucciones (podría estar equivocado al respecto). Si existe tal acoplamiento, la velocidad podría mejorarse ligeramente reordenando ligeramente sus instrucciones para tener otra instrucción entre ellas (una que no use hacha).

Espero que esto ayude.


Un Google rápido para el 8086 instructions timings size apareció http://8086.tk/, que parece tener todos los tiempos y tamaños para los 8086 (y más) conjuntos de instrucciones.

Sin duda, puede encontrar Intel doco oficial en la web con información similar.

Para su pregunta específica:

xor ax,ax inc ax

toma 3 + 3 = 6 ciclos de reloj y 2 + 1 = 3 bytes mientras

mov ax,1

toma 4 ciclos de reloj y 3 bytes.

Entonces este último es mejor en ese caso.

Pero debes hablar con tu instituto educativo sobre este tipo. 10% por una cosa tan simple como esa creencia de los mendigos.

Debería preguntar qué debería hacerse en caso de que tenga dos posibilidades, una más rápida y otra más corta.

Luego, una vez que hayan admitido que hay diferentes maneras de codificar dependiendo de lo que intente lograr, dígales que lo que está tratando de lograr es la legibilidad y el mantenimiento y seriamente no podría dar un gran salto sobre un desperdicio. ciclo o byte aquí o allá * a .

La optimización es algo que generalmente se hace siempre y cuando tenga un problema de rendimiento, después de que un fragmento de código se encuentra casi completo: casi siempre se desperdicia esfuerzo cuando el código aún está sujeto a una posibilidad no despreciable de cambio.

Por lo que vale, sub ax,ax parece estar a la par con xor ax,ax en términos de ciclos de reloj y bytes, así que tal vez podrías incluir eso en la mezcla la próxima vez para causarle más trabajo.

* a) No, realmente no, pero es divertido desahogar ocasionalmente :-)


Yo usaría mov [e]ax, 1 bajo cualquier circunstancia. Su codificación no es más larga que la secuencia pirateada xor , y estoy bastante seguro de que es más rápida en cualquier lugar. 8086 es lo suficientemente extraño como para ser la excepción, y como esa cosa es tan lenta, una micro-optimización como esta haría la mayor diferencia. Pero en cualquier otro lugar: la ejecución de 2 instrucciones "fáciles" siempre será más lenta que la ejecución 1, especialmente si se consideran los riesgos de datos y las tuberías largas. Está intentando leer un registro en la instrucción siguiente después de modificarlo, a menos que su CPU pueda eludir el resultado de la etapa N de la canalización (donde se está ejecutando el xor ) hasta la etapa N-1 (donde está el inc. tratando de cargar el registro, no importa agregar 1 a su valor), vas a tener puestos.

Otras cosas a tener en cuenta: ancho de banda de búsqueda de instrucciones (discutible para código de 16 bits, ambos son 3 bytes); mov evita cambiar de banderas (es más probable que sea útil que forzarlas a cero); dependiendo de qué valores puedan contener otros registros, podrías hacer lea ax,[bx+1] (también 3 bytes, incluso en código de 32 bits, sin efecto en flags); como otros han dicho, sbb ax,ax podría funcionar en circunstancias; también es más corto a 2 bytes.

Cuando te enfrentas a este tipo de micro-optimizaciones, realmente debes medir las alternativas en lugar de confiar ciegamente incluso en los manuales del procesador.

PS Nueva tarea: ¿es xor bx,bx más rápida que xor bx,cx (en cualquier procesador)?


Estás mejor con

mov AX, 1

en el 8086. Si está rastreando los contenidos del registro, posiblemente pueda hacerlo mejor si sabe que, por ejemplo, BX ya tiene un 1 en él:

mov AX, BX

o si sabes que AH es 0:

mov AL, 1

etc.