Arrays
-
Hi,
Es gibt ja unterschiede darin, wie man Arrays adressiert. Dieses unterscheidet sich ja folgendermaßen, bei:
1. lokalen Arrays
2. globalen Arrays
3. Arrays, die als Pointer an eine andere Funktion übergeben werden.Bei Nr 1 und 2 kann man einfach adressieren indem man z. B. folgendes macht:
MOV ... [a + EAX] (wobei EAX die Verschiebung enthält)Bei Nr 3 hingegen kann ich das nicht machen, stattdessen muss ich a in ESI oder EDI kopieren und dann geht folgendes:
MOV ... [EDI + EAX]Kann mir mal jemand bitte erklären wieso das so ist?
-
Speicher kann in der x86-32 Architektur durch Offsets und Registerausdrücke (Stichwort: Scale Index Base) adressiert werden: Wenn der pointer nicht in einem Register vorliegt, muss er zuerst in ein Register geladen werden! Die Dereferenzierung eines Arrays, wie in diversen Hochsprachen, ist daher nur in 2 schritten möglich: pointer in Reg. laden und anschießender Zugriff - Beides auf einmal ist nicht möglich.
Dass es in den beiden Ersten Fällen funktioniert, liegt dran, das die Adressen entweder durch ein Offset (globale Variablen) oder in einem Registerausdruck vorliegen (lokale Variablen, z.B.: [ebp-x]). Zu diesen kann man beliebiges Offset hinzufügen als auch das man sie Indexieren kann:
z.B.:
myLocal[eax*2] ==> [ebx+eax*2-x]
myGlobal[eax] ==> [x+eax]Mehr Details über die möglichen Arten der Adressierung findest du in Intels und AMDs Dokumentation
-
Hallo,
Es gibt ja unterschiede darin, wie man Arrays adressiert. Dieses unterscheidet sich ja folgendermaßen, bei:
1. lokalen Arrays
2. globalen Arrays
3. Arrays, die als Pointer an eine andere Funktion übergeben werden.Bei Nr 1 und 2 kann man einfach adressieren indem man z. B. folgendes macht:
MOV ... [a + EAX] (wobei EAX die Verschiebung enthält)a ist auch normalerweise eine Konstante(ist dann im Speicher so), die dann nur auf EAX drauf
addiert wird und das kannst du dann dereferenzieren. Das sieht man auch immer schön beim StackFrame eine Funktion ([ebp-n]).Bei Nr 3 hingegen kann ich das nicht machen, stattdessen muss ich a in ESI oder EDI kopieren und dann geht folgendes:
MOV ... [EDI + EAX]Du hast ja die Konstante an deine Funktion übergeben. Also musst du erstmal auf den Stack zugreifen, den Adresswert nehmen und dann wieder dereferenzieren. Eine direkte Doppeldereferenzierung geht ja nicht. An folgendem listing sieht man das ganz schön:
00401000 /$ 55 PUSH EBP 00401001 |. 8BEC MOV EBP,ESP 00401003 |. 837D 08 00 CMP DWORD PTR SS:[EBP+8],0 00401007 |. 74 14 JE SHORT test.0040101D 00401009 |. 57 PUSH EDI 0040100A |. 50 PUSH EAX 0040100B |. 51 PUSH ECX 0040100C |. 33C0 XOR EAX,EAX 0040100E |. F7D0 NOT EAX 00401010 |. 8B7D 08 MOV EDI,DWORD PTR SS:[EBP+8] 00401013 |. B9 0A000000 MOV ECX,0A 00401018 |. F3:AB REP STOS DWORD PTR ES:[EDI] 0040101A |. 59 POP ECX 0040101B |. 58 POP EAX 0040101C |. 5F POP EDI 0040101D |> C9 LEAVE 0040101E \. C2 0400 RETN 4 00401021 >/$ 68 00304000 PUSH test.00403000 00401026 |. E8 D5FFFFFF CALL test.00401000 0040102B |. 6A 00 PUSH 0 0040102D \. E8 00000000 CALL <JMP.&kernel32.ExitProcess> 00401032 .-FF25 00204000 JMP DWORD PTR DS:[<&kernel32.ExitProcess>]
MfG: sk0r