2016-05-04 7 views
2

Ich versuche, eine einfache Prozedur in x86-64 Assembly schreiben, die einfach die Länge eines Array von Ints zurückgibt. Das letzte Element im Array ist eine 0, die nicht gezählt werden sollte. Das Array wird als int * vom C-Code übergeben.Array-Element Vergleich in x86-64 Assembly (AT & T-Syntax)

Mein Assembler-Code ist wie folgt:

f1: 
    movq $0, %rax # zero out %rax 
    jmp test  # jump to test 
body: 
    incq %rax  # increment %rax, which is counter and array index 

test: 
    cmpq $0, (%rdi,%rax,4) # compare (rdi + (rax * 4)) to 0 
    jne body # jump if zero flag is not set 
ret 

Wenn diese läuft, bekomme ich ein Ergebnis, das nicht richtig, aber nicht wild falsch entweder, also statt 11 (Größe des Arrays bestanden minus endet 0) Ich bekomme 38. Was ich denke ist, dass meine Vergleichsaussage falsch ist. Mein Denken war, dass, da Cmpq führt (dest - src), ohne die Register zu ändern, wenn der Array-Index 0 ist, würde 0-0 eine Null ergeben, so dass die Null-Flag gesetzt wäre, aber das scheint nicht zu passieren.

Ich kann willkürlich jedes Element des Arrays in% rax laden, die den richtigen Wert zurückgibt:

movq (%rdi,%rax,4), %rax # %rax initially 0, so first element loaded into %rax 

Jede Hilfe wäre sehr dankbar!

+0

Gut gemacht, deinen Code sehr kurz haltend, nur der Teil, der nicht tut, was du denkst, dass es sollte, und um zu erklären, was du denkst, sollte passieren, also war es einfach, genau das zu erklären Thing. –

Antwort

2

int ist 32 Bit (4 Byte) in beiden x86-64 ABIs (SystemV und Windows). (Siehe das Tag Wiki für Details).

cmpq $0, (%rdi,%rax,4) skaliert den Index korrekt um 4, , verwendet jedoch falsch 64-Bit-Operandengröße. (q steht für Quadwort. In Intel x86-Terminologie ein "Wort" ist 16 Bits.)

cmpq wurde der Vergleich von zwei aufeinanderfolgenden Elementen. Die äquivalent C while(0 != *(int64_t*)&(array[i])){ ++i; }


Außerhalb x86 wäre, ist ein Wort, in der Regel das Register Größe der Maschine oder so ähnlich, so dass sie paßt die Größe von long. z.B. Ein Wort ist 32 Bit auf 32bit MIPS.

Es ist nur Terminologie, und es ist praktisch, bequem Namen wie Wort zu haben (AT & T Syntax w Suffix), dword (l Suffix), qword (q Suffix).

In gdb, an einigen Stellen "Wort" ist auch 32bits, wenn x86 Debugging (zB x Befehlsspeicher haben b (Byte) abzuladen, h (Halbwort: 16b), w (Wort) und g (Riese : 8B) Größenformatbezeichner

+0

Vielen Dank, und für die extra Trivia auch. Ich änderte die Anweisung zu 'Cmpl' und die richtigen Werte zurückgegeben werden, aber ich bin mir nicht sicher, warum ich verstehe. Ist die Operand-Größe Auswirkungen auf die Scali ng Wert für den Offset? – joezuu

+0

@joezuu: Nein, Ihre Adressierung war immer korrekt. Aktualisierte die Antwort mit dem, was 'cmpq' tatsächlich tat. –