2011-07-24 16 views
12

Actualmente estoy aprendiendo el lenguaje de ensamblaje x86 y me pregunto cuál es la mejor manera de implementar bucles. Una forma sería mover un valor al registro ecx y usar la instrucción de bucle y de otro modo usar una instrucción jmp y luego viene el cuerpo del bucle y luego un salto condicional eventualmente al principio del cuerpo del bucle. Supongo que el primero tendrá una mejor legibilidad, pero aparte de eso, no sé por qué usarlo.x86 bucles de programación de ensamblaje con instrucción ecx y loop versus jmp + j <condition>

+0

Nunca supe/sabrá cuándo aceptarlo ya que siempre puede haber una mejor respuesta, supongo? ¿Es esto realmente importante? porque realmente no lo sé – rob

+0

Relacionado: [¿Por qué los loops siempre se compilan de esta manera?] (Https://stackoverflow.com/questions/47783926/why-are-loops-always-compiled-like- this): casi siempre es mejor usar un 'do {} while() 'estructura en asm, con una rama condicional en la parte inferior. Si el ciclo puede necesitar ejecutarse 0 veces, entonces juntar al fondo es una estrategia, pero generalmente no es la mejor. –

Respuesta

12

Cuando mencionas jmp + body + test, creo que estás hablando de la traducción de un bucle while en idiomas de alto nivel. Hay una razón para el segundo enfoque. Vamos a ver.

Considere

x = N 
while (x != 0) { 
    BODY 
    x-- 
} 

La forma ingenua es

mov ecx, N  ; store var x in ecx register 
top: 
    cmp ecx, 0  ; test at top of loop 
    je bottom  ; loop exit when while condition false 
    BODY 
    dec ecx 
    jmp top 
bottom: 

Esto tiene N saltos condicionales y N saltos incondicionales.

La segunda forma es:

mov ecx, N 
    jmp bottom 
top: 
    BODY 
    dec ecx 
bottom: 
    cmp ecx, 0 
    jne top 

Ahora seguimos N saltos condicionales pero sólo lo hacen un salto incondicional. Un pequeño ahorro pero podría importar, especialmente porque está en un bucle.

Ahora se mencionó la instrucción loop que es esencialmente

dec ecx 
cmp ecx, 0 
je somewhere 

¿Cómo trabajar en que? Probablemente así:

mov ecx, N 
    cmp ecx, 0  ; Must guard against N==0 
    je bottom 
top: 
    BODY 
    loop top   ; built-in dec, test, and jump if not zero 
bottom: 

Esta es una pequeña solución típica de los procesadores CISC. ¿Es más rápido que la segunda manera anterior? Eso depende mucho de la arquitectura. Le sugiero que investigue un poco sobre el rendimiento de la instrucción loop en las arquitecturas de los procesadores IA-32 e Intel 64, si realmente quiere saber más.

+0

Gracias, eso ayudó a dejarlo un poco, intentaré hacer más investigaciones sobre la velocidad del ciclo ecx :) – rob

+3

@rob, investigación feliz. ¿Puedo sugerir http://www.agner.org/optimize/optimizing_assembly.pdf? Un recurso increíble. Muy largo. En la página 89 se menciona que debe evitar JECXZ y LOOP porque no son tan eficientes en las arquitecturas más modernas. –

+0

Relacionado: [¿Por qué es lenta la instrucción de bucle? ¿No pudo Intel haberlo implementado de manera eficiente?] (Https://stackoverflow.com/questions/35742570/why-is-the-loop-instruction-slow-couldnt-intel-have-implemented-it-efficiently) para algunos datos históricos factores. Dato curioso: AMD Bulldozer/Ryzen tiene '' loop' rápido, pero nada más lo hace. También relacionado: [¿Por qué los bucles siempre se compilan así?] (Https://stackoverflow.com/questions/47783926/why-are-loops-always-compiled-like-this) para estructuras de bucle eficientes: como dices, condicional rama en la parte inferior, y varias estrategias si es necesario ejecutar 0 veces. –

Cuestiones relacionadas