2016-06-12 12 views
1

Dieser Code wurde mit gcc 5.3.1 kompiliert. Verwendung disassemble mainWie die Addition für lokale und statische Variablen in C und Assembly funktioniert

Das Betriebssystem ist GNU/Linux auf einem Prozessor läuft x86_64

Montageanleitung wurden durch GDB 7,11 erzeugt.


int main() { 
    int i = 0; 
    return ++i; 
} 

push %rbp 
mov %rsp,%rbp 
movl $0x0,-0x4(%rbp) 
addl $0x1,-0x4(%rbp) 
mov -0x4(%rbp),%eax 
pop %rbp 
retq 

int main() { 
    static int i; 
    return ++i; 
} 

push %rbp 
mov %rsp,%rbp 
mov 0x200b54(%rip),%eax 
add $0x1,%eax 
mov %eax,0x200b4b(%rip) 
mov 0x200b45(%rip),%eax 
pop %rbp 
retq 

Im ersten Beispiel direkt die Speicheradresse betrieben wird, auf, wohingegen der Wert in dem letzteren Fall muss zunächst in das Register eax übertragen werden. Kann jemand erklären, was vor sich geht?

+1

Nun, statische Variablen werden nicht auf die gleiche Weise wie lokale Variablen behandelt. Sie müssen in einem bestimmten Teil des Prozessspeichers gespeichert werden. Der Compiler kann sie nicht optimieren oder versucht zumindest nicht, die Extraladung auszuführen. – Bakuriu

+0

Ah okay. Aus irgendeinem Grund dachte ich, alle Operationen mit der ALU müssten über ein Register durchgeführt werden. @Bakuriu –

+1

Die statische Speicherklasse weist den Compiler an, eine lokale Variable während der Laufzeit des Programms zu erstellen, anstatt sie jedes Mal zu erstellen und zu löschen, wenn sie in den Gültigkeitsbereich des Programms gelangt. – mssirvi

Antwort

1

Was passiert, ist, dass Sie gcc nicht angewiesen haben, die Baugruppe zu optimieren. Daher ist die von ihm ausgesendete Baugruppe nicht wirklich repräsentativ für das, was die CPU tun kann. In optimierte Anordnung würden die beiden Sequenzen wahrscheinlich so aussehen:

# adding 1 an automatic variable in register eax 
add $1,%eax 

# alternatively 
inc %eax 

# adding 1 to an automatic variable on the stack 
add $1,12(%rbp) 

# alternatively 
inc 12(%rbp) 

# adding 1 to a static variable 
add $1,i(%rip) 

# alternatively 
inc i(%rip) 

rip ist der Befehlszeiger. Amd64 wird der Zugriff auf statische Variablen in der Regel relativ zum Befehlszeiger ausgeführt, um den PIC-Code zu aktivieren.