2010-03-01 12 views
5

Cuando se usa una instrucción continue dentro de un bucle en código C, GCC crea una nueva etiqueta con una instrucción nop justo antes del final del bloque de bucle y salta hacia ella, en lugar de saltar hasta el final del bloque de bucle en sí. Por ejemplo, el siguiente código CConjunto generado por GCC equivalente a instrucción continue en C

for (i=0; i<10; i++) { 
    puts("blah\n"); 
    if (i < 10) continue; 
    puts("This shouldn't be printed.\n"); 
} 

produce los siguientes equivalente ASM (usando -S gcc):

movl $0, 28(%esp) 
    jmp L2 
L5: 
    movl $LC0, (%esp) 
    call _puts 
    cmpl $9, 28(%esp) 
    jle L7 
L3: 
    movl $LC1, (%esp) 
    call _puts 
    jmp L4 
L7: 
    nop 
L4: 
    incl 28(%esp) 
L2: 
    cmpl $9, 28(%esp) 
    jle L5 

(El si (i < se inserta 10) parte para que el compilador doesn' t "optimizar" la sección eliminando lo que sigue a la instrucción continue)

Mi pregunta es, ¿por qué no saltar directamente a L4? IMO podríamos pasar a L4, ¿me estoy perdiendo algo?

Respuesta

4

Lo que estás describiendo es una optimización. Sin duda, si le dice a gcc que optimice (-O1 es suficiente), hará exactamente lo que usted describe.

+0

Gracias por la respuesta rápida! -O1 hizo el truco, aunque el flujo del programa después de la optimización parece algo menos intuitivo ahora, a menos que esté equivocado, el bucle parece parcialmente desenrollado ahora. Ahora tengo curiosidad sobre si hay algún incentivo para crear la etiqueta con la instrucción nop. ¿Hay alguna situación en la que este enfoque evite que ocurra algo si se quiere saltar directamente a L4? – susmits

+0

Con fines de depuración, puede establecer un punto de interrupción en la etiqueta L7; sería difícil romper el caso continuo si no estuviera allí. – nos

+0

@susmits: con -O1, el ensamblaje es menos detallado, pero el ciclo no se desenrolla (con -O3 puede ver la versión desenrollada, observe que ni siquiera incluye el control i <10 o el segundo puts()) . En general, crear la etiqueta y no realizar dichas optimizaciones ayuda mucho en la depuración. –

1

Supongo que es un marcador de posición para algún tipo de secuencia de reparación de código omitido. Quizás el nop a veces se reemplaza con instrucciones para almacenar registros en la pila o algo así.

Pero para obtener más evidencia de esto, sería útil encontrar un ejemplo donde el nop se sustituye por otra cosa.

+0

Creo que esto es probablemente así. En este caso, hay tan pocas variables involucradas que el conjunto de variables en los registros en "continuar" sea el mismo que el conjunto de variables en los registros después de las segundas. Si ese no era el caso, entonces después de L7 sería el código para sincronizarlos. Si hubiera múltiples "continuas" en el ciclo, entonces cada uno todavía tendría que sincronizarse con el estado correcto de L7 antes de saltar, por supuesto. –

+0

Por otro lado, colocar dicho código en un bloque asociado con una declaración de continuar es extremadamente ineficiente, así que supongo que es una vista bastante rara de todos modos. –

+0

Tenga en cuenta que susmits ha solicitado implícitamente código ineficaz (al no especificar -O) ;-) –

Cuestiones relacionadas