Boucle For Next en asm

Pour discuter de l'assembleur
beauregard
Messages : 1307
Inscription : dim. 08/juil./2007 18:32
Localisation : Toulouse

Boucle For Next en asm

Message par beauregard »

Bonjour,

Dans le cadre d’un développement 6502, pour la console portable Lynx, je souhaite transformer en langage d’assemblage une partie du code C composé de boucle for. Ces boucles sont en effet très gourmandes en ressource machine ! J'imagine que le fonctionnement 6502 et x86 est à peu près le même, avec possibilité de transfert de données dans les registres du CPU et adresse mémoire.

assembleur Lynx: RA65.exe et LYXASS.exe
et un LIBR65.EXE qui doit concerner les librairies.

Ci-dessous, un exemple basique de ma conception, en asm (dans la procédure Vtest():

Code : Tout sélectionner

uchar vac=0x00; // déclaration variable testable en assembleur
uchar vac=0x01; // si j'active cette ligne, la variable vac sera donc mis à 1, ce qui provoquera avec la commande BNE une boucle infini.

void Vtest() 
{
#asm
rretour:
	clc ; mise à 0 de l'Accumulateur
	lda _vac ; charge le contenu de la variable vac dans l'Accumulateur du 6502
	bne rretour ; Si Accumulateur > 0 Alors goto rretour
#endasm
};

// et enfin l'appel de la procédure, donc à placer dans la boucle principale:
Vtest(); // si vac=0x01 alors le programme se bloque comme prévu (c’est juste pour tester voyez).
un autre exemple en asm avec plus de commandes:

Code : Tout sélectionner

// manual clear of collision buffer
void clear_coll_buffer(void) {
#asm
		pha
		phx
		phy
		lda #0
		ldy #10
loop0	ldx #0
loop1	sta $9C60,x
		dex
		bne loop1
		dey
		bne loop0
		ply
		plx
		pla
#endasm
}

******************** LDA STA

Et voici le code en C:

Code : Tout sélectionner

// ** LDA STA ******************************************
// ** Ci-dessous le code à transformer en asm 6502 ***
// *******************************************************

// Tout d'abord, voici la déclaration des variables:

int col_x, tile_x, grpx, lecx, comptx, compty, brnbr, level, tlnb;

uchar tbr01[7][56]=
{
	{0,0,0,0,0,23,24,25,26,27,0,0,0,0,0,0,0,0,0,23,24,25,26,27,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,7},
	{0,0,0,0,0,19,20,21,22,0,0,0,0,0,0,0,0,0,0,19,20,21,22,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,8},
	{0,0,0,0,0,15,16,17,18,0,0,0,0,15,0,0,0,0,0,0,16,17,18,0,0,0,1,7,28,28,28,1,7,0,0,0,0,0,0,0,1,7,0,0,0,0,0,0,0,0,0,0,0,0,2,8},
	{12,13,12,13,12,14,12,14,12,13,12,13,12,14,12,13,12,13,12,13,12,14,12,13,12,13,12,13,12,13,12,13,12,13,12,13,0,0,1,3,2,8,0,0,0,0,0,0,0,0,0,0,0,0,2,8},
	{10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,1,3,5,7,10,11,10,11,10,11,10,11,10,11,10,11,1,3,5,3,2,8,0,0,0,0,0,0,0,0,0,0,0,0,2,8},
	{1,3,5,7,9,9,9,9,9,9,1,3,5,3,5,3,5,3,5,7,2,4,6,8,7,9,9,9,9,9,9,1,3,5,3,5,3,5,5,5,2,8,0,0,0,0,0,0,0,0,0,0,0,0,2,8},
	{2,4,6,8,3,5,3,5,3,5,2,4,6,4,6,4,6,4,6,8,2,4,6,8,8,3,5,3,5,3,5,2,4,6,4,6,4,6,6,6,2,8,3,5,3,5,3,5,3,5,3,5,3,5,2,8}
};



// Ci-dessous, vous voyez le code en C que je souhaite tranformer en asm. Ce code est situé dans la boucle principale :

			col_x+=1;
			if (col_x>23)
				{
				col_x=0;tile_x+=1;
				
				for(grpx=0 ; grpx<6; grpx++) // de 0 à 5, ce qui fait 6 tests voyez.
					{
					for(lecx=(grpx*8) ; lecx<(grpx*8)+8; lecx++) // de 40 à 47, ce qui fait 8
						{
						if (tile_x == 2+lecx)
							{
							comptx = 8+lecx;brnbr = 7*(lecx-(grpx*8));
							for(compty=0 ; compty<7; compty++) // de 0 à 6, ce qui fait 7
								{
								if (level==1)
									{
									tlnb=24;tlnb=tlnb+brnbr;
									SCBDATA(&SCB[tlnb][0])  = dctab[tbr01[compty][comptx]%29];
									SCBX(&SCB[tlnb][0]) = comptx*24;
									SCBY(&SCB[tlnb][0]) = compty*24;
									++brnbr;
									}
								}
							}
						}
					}
					
				}
				
			col_x-=1;
			if (col_x<1)
				{
				col_x=24;tile_x-=1;
				
				for(grpx=0 ; grpx<6; grpx++) // de 0 à 5, ce qui fait 6
					{
					for(lecx=(grpx*8) ; lecx<(grpx*8)+8; lecx++) // de 40 à 47, ce qui fait 8
						{
						if (tile_x == 1+lecx)
							{
							comptx = lecx;brnbr = 7*(lecx-(grpx*8));
							for(compty=0 ; compty<7; compty++) // de 0 à 6, ce qui fait 7
								{
								if (level==1)
									{
									tlnb=24;tlnb=tlnb+brnbr;
									SCBDATA(&SCB[tlnb][0])  = dctab[tbr01[compty][comptx]%29];
									SCBX(&SCB[tlnb][0]) = comptx*24;
									SCBY(&SCB[tlnb][0]) = compty*24;
									++brnbr;
									}
								}
							}
						}
					}
					
				}
source mascot1 (scrolling + test sprite zoom) pour la console Lynx:
http://www.mirari.fr/gBdW
config de mon ordi: seven, directx11, Pentium(R) DualCore E5700, RadeonHD 4550 512MB, PureBasic 4.61 x86
Mesa
Messages : 1093
Inscription : mer. 14/sept./2011 16:59

Re: Boucle For Next en asm

Message par Mesa »

Les puces motorola 6xxx et les puces intel x86 ainsi que leur assembleurs sont très différents et un spécialiste du x86 ne pourra rien faire sur un 6502 et vice versa. Le jeu d'instruction, les registres, les bugs à connaitre (et oui les puces elle-même sont bogguées ! http://fr.wikipedia.org/wiki/MOS_Technology_6502), tout diffère d'une puce à une autre.

C'est vrai que l'assembleur 6502 a l'air simple et doit être assez rapide à apprendre mais t'aurais plus de chance de réponse en postant sur un forum spécialisé dans cette puce.

Pour info, il a été prouvé qu'un compilateur C était toujours plus performant qu'un humain même spécialisé dans l'assembleur. C'est dû au fait que le C est assez bas niveau et qu'à ses débuts tout les ingénieurs et chercheurs du monde se sont rués dessus pour le perfectionner. Mais bon, il est encore possible d'améliorer une boucle par-ci par-là.

Mesa.
Avatar de l’utilisateur
flaith
Messages : 1487
Inscription : jeu. 07/avr./2005 1:06
Localisation : Rennes
Contact :

Re: Boucle For Next en asm

Message par flaith »

Salut

Attention :

Code : Tout sélectionner

clc ; mise à 0 de l'Accumulateur
Ne met pas à 0 l'accumulateur, c'est juste le carry qui est mis à 0
On utilise CLC avant de faire des additions, pour être sûr de ne pas rajouter la retenue
Le CLC est ici inutile :wink:
beauregard
Messages : 1307
Inscription : dim. 08/juil./2007 18:32
Localisation : Toulouse

Re: Boucle For Next en asm

Message par beauregard »

On m'a conseillé d'optimiser, en effectuant les calculs avant l'une des boucles par exemple:
Grpx×8 à chaque itération, c'est lourd, donc stocker dans une variable le résultat, puis utiliser cette variable dans la boucle, au lieu de refaire à chaque le calcul. C'est du bon sens, mais encore faut-il y penser. Une autre astuce consiste à remplacer la multiplication par 8 par <<3

Si vous avez un petit exemple de boucle en asm, même en x86, je suis toujours intéressé.
:mrgreen:
config de mon ordi: seven, directx11, Pentium(R) DualCore E5700, RadeonHD 4550 512MB, PureBasic 4.61 x86
Avatar de l’utilisateur
djes
Messages : 4252
Inscription : ven. 11/févr./2005 17:34
Localisation : Arras, France

Re: Boucle For Next en asm

Message par djes »

Mesa a écrit :Pour info, il a été prouvé qu'un compilateur C était toujours plus performant qu'un humain même spécialisé dans l'assembleur. C'est dû au fait que le C est assez bas niveau et qu'à ses débuts tout les ingénieurs et chercheurs du monde se sont rués dessus pour le perfectionner. Mais bon, il est encore possible d'améliorer une boucle par-ci par-là.
J'ai souvent lu des discussions là-dessus entre les afficionados du C et de l'assembleur. De fait, un compilateur est fait par des pros de l'assembleur ET du C. Le compilo sert pour des codes de grande taille, difficiles et longs à faire en assembleur. Le compilateur est fait par des armées de développeurs qui suivent et travaillent de concert avec les constructeurs (quand ils ne travaillent pas pour eux...).

Mais il ne faut quand même pas oublier plusieurs choses importantes pour nous, les humains : la passion, l'art, le rêve ! Ainsi, il y a quand même de supers bons programmeurs en assembleur (de même qu'il y en a en C...) qui te feront des codes magnifiques qu'aucun compilo ne saurait approcher. Pour plusieurs raisons :
  • le compilo ne connait pas la finalité du code, le plus souvent il ne fait que repérer des motifs qu'il remplace par des codes plus efficaces ; cela ne peut se faire sur l'ensemble d'un code qu'avec plusieurs passes, mais le nombre de passes est forcément limité...
  • la première des optims tient dans l'algo, et les limites des langages de haut niveau ne se retrouvent pas en assembleur. Ainsi, il existe des façons de faire des boucles en assembleur qui n'existent pas en C...
  • Le code modifié est souvent déconseillé, mais il permet de faire des choses bien sympa, comme des protections fortes ; difficile à faire en C.
  • Le code généré est difficile à faire si on ne connait pas l'assembleur... Et ça peut être bien utile !
Bref, il y aura encore longtemps des compétitions entre programmeurs/langages, et pourvu que ça dure ! Vive la diversité :)
Mesa
Messages : 1093
Inscription : mer. 14/sept./2011 16:59

Re: Boucle For Next en asm

Message par Mesa »

Je ne sais pas si peut aider mais voici une boucle en assembleur pour x86.
Les accumulateurs : AX=16 bits, EAX=32bits, RAX=64bits

Code : Tout sélectionner

PUSH EAX ; sauvegarde de l'accumulateur sur la pile au cas où un sous-programme en attente l'utilserait
PUSH ECX ; idem. CX était prévu pour faire des boucles, justement.

MOV ECX, 20 ; On met le compteur (nombre de boucle) à 20

boucle: ; étiquette sur laquelle on va boucler (peut s'écrire différemment suivant les assembleurs

; Mettre les instructions à faire

DEC ECX ; on décrémente ECX de 1 => ECX = ECX - 1

CMP ECX, 0 ; On compare ecx avec 0
JE exit ; jump if equal, si ecx = 0 alors on saute au label exit sinon on continue
JUMP boucle ; on saute vers boucle pour refaire une boucle si ecx <> 0

exit : ; fin de la boucle
POP ECX ; on récupère le ecx comme il était avent la boucle (attention à gérer la pile convenablement)
POP EAX ; idem

; instruction ici
;=================
; Souvent les programmeurs préfère mettre le test en premier, comme ici :
http://stackoverflow.com/questions/6805 ... -jmp-jcond

Il existe plusieurs variantes.
Les x86 ont une instruction spéciale qui simplifie tout :
JECXZ - jump if ECX is zero

On peut aussi comparer des octets directement en mémoire
CMPS[B/D/W] : Compare l'octet/le mot/le double-mot qui se trouve en DS:ESI avec celui qui se trouve en ES:EDI.

Mesa.
beauregard
Messages : 1307
Inscription : dim. 08/juil./2007 18:32
Localisation : Toulouse

Re: Boucle For Next en asm

Message par beauregard »

Mesa a écrit :Je ne sais pas si peut aider mais voici une boucle en assembleur pour x86.
Grand merci, c'est exactement ce type d'exemple qu'il me fallait. Je comprend la théorie de l'assembleur, c'est là le vrai langage. Et pouvoir insérer quelques lignes d'assembleur, c'est comme attraper le pom pom quand on était gosse sur un manège, c'est que du bonheur. :D
Avatar de l’utilisateur
Ar-S
Messages : 9472
Inscription : dim. 09/oct./2005 16:51
Contact :

Re: Boucle For Next en asm

Message par Ar-S »

J'ai une question peut-être bête mais je la pose tout de même...
On peut insérer de l'assembleur dans notre code PB. Mais si je ne m'abuse, lors de la compilation tout est converti (enfin compilé) en assembleur par PB. Donc quel est l'intérêt (hors celui de l'apprentissage) d'insérer de l'ASM dans un code ?
~~~~Règles du forum ~~~~
⋅.˳˳.⋅ॱ˙˙ॱ⋅.˳Ar-S ˳.⋅ॱ˙˙ॱ⋅.˳˳.⋅
W11x64 PB 6.x
Section HORS SUJET : ICI
LDV MULTIMEDIA : Dépannage informatique & mes Logiciels PB
UPLOAD D'IMAGES : Uploader des images de vos logiciels
Avatar de l’utilisateur
djes
Messages : 4252
Inscription : ven. 11/févr./2005 17:34
Localisation : Arras, France

Re: Boucle For Next en asm

Message par djes »

Plusieurs bonnes raisons :
  • L'asm directement concocté par tes soins peut être de meilleure qualité que celui généré par le compilateur de PB. Plus rapide, plus efficace, plus optimisé, plus joli, plus compact, etc.
  • Tu as récupéré un bout de code en assembleur quelque part et tu n'as pas envie de le convertir en PB.
  • Tu as besoin d'une instruction ASM particulière.
  • Tu codes toujours en ASM et tu n'utilises PB que pour des trucs en rapport avec l'API ou les fichiers. (c'est ce que je faisais en Blitz sur Amiga)
  • Tu veux être le seul à comprendre ton code !
etc.
Avatar de l’utilisateur
Ar-S
Messages : 9472
Inscription : dim. 09/oct./2005 16:51
Contact :

Re: Boucle For Next en asm

Message par Ar-S »

En effet ça fait quelques bonnes raisons ;) merci.
~~~~Règles du forum ~~~~
⋅.˳˳.⋅ॱ˙˙ॱ⋅.˳Ar-S ˳.⋅ॱ˙˙ॱ⋅.˳˳.⋅
W11x64 PB 6.x
Section HORS SUJET : ICI
LDV MULTIMEDIA : Dépannage informatique & mes Logiciels PB
UPLOAD D'IMAGES : Uploader des images de vos logiciels
Répondre