2016-01-25 3 views
5

Ich bin neu in Assembly in C, und ich weiß nicht, wie Sie diesen Fehler beheben. Ich mache eine Funktion, die bedeutet, eine Datei zu schreiben. Was ich habe ist:Warum asm unmögliche Einschränkungen haben, wenn ich Register registriere?

ssize_t mywrite(int fd, const void *buf, size_t count) { 
// return write(fd, buf, count); 
    ssize_t var; 
    __asm__("movl $4,%%eax\n\t" // Write 
     "movl %1,%%ebx\n\t" 
     "movl %2,%%ecx\n\t" 
     "movl %3,%%edx\n\t" 
     "int $0x80\n\t"   // System call 
     "movl %%eax,%0" 
     :"=r"(var) 
     :"r"(fd),"r"(buf),"r"(count) 
     :"%eax","%ebx","%ecx","%edx" 
    ); 
    return var; 
} 

Meine asm soll das gleiche wie schreiben (fd, buf, count); Wenn ich es kompiliere, bekomme ich "'asm' Operand hat unmögliche Einschränkungen". Wenn Sie jedoch die Variablen nicht benennen und die Werte direkt vom Stapel abrufen, erhalte ich keinen Fehler. Hier ist der Code

__asm__("movl $4,%%eax\n\t" 
     "movl 8(%%ebp),%%ebx\n\t" 
     "movl 12(%%ebp),%%ecx\n\t" 
     "movl 16(%%ebp),%%edx\n\t" 
     "int $0x80\n\t" 
     "movl %%eax,%0" 
     :"=r"(var) 
     : 
     :"%eax","%ebx","%ecx","%edx" 
    ); 

ich den zweiten Code verwenden könnte, OFC, aber ich brauche es mit Optimierung kompiliert 2. Dann% ebp nicht zeigen, wo ich brauche es. Ich habe versucht, "a", "b", "c" und "d" anstelle von "r" zu verwenden, aber keinen Erfolg. Jeder könnte helfen? Danke: D

+0

Komponieren Sie zufällig im 64-Bit-Modus? – fuz

Antwort

7

Das Problem ist, dass die Einschränkung r bedeutet Register, aber Ihre CPU hat einfach nicht so viele Register!

können Sie die Einschränkung Speicher verwenden m:

:"m"(fd),"m"(buf),"m"(count) 

, die Anweisungen generieren, wie:

movl 8(%ebp),%ebx 

Aber ich würde die x86 constraints in seiner ganzen Pracht zu verwenden, empfehlen:

ssize_t mywrite(int fd, const void *buf, size_t count) { 
    ssize_t var; 
    __asm__(
     "int $0x80" 
     :"=a"(var) 
     :"0"(4), "b"(fd),"c"(buf),"d"(count) 
    ); 
    return var; 
} 

Das, mit -Ofast gibt:

push %ebx 
mov $0x4,%eax 
mov 0x10(%esp),%edx 
mov 0xc(%esp),%ecx 
mov 0x8(%esp),%ebx 
int $0x80 
pop %ebx 
ret 

Und mit -Os:

push %ebp 
mov $0x4,%eax 
mov %esp,%ebp 
push %ebx 
mov 0x10(%ebp),%edx 
mov 0x8(%ebp),%ebx 
mov 0xc(%ebp),%ecx 
int $0x80 
pop %ebx 
pop %ebp 
ret  

Hinweis, wie durch den Einsatz von Einschränkungen anstelle der Register mit Namen, der Compiler den Code weiter optimieren kann.

+0

Ich habe versucht, die X86-Einschränkungen und es funktioniert jetzt! Vielen Dank! Gut, dass Sie diesen alternativen Weg kennen: D – Behnken

+1

@Behnken: Beachten Sie, dass der load-direkt-from-the-Stack-Weg (2. Weg in Ihrer Frage) bricht, sobald Ihre Funktion inline ist. So ist dieser Weg nicht einmal eine Alternative, er ist nur gebrochen. (Oh, ich denke, das wussten Sie, basierend auf dem Text). Der erste Weg in Ihrer Frage hätte Code erzeugt, der Daten in andere Register geladen hat, und dann Ihre reg-reg-Verschiebungsanweisungen ausgeführt, so dass doppelt so viele Anweisungen benötigt würden wie benötigt. Wie immer schreiben Sie so wenig wie möglich Anweisungen selbst und überlassen Sie es dem Compiler zu entscheiden, wie Sie Daten in Ihre inline-asm hinein- oder herausholen können. –

+0

@PeterCordes Oh, das stimmt ... Ich wusste nicht, dass dieser Weg auf den ersten Blick gebrochen ist. Danke: D Interessant zu bemerken, dass der Code auf diese Weise besser optimiert ist. Wie gesagt, ich bin sehr neu in Asm und fange an zu lernen, tbh. Dies ist ein Ratschlag, den ich mitnehmen werde. Danke, dass du es gegeben hast! – Behnken

Verwandte Themen