2016-04-24 6 views
0
# x at %ebp+8, n at %ebp+12 
movl 8(%ebp), %esi 
movl 12(%ebp), %ebx 
movl $-1, %edi 
movl $1, %edx 
.L2: 
movl %edx, %eax 
andl %esi, %eax 
xorl %eax, %edi 
movl %ebx, %ecx 
sall %cl, %edx 
testl %edx, %edx 
jne .L2 
movl %edi, %eax 

Ich konvertierte den obigen Code in den folgenden Code, aber ich bin nicht ganz sicher, ob es korrekt ist.Versucht, diesen Assemblycode in C-Code umzuwandeln

int loop(int x, int n){ 

    int result = -1; 

    for (mask = 1; mask >= result; mask = x&1) { 

    result ^= n; 

    } 
return result; 
} 

x und n sind zwei in% EBP Speicher gespeicherten ganzen Zahlen und bewegt% und esi% EBX auf Registrierung. Ergebnis und Maske haben einen Wert von -1 und 1 und das ist vom ersten Teil des Codes Ich denke, nach .L2: startet die Schleife und das ist, wo ich verwirrt bin. Am Endergebnis wird zurückgegeben movl %edi, %eax

Antwort

1

Ihr Code ist völlig falsch. Sie sollten einige Tests selbst durchgeführt haben, bevor Sie Fragen stellen.

Zunächst ist mask in Ihrem Code nicht in Ihrer Funktion deklariert.

Dann, nach mask als int declareing die Funktion loop wird in eine Endlosschleife geraten, wenn result wird über result ^= n; nicht positiv. Auf der anderen Seite wird der Assemblercode nicht in eine Endlosschleife fallen, es sei denn, n ist ein Vielfaches von 32 (einschließlich Null).

Um den Code zu konvertieren Montage:

1. Ich habe direkte Umwandlung von der Montage zu C.

beachte, dass ich unsigned-Typ verwendet, weil uint32_t

  • Verwendung unsigned Typ, weil Linksverschiebungsoperation zu Ganzzahl mit Vorzeichen verursachen undefiniertes Verhalten wenn ein Überlauf occures oder den Wert auf verschoben werden ist negativ.
  • Verwenden Sie uint32_t, da die Größe unsigned int von Umgebungen abhängig ist und weniger als 32 Bit lang sein kann, während die hier verwendeten Register (außer %cl) 32 Bit lang sind.

Quote von N1570 6.5.7 Bitverschiebung Operatoren:

4 Das Ergebnis ist E1 << E2E1 links verschobenen E2 Bitpositionen; Freigegebene Bits werden mit Nullen gefüllt. Wenn E1 einen vorzeichenlosen Typ aufweist, ist der Wert des Ergebnisses E1 × 2 E2, Modulo um einen Wert mehr als der im Ergebnistyp darstellbare Maximalwert reduziert. Wenn E1 einen signierten Typ und einen nichtnegativen Wert hat und E1 × 2 E2 im Ergebnistyp darstellbar ist, dann ist das der resultierende Wert; Andernfalls ist das Verhalten nicht definiert.

Beachten Sie auch, dass stdint.h oder inttypes.h enthalten sein muss uint32_t zu verwenden.

Die zu verschiebende Breite wird in x86-CPUs mit 5 Bit Länge maskiert, dh 80286 oder höher.

uint32_t loop(uint32_t x, uint32_t n) { 
    uint32_t esi = x;    /* movl 8(%ebp), %esi   */ 
    uint32_t ebx = n;    /* movl 12(%ebp), %ebx  */ 
    uint32_t edi = -1;    /* movl $-1, %edi    */ 
    uint32_t edx = 1;    /* movl $1, %edx    */ 
    uint32_t eax, ecx; 
    do {       /* .L2:      */ 
     eax = edx;     /* movl %edx, %eax   */ 
     eax &= esi;    /* andl %esi, %eax   */ 
     edi ^= eax;    /* xorl %eax, %edi   */ 
     ecx = ebx;     /* movl %ebx, %ecx   */ 
     edx <<= (ecx & 0xff) & 31; /* sall %cl, %edx    */ 
    } while (edx != 0);   /* testl %edx, %edx ; jne .L2 */ 
    eax = edi;      /* movl %edi, %eax   */ 
    return eax; 
} 

2. Ich habe Variablennamen eingeführt, um ihre Rollen klar zu machen.

uint32_t loop(uint32_t x, uint32_t n) { 
    uint32_t result = -1; 
    uint32_t mask = 1; 
    uint32_t eax, ecx; 
    do { 
     eax = mask; 
     eax &= x; 
     result ^= eax; 
     ecx = n; 
     mask <<= (ecx & 0xff) & 31; 
    } while (mask != 0); 
    return result; 
} 

3. Ich habe einige Ausdrücke zusammengefügt.

uint32_t loop(uint32_t x, uint32_t n) { 
    uint32_t result = -1; 
    uint32_t mask = 1; 
    do { 
     result ^= mask & x; 
     mask <<= n & 31; 
    } while (mask != 0); 
    return result; 
} 

4. Ich änderte do Schleife zu for Schleife, weil Ihr Versuch es verwendet.

uint32_t loop(uint32_t x, uint32_t n) { 
    uint32_t result = -1; 
    uint32_t mask; 
    for (mask = 1; mask != 0; mask <<= n & 31) { 
     result ^= mask & x; 
    } 
    return result; 
} 

Voll Code zum Testen und demo:

#include <stdio.h> 
#include <inttypes.h> 
#include <limits.h> 

__asm__ (
/* support both environments that does and doesn't add underscore before function name */ 
"loop_asm:\n" 
"_loop_asm:\n" 
"push %ebp\n" 
"mov %esp, %ebp\n" 
"push %esi\n" 
"push %edi\n" 
"push %ebx\n" 

"# x at %ebp+8, n at %ebp+12\n" 
"movl 8(%ebp), %esi\n" 
"movl 12(%ebp), %ebx\n" 
"movl $-1, %edi\n" 
"movl $1, %edx\n" 
".L2_test:\n" /* rename .L2 to .L2_test to avoid collision */ 
"movl %edx, %eax\n" 
"andl %esi, %eax\n" 
"xorl %eax, %edi\n" 
"movl %ebx, %ecx\n" 
"sall %cl, %edx\n" 
"testl %edx, %edx\n" 
"jne .L2_test\n" 
"movl %edi, %eax\n" 

"pop %ebx\n" 
"pop %edi\n" 
"pop %esi\n" 
"leave\n" 
"ret\n" 
); 

uint32_t loop_asm(uint32_t, uint32_t); 

uint32_t loop_convert(uint32_t x, uint32_t n) { 
    uint32_t result = -1; 
    uint32_t mask; 
    for (mask = 1; mask != 0; mask <<= n & 31) { 
     result ^= mask & x; 
    } 
    return result; 
} 

int mask; 
    int loop(int x, int n){ 

    int result = -1; 

    for (mask = 1; mask >= result; mask = x&1) { 

    result ^= n; 

    } 
return result; 
} 

int main(void) { 
    int x, n; 
    uint32_t raw, test, conv; 
    int miss_count = 0; 
    /* search for mismatch in some range */ 
    for (n = 1; n < 32; n++) { 
     uint32_t x_test; 
     for (x_test = 0; x_test < UINT32_C(100000); x_test++) { 
      if (loop_asm(x, n) != loop_convert(x, n)) { 
       printf("mismatch at x=%"PRIu32", n=%d\n", x_test, n); 
       if (miss_count < INT_MAX) miss_count++; 
      } 
     } 
    } 
    printf("%d mismatch(es) found.\n", miss_count); 
    /* print some examples */ 
    x = 100; 
    n = 5; 
    raw = loop_asm(x, n); 
    conv = loop_convert(x, n); 
    printf("loop_asm(%d, %d) = %"PRIu32"\n", x, n, raw); 
    printf("loop_convert(%d, %d) = %"PRIu32"\n", x, n, conv); 
    fflush(stdout); 
    test = loop(x, n); 
    printf("loop(%d, %d) = %"PRIu32"\n", x, n, test); 
    return 0; 
} 
+0

Große Erklärung, vielen Dank! Das hat sehr geholfen – SimranTea