2014-02-11 3 views
5

den folgenden Quellcode Betrachten, wobei R, S und T sind Konstanten mit #define erklärt:Störungsbestimmungs Konstanten in diesem Assembler-Code zu haben

int A[R][S][T]; 

int store_ele(int i, int j, int k, int *dest) 
{ 

*dest = A[i][j][k]; 
return sizeof(A); 

} 

dieses Programm Bei der Zusammenstellung erzeugt GCC den folgenden Assembler-Code:

i at %ebp+8, j at %ebp+12, k at %ebp+16, dest at %ebp+20 

1. movl 12(%ebp), %edx //move j into register %edx 
2. leal (%edx, %edx, 8), %eax //move address %edx+%edx*9 into %eax 
3. leal (%edx, %eax, 4), %eax //move address %edx + %eax*4 into %eax 
4. imull $111, 8(%ebp), %edx //111*i goes into %edx 
5. addl %edx, %eax 
6. addl 16(%ebp), %eax //add k to %eax 
7. movl A(, %eax, 4), %edx //%eax*4 offset by address of A moved into %edx 
8. movl 20(%ebp), %eax 
9. movl %edx, (%eax) 
10. movl $888, %eax 

ich weiß, dass der letzte Befehl 'movl 888 $,% eax' sagt, dass es 888 Bytes sind, die zu 222 ints entspricht (i j * k *). Wie Sie sehen können, weiß ich, was jede Anweisung macht, aber ich habe Schwierigkeiten, diese zu rekonstruieren, um die Konstanten zu bestimmen, die in i, j und k übergeben werden. i * 111 = i * 3 * 37:

ich keine Antworten erwarten aber keine Hinweise mich in die richtige Richtung weisen würde stark

+0

Welche Version verwenden Sie? –

+0

Nachdem ich mir den Code genauer angesehen hatte, konnte ich feststellen, dass% edx eine Menge Arithmetik durchläuft, dann wird bei Anweisung 9% edx als Dereferenz auf% eax (die zu der Zeit auf die Adresse von A gesetzt wurde) verschoben. . Danke auch an alle, die meinen Beitrag bearbeitet haben, um ein passendes Format zu haben, ich bin ein Neuling auf dieser Seite. – user3296049

+0

Diese Version ist ATT – user3296049

Antwort

7

Die Give-away ist geschätzt. Zuvor wurden die 2 LEA-Anweisungen kombiniert, um eax = 37 * j festzulegen. Hinzufügen von k zur Summe: eax = 3 * 37 * i + 37 * j + k. Da int 4 Bytes ist und die Array-Größe 888 Bytes hat, hat das Array 222 Elemente. Die Array-Dimensionen sind eine Ordnung der Primzahlen: {2,3,37}

zu erweitern:

edx <- j 
eax <- edx + 8 * edx = 9.j 
eax <- edx + 4 * eax = j + 4 * 9j = 37.j 

edx <- i * 111 = 3 * 37.i 
eax <- eax + edx = 3 * 37.i + 37.j 
eax <- eax + k = 3 * 37.i + 37.j + k 

Offensichtlich (i == 2) bringt uns an Element A[222], die außerhalb des Bereichs liegt. So unter der Annahme (i,j,k)-(R,S,T) entspricht, haben wir: R = 2, wobei gilt: (i < 2)

Ähnlich (j == 36) einen Index von mindestens ergibt (36 * 37 = 1332), also muss es in den Prime entsprechen: S = 3, wobei gilt: (j < 3) - die Blätter: T = 37 , wo: (k < 37).

Deshalb haben wir das Array: A[2][3][37], wobei gilt: (i < 2, j < 3, k < 37)

Im Allgemeinen ist der Index: ((((i * S) + j) * T) + k), wobei gilt: (i < R, j < S, k < T)

+0

Brett, danke Sie so sehr für Ihre Hilfe. Ich hoffe, dass ich diese Probleme mit mehr Übung besser verstehen kann. Es ist sehr schwierig zu visualisieren, was eine Liste von asm-Anweisungen manchmal macht – user3296049

+0

Können Sie erklären, warum ich * 111 = i * 3 * 37? –

+0

@David Weil 3 * 37 = 111 –

0

Dies ist, wie ich es bekommen habe, wenn ich falsch bitte korrigieren Sie mich da Ich bin ein Neuling.

1. movl 12(%ebp), %edx // move j into edx 
2. leal (%edx, %edx, 8), %eax // eax = j + j*8 = 9j 
3. leal (%edx, %eax, 4), %eax // eax = j + 4*9j = 37j 
4. imull $111, 8(%ebp), %edx // edx = 111*i 
5. addl %edx, %eax // eax = 111*i + 37j 
6. addl 16(%ebp), %eax // eax = 111*i +37j + k 
7. movl A(, %eax, 4), %edx // edx = A(eax * 4) 
8. movl 20(%ebp), %eax 
9. movl %edx, (%eax) 
10. movl $888, %eax 

in Byte-Adressierung Sie so etwas wie

I want the [111][37][3]-th element 

schreiben würde, aber da Sie eine int Array haben diese Indizes oben müssen unterschiedlich sein (int = 4 Byte, ich gehe davon aus, dass)

111 ist nur faktorisierbar als 3 * 37, da das Speicherlayout angibt, dass k ein Index im innersten Array ist, j ein Index in das mittlere Array und i ein Index in die äußerste Arraygruppierung

(2x2x2 case) 
(((int, int), (int, int)), ((int, int), (int, int))) 

also in einem i = 1, j = 0, k = 0 Fall hätten wir das 111. Element genommen.

Dies bedeutet, dass das Array A[2][3][37] ist, da A [1] [0] [0] 111 * 1 + 37 * 0 + 0 = 111 ergeben würde, genau wie 37 * 3 (alle j- und k-Dimensionen an ihrer Spitze) Kapazität) und A [0] [2] [0] würde 37 * 2 ergeben (und wenn Sie die verbleibenden mit den k Elementen füllen, haben Sie 111, genau den i-Index)

+0

Ich habe die anfänglichen Schleifenindexmultiplikationen durcheinander gebracht, die ich korrigiert habe. Sie scheinen einen ähnlichen Fehler gemacht zu haben - wenn Sie auf Element zugreifen: 'A [0] [36] [0]', ergibt der '37.j' Term:' 1332'! –

+0

Sie haben Recht, ich habe die Indizes in die falsche Reihenfolge gebracht, behoben. Vielen Dank! –

Verwandte Themen