Forum: PC-Programmierung x86 Assembler: XOR ECX, ECX


von Thomas (Gast)


Lesenswert?

Hallo,
bin gerade dabei mir ein Programm mit einem Dissassembler anzusehen. 
Dort findet man öfters mal:
XOR   ECX, ECX
was wohl dazu dient das ECX Register auf 0 zu setzen.
Warum macht man das damit, und nicht mit
MOV ECX, 0
Ist die XOR Lösung schneller oder was hat das für einen Hintergrund?

von (prx) A. K. (prx)


Lesenswert?

MOV: 5 Bytes.
XOR: 2 Bytes.

Dieses XOR wird aufgrund der Häufigkeit heute speziell dekodiert und wie 
eine Art CLR behandelt, um die scheinbare Abhängigkeit vom vorigen Wert 
des Registers zu vermeiden. Wäre sonst effektiv wesentlich langsamer als 
MOV.

von Thomas (Gast)


Lesenswert?

Oh, das ging schnell. Danke.

Ich frage nur wegen möglichen Nebeneffekten, weil ich ein Programm habe 
was wohl objektorientiert programmiert wurde. Laut meinen Informationen 
wird bei den Memberfunktionen der this-Zeiger im ECX-Register übergeben.
Ich habe da ein Programm in dem (so wie es aussieht) in einer Methode 
eine weitere Methode aufgerufen wird. Nach dem Aufruf wird eben ecx auf 
0 gesetzt, und nachher wird es so wie es aussieht nur als Null-Konstante 
weiterverwendet (bin absoluter x86 Assembler Noob muss ich sagen).

Beispiel:

.text:0040ACA0     sub_func1 proc near
.text:0040ACA0
.text:0040ACA0     var_4= dword ptr -4
.text:0040ACA0
.text:0040ACA0 push    ebp
.text:0040ACA1 mov     ebp, esp
.text:0040ACA3 push    ecx
.text:0040ACA4 mov     [ebp+var_4], ecx
.text:0040ACA7 mov     ecx, [ebp+var_4]
.text:0040ACAA call    sub_func2       ; Call Procedure
.text:0040ACAF xor     ecx, ecx
.text:0040ACB1 cmp     dword ptr [eax+4], 0  ; Compare Two Operands
.text:0040ACB5 setz    cl                    ; Set Byte if Zero (ZF=1)
.text:0040ACB8 mov     eax, ecx
.text:0040ACBA mov     esp, ebp
.text:0040ACBC pop     ebp
.text:0040ACBD retn

von Jasch (Gast)


Lesenswert?

Thomas schrieb:
> Oh, das ging schnell. Danke.
>
> Ich frage nur wegen möglichen Nebeneffekten, weil ich ein Programm habe
> was wohl objektorientiert programmiert wurde. Laut meinen Informationen
> wird bei den Memberfunktionen der this-Zeiger im ECX-Register übergeben.

OK, ich gehe mal davon aus.

> Ich habe da ein Programm in dem (so wie es aussieht) in einer Methode
> eine weitere Methode aufgerufen wird. Nach dem Aufruf wird eben ecx auf
> 0 gesetzt, und nachher wird es so wie es aussieht nur als Null-Konstante
> weiterverwendet (bin absoluter x86 Assembler Noob muss ich sagen).

Alles Übung. Und Compiler-Output zu entziffern ist nochmal eine andere 
Sache, Compiler sind ziemlich eigen und ziemlich dumm.

> Beispiel:
>
> .text:0040ACA0     sub_func1 proc near
> .text:0040ACA0
> .text:0040ACA0     var_4= dword ptr -4
> .text:0040ACA0
> .text:0040ACA0 push    ebp
> .text:0040ACA1 mov     ebp, esp
> .text:0040ACA3 push    ecx
> .text:0040ACA4 mov     [ebp+var_4], ecx
> .text:0040ACA7 mov     ecx, [ebp+var_4]

Komischer Code. Versicherung für Register-Spills?

> .text:0040ACAA call    sub_func2       ; Call Procedure

Die Funktion sub_func2 wird aufgerufen

> .text:0040ACAF xor     ecx, ecx

ECX wird auf 0 gesetzt

> .text:0040ACB1 cmp     dword ptr [eax+4], 0  ; Compare Two Operands
> .text:0040ACB5 setz    cl                    ; Set Byte if Zero (ZF=1)

CL (unterste 8 Bit von ECX) wird auf 1 gesetzt falls der Inhalt (32 Bit) 
von Adresse EAX + 4 gleich 0 war, EAX ist vermutlich der Rückgabewert 
der Funktion sub_func2 - ein Pointer auf irgendwas

> .text:0040ACB8 mov     eax, ecx

EAX wird auf ECX gesetzt, d.h. auf 0 oder 1 - vermutlich ein int oder 
bool, EAX ist üblicherweise der Rückgabewert von Funktionen für int, 
bool, Pointer usw.

> .text:0040ACBA mov     esp, ebp
> .text:0040ACBC pop     ebp
> .text:0040ACBD retn

Komisch, der oben per PUSH gesicherte Wert von ECX wird nicht wieder 
hergestellt. Wahrscheinlich wurde das einzige Argument von sub_func1 in 
ECX übergeben?

von (prx) A. K. (prx)


Lesenswert?

Jasch schrieb:

> Komischer Code. Versicherung für Register-Spills?

Eher unoptimierter schematischer Code. Der Parameter wird erst einmal in 
eine lokale Variable verfrachtet und danach sieht man weiter.

> Komisch, der oben per PUSH gesicherte Wert von ECX wird nicht wieder
> hergestellt. Wahrscheinlich wurde das einzige Argument von sub_func1 in
> ECX übergeben?

Die ersten 3 (oder so) Parameter werden in Registern übergeben. Register 
sind per ABI klassifiziert in solche, die eine Funktionen sichern muss 
und solche, wo das nicht der Fall ist. ECX gehört zu denen, die nicht 
gesichert werden.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.