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 << E2
E1
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;
}
Große Erklärung, vielen Dank! Das hat sehr geholfen – SimranTea