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


Anmelden zum Antworten