2013-10-24 16 views
9

Ich schrieb das folgende Programm:Warum JLE anstelle von JL verwenden?

#include <stdio.h> 

int main() 
{ 
    int i = 0; 
    for (; i < 4; i++) 
    { 
     printf("%i",i); 
    } 

    return 0; 
} 

ich es gcc test.c -o test.o mit kompiliert, dann objdump -d -Mintel test.o mit zerlegt. Der Assembler-Code Ich habe (zumindest der betreffende Teil) ist die folgende:

0804840c <main>: 
804840c: 55      push ebp 
804840d: 89 e5     mov ebp,esp 
804840f: 83 e4 f0    and esp,0xfffffff0 
8048412: 83 ec 20    sub esp,0x20 
8048415: c7 44 24 1c 00 00 00 mov DWORD PTR [esp+0x1c],0x0 
804841c: 00 
804841d: eb 19     jmp 8048438 <main+0x2c>   
804841f: 8b 44 24 1c    mov eax,DWORD PTR [esp+0x1c] 
8048423: 89 44 24 04    mov DWORD PTR [esp+0x4],eax 
8048427: c7 04 24 e8 84 04 08 mov DWORD PTR [esp],0x80484e8 
804842e: e8 bd fe ff ff   call 80482f0 <[email protected]> 
8048433: 83 44 24 1c 01   add DWORD PTR [esp+0x1c],0x1 
8048438: 83 7c 24 1c 03   cmp DWORD PTR [esp+0x1c],0x3 
804843d: 7e e0     jle 804841f <main+0x13> 
804843f: b8 00 00 00 00   mov eax,0x0 
8048444: c9      leave 
8048445: c3      ret 

Ich bemerkte, dass, obwohl meine Vergleichsoperation i < 4 war, die Assembler-Code (nach der Demontage) ist i <= 3. Warum passiert das? Warum würde es JLE anstelle von JL verwenden?

+3

Das ist wahrscheinlich Code-Gen, das eine anschließende Optimierung, wie Schleife Abrollung fördert. Was nicht passiert ist, vermeiden Sie, unoptimierten Code zu betrachten. –

+0

Dies ist eigentlich eine GCC-Code-Generation Wahl (Sie müssen in die Baumdarstellung des Codes graben), aber es macht einen 'var Petesh

Antwort

5

Loops, die aufwärts zählen und eine konstante Grenze haben, sind sehr häufig. Der Compiler verfügt über zwei Optionen zum Implementieren der Überprüfung auf Schleifenabschluss - JLE und JL. Während die beiden Möglichkeiten absolut gleichwertig erscheinen, sollten Sie folgendes beachten.

Wie Sie in der Demontage-Liste sehen können, ist die Konstante (3 in Ihrem Fall) in 1 Byte codiert. Wenn Ihre Schleife zu 256 statt zu 4 gezählt würde, wäre es impossible, eine so effiziente Codierung für die CMP Anweisung zu verwenden, und der Compiler müsste eine "größere" Codierung verwenden. So bietet JLE eine geringfügige Verbesserung der Codedichte (was aufgrund der Zwischenspeicherung letztendlich für die Leistung gut ist).

0

Es wäre JLE, weil es den Wert um eins verschoben hat.

if (x < 4) { 
    // ran when x is 3, 2, 1, 0, -1, ... MIN_INT. 
} 

ist logisch äquivalent zu

if (x <= 3) { 
    // ran when x is 3, 2, 1, 0, -1, ... MIN_INT. 
} 

Warum der Compiler eine interne Darstellung über eine andere ist oft eine Frage der Optimierung gewählt haben, aber eigentlich ist es schwer zu wissen, ob die Optimierung der wahre Fahrer war. In jedem Fall sind funktionale Äquivalente wie diese der Grund, warum das Rückmapping nicht 100% genau ist. Es gibt viele Möglichkeiten, eine Bedingung zu schreiben, die über die gleichen Eingaben die gleiche Wirkung hat.

Verwandte Themen