11
votes

Gaz Vs. Nasm: quel assembleur produit le meilleur code?

Les deux outils traduisent les instructions d'assemblage directement dans le code de la machine, mais est-il possible de déterminer lequel produit le code le plus rapide et le plus propre?


0 commentaires

6 Réponses :


28
votes

Lorsque vous écrivez dans l'assembleur, Vous décrivez précisément les instructions pour générer afin que cela ne dépend pas de l'assembleur. Cela dépend de toi. Il y a une correspondance individuelle entre les mnémoniques que vous écrivez et des instructions réelles dans le code de la machine.


7 commentaires

Techniquement ce n'est pas tout à fait vrai; Pour des choses comme des modes d'adressage, il peut y avoir plus d'une façon de coder le même emplacement. Il y a d'autres isomorphismes que j'ai oubliés; Un assembleur Shareware X86 de retour dans la journée a utilisé ces isomorphismes à un code «digital d'empreinte» assemblé avec elle, en vue d'attraper des tricheurs.


Je comprends ce que tu dis. Il peut y avoir des instructions de code de machine différentes avec un effet similaire. Techniquement, une assembleur peut fournir deux représentations différentes pour ces instructions ( int3 et int 3 ) ou utilisez des indications pour choisir celui à générer. Ces trucs sont généralement documentés pour chaque assembleur. Je suppose que, dans le but de cette question, il est raisonnable d'ignorer ces problèmes depuis théoriquement, Ce sont des instructions vraiment différentes et l'assembleur pourrait vous permettre de choisir parmi un.


Même dans l'assembleur, il y a une place pour optimiser. Beaucoup d'architectures permettent aux modes courts d'adressage, par exemple en utilisant une valeur d'octets pour un déplacement relatif au lieu d'une longue. Étant donné que ces optimisations changent la taille du code d'objet, certains déplacements peuvent être utilisés sous forme abrégée. Une optimisation multiple est donc requise. Afaik Yasm peut faire cela.


Le point est, tandis que les assembleurs peuvent aider, la plupart du temps, vous pouvez toujours forcer l'instruction exacte que vous souhaitez générer.


Si je me souviens bien, NasM en particulier est de «ce que vous écrivez est ce que vous obtenez la persuasion» et générera précisément les opcodes que vous demandez; S'il y a une ambiguïté n'importe où, vous devrez être désambiguement explicitement.


Cela peut également importer si vous devrez peut-être écrire un assemblage sur d'autres plates-formes. C'est bien de les avoir dans le même format et Nasm ne fonctionne que pour X86 / X64.


@Pinael: NASM vous permet de spécifier un "niveau d'optimisation" qui indique en réalité le nombre de passes du code à faire. Comme plus d'adresses sont résolues, les adresses longues peuvent être remplacées par des courtes et ainsi de suite.



4
votes

Il est convaincu ... cela n'oblise pas le code. Cela se traduit comme ça. Donc, le code le plus rapide et le plus propre est produit par programmeur ou compilateur


2 commentaires

Ok l'a eu! Maintenant, l'assembleur est également un compilateur non? Pourrait-il sauver un cycle de la CPU ici et là? C'était mon doute ...


L'assembleur n'est pas un compilateur. Un compilateur repose généralement sur un assembleur. Et assembleur traduit l'assemblage en code OP binaire.



2
votes

Évidemment Nasm car la syntaxe Intel semble beaucoup plus propre que la syntaxe AT & T.


5 commentaires

Oui, le "look" propre compte aussi aussi, je pense.


Je préfère honnêtement la syntaxe AT & T. Je pense que cela transfère l'intention du code plus clair et semble moins encombré. Seulement dommage qu'il y ait si peu de documentation sur elle là-bas.


+1 pour recommander la syntaxe Intel sur AT & T. Les amis ne laissent pas les amis utiliser AT & T.


@Jason haha! Je pense que cela pourrait être ma nouvelle devise. :)


Le gaz soutient également la syntaxe Intel à partir de Binutils-2.10, qui a été publiée en 2000 - pas trop récemment.



1
votes

@brian: Ce n'était pas la question ...

@ cyber98834: Eh bien, un assembleur fait ce que chaque assembleur doit faire: Traduire toutes les instructions à son opcode.

Il n'y a pas d'optimisation.

Oh et aussi, il n'y a pas une chose comme un "code le plus rapide" ... Puis-je vous poser une question? La vitesse de la CPU est statique, n'est-ce pas?

Donc, vous ne pouvez pas faire fonctionner un code plus rapidement car vous ne pouvez pas modifier la vitesse de la CPU.

Mais vous pouvez réduire le code de sorte que la CPU gère moins de la quantité d'instructions, et prend donc moins de temps à courir.

J'espère que vous comprenez ce que j'essaie de dire.

Je vous suggère d'acheter (ou de rechercher des PDF, mais je ne sais pas si c'est légal) Livre noir de la programmation graphique de Michael Abrash qui couvre de nombreuses leçons d'optimisation.


1 commentaires

Salut Sbouazza! Je comprends ton point. Merci! I VE a déjà eu Michael Abrash S Programmation graphique Noir Livre Prêt ( gamedev.net/reference/articles/article1698.asp ) pour plus tard :)



8
votes

Je ne connais pas ces deux outils spécifiques, mais certaines instructions peuvent être codées différemment:

  • ajoutez la hache, 1 est soit 05 01 ou 81 c0 01 ou fe c0
  • int 3 est soit cc ou CD 03
  • Nouveau AVX instructions qui prolongent les instructions de SSE à deux octets auront une 2 -byte ou préfixe de 3 octets. Tous les préfixes de 2 octets peuvent également être codés sous forme de préfixes de 3 octets.

    Ce ne sont que quelques exemples de la tête de ma tête de la manière dont les assembleurs peuvent encoder la même instruction différemment, la question a donc un sens.


5 commentaires

La plupart des assembleurs choisissent généralement l'instruction avec une taille minimale et peuvent fournir des astuces pour vous permettre de choisir spécifiquement celui que vous souhaitez générer. Par exemple, cc et CD 03 sont deux instructions distinctes du point de vue de la CPU. C'est complètement au nom de l'assembleur de choisir de ne pas fournir un moyen de générer une instruction.


Je conviens qu'un bon assembleur devrait le faire. Je souligne juste des façons dont une assembleur peut faire quelque chose de différent. Par exemple, Inc Ax codé en tant que Fe c0 est exactement identique à celui de Ajouter une hache, 1 codé sous 05 01 En ce qui concerne la fonctionnalité et la longueur d'instruction, bien qu'ils soient effectivement décodés séparément dans la CPU.


C'est ce que je cherchais en fait de ma question. Je commence à apprendre l'assemblage x86 (lisez le manuel Intel) et je veux utiliser des outils Linux pour cela, mais il faisait des doutes sur quel outil pour commencer. Puisqu'il ne semble pas que l'essence et le nasme ne véritaient pas une vraie différence, je vais prendre des nasmes à cause du sintax plus amical. Merci pour l'aide!


@Nathanfellman effectivement ajoutez AX, 1 (c.-à-d. 05 01 ) et Inc Ax (c.-à-d. fe c0 ) sont < B> Très Différentes instructions: Le premier affecte tous les drapeaux liés à l'arithmétique, tandis que ce dernier n'affecte pas cf . Un assembleur qui échange un pour un autre est un mauvais assembleur. Je serais surpris si j'ai écrit ajoutez AX, 1; JC transporté et le saut a semblé dépendre de l'état précédent de CF au lieu du résultat de l'addition.


@Ruslan: Vous avez absolument raison. Je n'irais pas si loin de dire qu'ils sont très différents, mais oui, il y a cette différence que j'ai négligée.



5
votes

comme un Sidenote sur la syntaxe-la question. Vous pouvez avoir des travaux de gaz parfaitement bien avec la syntaxe Intel en mettant la ligne suivante en haut de votre fichier source: xxx

J'utilise également la syntaxe Intel pour tous mes besoins assimilés. Il semble beaucoup plus naturel que la syntaxe AT & T. Et cela sauve des frappes de frappe: -).


1 commentaires

le gaz récent . Si vous êtes sur OS / 2, vous pourriez être mal de chance :)