J'essayais de trouver une assemblée en ligne pour GCC pour obtenir la division et le module à l'aide d'instructions de divl code> divl code>. Malheureusement, je ne suis pas si bon à l'assemblée. Quelqu'un pourrait-il s'il vous plaît aidez-moi à ce sujet? Merci. P>
5 Réponses :
Oui - Un DIVL produira le quotient dans EAX et le reste dans EDX. Utilisation de Syntaxe Intel, par exemple:
mov eax, 17 mov ebx, 3 xor edx, edx div ebx ; eax = 5 ; edx = 2
Jerry, c'est drôle parce que gcc code> n'essaie même pas d'optimiser deux de ces opérations en une. Je vous achèterai une bière si vous pouviez me donner une assemblée GCC afin que je puisse l'utiliser comme une fonction en ligne ou quelque chose de ...
Fausse alarme. Pardon. GCC le fait pour moi si je n'oublie pas de spécifier les indicateurs requis.
Cette réponse est plutôt hors tension, car la question est spécifique à la GCC et vous y répondez avec l'assemblage dans Intel Syntax Charles et Raylu sont tout autour mieux.
@EventRancarroll: Ce qu'il a demandé était une séquence d'instructions de montage qui produirait à la fois le quotient et le reste en utilisant uniquement une seule instruction DIV. Aucun de ces "réponses" ne tente même de fournir cela. Ils sont tous deux des commentaires vraiment, pas des réponses. La seule autre réponse réelle ici est des dosants '.
Non ce n'est pas ce qu'il demande, lisez la question suivante: "J'essayais de trouver Assemblée en ligne pour GCC B> pour obtenir la division et le module à l'aide d'une seule instruction code> DIVL code> . " i>
@Evancarroll: Oui, "asssidbly". Aucune des réponses que vous semblez aimer montrer comment faire la tâche dans la langue d'assemblage du tout i>. Ils viennent juste de défendre l'utilisation de C ++. Ce n'est clairement pas un même vaguement similaire à répondre à la question qu'il a posée.
Vous ne devriez pas essayer d'optimiser cette vous-même. GCC fait déjà cela.
main: pushl %ebp movl %esp, %ebp andl $-16, %esp subl $16, %esp movl some_a, %eax movl some_b, %ecx movl %eax, %edx sarl $31, %edx idivl %ecx movl %edx, 8(%esp) movl %eax, 4(%esp) movl $.LC0, (%esp) call printf movl $0, %eax leave ret
En fait, gcc ne fonctionne pas. Du moins pas avec des drapeaux, je me sers. Peut-être que je manque quelque chose.
Je suis sur GCC (Debian 4.5.2-4) 4.5.2, mais même 4,3 cela. Êtes-vous en train de passer -o?
J'utilise GCC 4.6 .. mais sacrément! J'ai passé 30 minutes à jouer avec cela avant de demander ici et il s'avère que je viens d'oublier de préciser '-O3'. J'avais '-MTune = natif "mais ça n'a pas aidé. Merci! Je devrais avoir un peu de sommeil ...
Pourquoi seulement -o code>? Utilisez au moins
-O2 code> de sorte que GCC peephole le signe-extension dans
edx code> avec
CDQ code> (AKA
CLTD code> in & t Syntaxe, IIRC). Quoi qu'il en soit, si vous écrivez une fonction qui prend deux arguments et stocke les résultats des globaux (ou renvoyez-les comme une structure, ou renvoyez une et rangez l'autre), il évitera d'optimiser l'optimisation mais nécessite moins d'instructions si vous écrivez un < Code> Main () Code> et utilisez
volatile code>. Voir Stackoverflow.com/Questtions/32741032/...
Pour montrer le minimum nécessaire pour obtenir le comportement décrit dans la question.
Ok, mais cela montre gcc rendre le code maladroites, et comment vous devez réellement compiler. (Et BTW, l'OP demandait divl code>, vous auriez pu utiliser
non signé code> ne doit donc à zéro
EDX code> au lieu de signe s'étendant dans EDX: EAX).
Heureusement, vous n'avez pas à recourir à l'assemblage ligne pour y parvenir. gcc fera automatiquement quand il le peut.
$ cat divmod.c code> p>
.file "divmod.c"
.text
.p2align 4,,15
.globl divide
.type divide, @function
divide:
.LFB0:
.cfi_startproc
movq %rdi, %rax
xorl %edx, %edx
divq %rsi
ret
.cfi_endproc
.LFE0:
.size divide, .-divide
.ident "GCC: (GNU) 4.4.4 20100630 (Red Hat 4.4.4-10)"
.section .note.GNU-stack,"",@progbits
Oui tu as raison. S'avère que j'avais trop de bière et j'ai oublié d'allumer des optimisations. Merci. J'ai suscité tout le monde.
Vous cherchez quelque chose comme ceci:
__asm__("divl %2\n" : "=d" (remainder), "=a" (quotient) : "g" (modulus), "d" (high), "a" (low));
"g" code> pour la source opérande n'est pas correct, car DIV ne supporte pas les opérandes immédiats. Utilisez
"rm" code>. (En fait, vous voudrez peut-être
« g » code> si votre code cassera à la compilation si vous jamais vous tirer une balle dans le pied en forçant l'utilisation de DIV lorsque le diviseur est une constante de compilation .) Vous pourriez peut-être aussi utiliser
__ builtin_constant_p code> pour détecter la compilation constante opérandes. Il faut bien travailler avec gcc, mais il évalue clang avant que la fonction inline (donc vous obtenez des faux négatifs).
Voici un exemple dans le code du noyau Linux sur DIVL
/* * do_div() is NOT a C function. It wants to return * two values (the quotient and the remainder), but * since that doesn't work very well in C, what it * does is: * * - modifies the 64-bit dividend _in_place_ * - returns the 32-bit remainder * * This ends up being the most efficient "calling * convention" on x86. */ #define do_div(n, base) \ ({ \ unsigned long __upper, __low, __high, __mod, __base; \ __base = (base); \ if (__builtin_constant_p(__base) && is_power_of_2(__base)) { \ __mod = n & (__base - 1); \ n >>= ilog2(__base); \ } else { \ asm("" : "=a" (__low), "=d" (__high) : "A" (n));\ __upper = __high; \ if (__high) { \ __upper = __high % (__base); \ __high = __high / (__base); \ } \ asm("divl %2" : "=a" (__low), "=d" (__mod) \ : "rm" (__base), "0" (__low), "1" (__upper)); \ asm("" : "=A" (n) : "a" (__low), "d" (__high)); \ } \ __mod; \ })
Voir Stackoverflow.com/Questtions/3323445/... Où je l'ai utilisé comme exemple de MSVC Inline ASM vs. GNU C en ligne ASM. (Y compris une fonction d'emballage DIVL CODE> DIVL CODE> DIVL CODE> En ligne, avec une seule instruction à l'intérieur de l'instruction ASM en ligne, identique à la réponse correcte de D0SSBOots ici.)
Voir aussi Stackoverflow.com/Questtions/32741032/... pour une double duplicata, montrant que vous n'avez pas besoin d'utiliser Inline ASM (le compilateur le fait pour vous), mais aussi montrer comment le faire correctement avec inline ASM. (Pas de différence significative pour la réponse de Dosboot)