Bug dans la wiki 6502?

Tout ce qui concerne le logiciel original et sa sauvegarde avec entre autre la régénération des disquettes ou autres supports physiques.

Modérateurs : Papy.G, fneck, Carl

Répondre
__sam__
Messages : 7964
Inscription : 18 sept. 2010 12:08
Localisation : Brest et parfois les Flandres

Bug dans la wiki 6502?

Message par __sam__ »

Voulant comprendre un peu mieux l'asm 6502 je suis tombé sur le code du memcpy de la wikipedia:

Code : Tout sélectionner

                ; memcpy --
                ; Copy a block of memory from one location to another.
                ;
                ; Entry parameters
                ;      SRC - Address of source data block
                ;      DST - Address of target data block
                ;      CNT - Number of bytes to copy
 
0040                        ORG     $0040       ;Parameters at $0040
0040  00 00     SRC         DW      $0000
0042  00 00     DST         DW      $0000
0044  00 00     CNT         DW      $0000
 
0600                        ORG     $0600       ;Code at $0600
0600  A4 44     MEMCPY      LDY     CNT+0       ;Set Y = CNT.L
0602  D0 05                 BNE     LOOP        ;If CNT.L > 0, then loop
0604  A5 45                 LDA     CNT+1       ;If CNT.H > 0,
0606  D0 01                 BNE     LOOP        ; then loop
0608  60                    RTS                 ;Return
0609  B1 40     LOOP        LDA     (SRC),Y     ;Load A from ((SRC)+Y)
060B  91 42                 STA     (DST),Y     ;Store A to ((DST)+Y)
060D  88                    DEY                 ;Decr CNT.L
060E  D0 F9                 BNE     LOOP        ;if CNT.L > 0, then loop
0610  E6 41                 INC     SRC+1       ;Incr SRC += $0100
0612  E6 43                 INC     DST+1       ;Incr DST += $0100
0614  88                    DEY                 ;Decr CNT.L
0615  C6 45                 DEC     CNT+1       ;Decr CNT.H
0617  D0 F0                 BNE     LOOP        ;If CNT.H > 0, then loop
0619  60                    RTS                 ;Return
061A                        END
Or j'ai l'impression qu'il ne marche pas si l'on copie moins de 256 octets. En effet si on l'appelle avec CNT=1 (on ne copie qu'un seul octet), le BNE LOOP en 0617 sera faux (CNT+1 contient 0), et on ira copier pleins d'autre octets.

Est-ce que je me trompe ou pas dans l'analyse du programme ? Qu'en pensent les spécialistes 6502 ?
Samuel.
A500 Vampire V2+ ^8^, A1200 (030@50mhz/fpu/64mb/cf 8go),
A500 GVP530(MMU/FPU) h.s., R-Pi, TO9, TO8D, TO8.Démos
bilbo

Re: Bug dans la wiki 6502?

Message par bilbo »

En fait si CNT+0 = 0
Et CNT+1 1 contient 1

On a déja chargé 0 dans Y la séquence:

DEY Y = 0 - 1 = 255
BNE détecte en fait le retour a zéro c'est a dire une boucle complète

donc avec CNT+0 = 0 et CNT+1 = 1 on auras bien copié 256 octets

Notez que l'on copie avant de comparer...

Je suis un peu rouillé :)
__sam__
Messages : 7964
Inscription : 18 sept. 2010 12:08
Localisation : Brest et parfois les Flandres

Re: Bug dans la wiki 6502?

Message par __sam__ »

Dans ton cas oui on copie 256 octets.. mais le pb se trouve quand on copie 1 octet par exemple: CNT+0 contient 1 et CNT+1 contient 0.

A l'entrée Y contient le 1, fait la copie puis est décrémenté (ligne 0614). Tout est bon. Le test BNE est faux, on ajoute donc 256 à SRC et DST (sur 16bits), on décrémente y (qui vaut alors 255) et on décrémente CNT+1 (ligne 0615) qui vaut alors 255 (il était à 0 au début). Le BNE de 0617 est donc vrai et on repart vers LOOP au lieu de sortir.

Donc je crois bien que cet algo est faux pour toutes les valeurs ayant CNT+1 à 0 à l'entrée, c'est à dire la copie de moins de 255 octets.
Samuel.
A500 Vampire V2+ ^8^, A1200 (030@50mhz/fpu/64mb/cf 8go),
A500 GVP530(MMU/FPU) h.s., R-Pi, TO9, TO8D, TO8.Démos
bilbo

Re: Bug dans la wiki 6502?

Message par bilbo »

C'est exact si CNT+0 = 1 et CNT+1 = 0

1 octet est bien copié
et src et dst sont bien perdu (incrémenté)
mais le C spécifie t'il que les pointeurs sont conservées après l'appel

Pour moi cette fonction implémente bien une copie qui fonctionne
avec les pointeurs qui sont perdus

Il faudrait jeter un oeil sur la doc du compilo
Ce qui compte c'est que le résultat soit obtenu et conforme au C
Coté implémentation il y a plusieurs possibilités, celle ci en est une
__sam__
Messages : 7964
Inscription : 18 sept. 2010 12:08
Localisation : Brest et parfois les Flandres

Re: Bug dans la wiki 6502?

Message par __sam__ »

bilbo a écrit :C'est exact si CNT+0 = 1 et CNT+1 = 0
1 octet est bien copié
Pourquoi n'en copie t'il pas d'autres? le "dec CNT+1" en 0615 le fait passer à 255, ce qui fait prendre la boucle lors du BNE en ligne 0617, et c'est reparti pour un tour en copiant plus d'octets que celui qui était demandé.

Pour moi il me semble que cette routine ne peut copier 1 seul octet. Elle déborde nécessairement!
Pour moi cette fonction implémente bien une copie qui fonctionne
avec les pointeurs qui sont perdus
C'est pas la valeur des pointeurs qui m'inquiète c'est que je ne vois pas comment cette boucle pourrait copier un seul octet avec CNT+0=1 et CNT+1=0.

La seule façon de copier 1 octet est de l'appeller avec CNT+0=1 et CNT+1=1 de sorte que le "dec CNT+1" rende le test BNE en 0617 faux de sorte à sortir de la boucle de copie. Le soucis c'est qu'avec ces valeurs là dans CNT on devrait copier 257 octets. On est loin du compte au final.

Pour résumer si {CNT,CNT+1} vaut 257 (little endian) on ne copie qu'un seul octet, et s'il vaut 1 on en copie bien plus (environ 256*255+1).

Le soucis qu'il ne faudrait pas un BNE en 0617 mais un branchement BPL ( >0) plutôt. Enfin je crois.
Samuel.
A500 Vampire V2+ ^8^, A1200 (030@50mhz/fpu/64mb/cf 8go),
A500 GVP530(MMU/FPU) h.s., R-Pi, TO9, TO8D, TO8.Démos
Avatar de l’utilisateur
fneck
Site Admin
Messages : 17490
Inscription : 01 avr. 2007 12:03
Localisation : Drôme Provençale (26)
Contact :

Re: Bug dans la wiki 6502?

Message par fneck »

J'ai déplacé le topic ici, je pense plus adapté à cette discussion.
Fabien https://www.system-cfg.com
Les bonnes pratiques de l'utilisateur du forum viewtopic.php?f=14&t=3
Avatar de l’utilisateur
6502man
Messages : 12312
Inscription : 12 avr. 2007 22:46
Localisation : VAR
Contact :

Re: Bug dans la wiki 6502?

Message par 6502man »

Cette routine ne peux pas copier qu'un seul octet :roll:

En 6502 il n'y a aucun registres 16bits, et on utilise souvent la page zéro pour adresser des blocs de plus de 256 octets sinon on passe par des instructions indéxés plus simples et moins couteuses en cycles :wink:

A l'époque je préférai utiliser la technique de l'auto-modification du code pour adresser la RAM, oui je sait beaucoup de personnes n'aime pas ca et trouve que ce n'est pas "propre", mais c'était efficace :lol: :lol: :lol:
Phil.

www.6502man.com

To bit or not to bit.
1 or 0.
Avatar de l’utilisateur
6502man
Messages : 12312
Inscription : 12 avr. 2007 22:46
Localisation : VAR
Contact :

Re: Bug dans la wiki 6502?

Message par 6502man »

Si tu t'intéresse au 6502 et que tu veux essayer quelques routines tu peux utiliser l'assembleur en ligne 6502 et il y a même un émulateur en ligne VIRTUAL 6502 :wink:

Si tu as besoins n'hésite pas à demander :wink:
Phil.

www.6502man.com

To bit or not to bit.
1 or 0.
__sam__
Messages : 7964
Inscription : 18 sept. 2010 12:08
Localisation : Brest et parfois les Flandres

Re: Bug dans la wiki 6502?

Message par __sam__ »

Bon je confirme.. il y a clairement un bug dans la wikipedia sur le code du memcpy. Le BNE final devrait être un BPL, cf le code http://atariage.com/forums/topic/175905 ... ?p=2627696 qui contient bien un BPL juste après la décrémentation sur la longueur.

De même le code du memcpy() du compilo cc65 utilise 2 boucles. L'une (L1) pour copier des blocs de 256 octets, et l'autre (L2) pour copier le reste de moins de 256 octets restant. Outre un code rapide, cette implémentation évite le soucis de la wikipedia car on saute directement en L2 si on doit copier 1 octet par exemple: https://github.com/cc65/cc65/blob/maste ... n/memcpy.s

Je pense que l'erreur de la wiki passe inaperçue parce que pour copier moins de 255 octets, les gens font une boucle plus simple qui n'a pas besoin de passer par la page zéro. Cependant c'est ennuyeux car ca perturbe les débutants qui comme moi se demandent pourquoi il y a un truc qui cloche et surtout pourquoi personne d'autre ne l'avait remarqué.
Samuel.
A500 Vampire V2+ ^8^, A1200 (030@50mhz/fpu/64mb/cf 8go),
A500 GVP530(MMU/FPU) h.s., R-Pi, TO9, TO8D, TO8.Démos
Avatar de l’utilisateur
6502man
Messages : 12312
Inscription : 12 avr. 2007 22:46
Localisation : VAR
Contact :

Re: Bug dans la wiki 6502?

Message par 6502man »

Honnêtement je pense que pour débuter il vaux mieux regarder des sources sur des sites spécialisées, plutôt que wiki :roll:
Enfin c'est mon avis.

Et les connaisseur du 6502 n'ont même pas du aller regarder ce code :wink:
Phil.

www.6502man.com

To bit or not to bit.
1 or 0.
__sam__
Messages : 7964
Inscription : 18 sept. 2010 12:08
Localisation : Brest et parfois les Flandres

Re: Bug dans la wiki 6502?

Message par __sam__ »

Le code source ce cc65 est plein de routines intéressantes: Contrairement au 6809 ce cpu n'a aucun registre 16 bits et il faut ruser. En assembleur ce que j'aime particulièrement est justement la ruse et les sources de ce compilo sont plein de trucs et astuces. Par exemple pour faire du C il vaut mieux que le type int16 soit facilement accessible. Ils font cela en utilisant la paire de registres a et x (a=poids faible, x=poids fort). C'est très ingénieux. Autre soucis du C: la pile doit être grosse. Or sur 6502 elle est petite (256 octets)et ne peut être déplacée. Qu'à cela ne tienne, ils utilisent deux cases de la page zero for opportunément appelées SP comme pointeur de pile que l'on peut reloger partout en mémoire. Ce SP en page zero est ensuite utilisé via l'indexation par X ou Y pour récupérer n'importe quelle valeur en pile. Ingénieux.

De ce que je comprends de la programmation sur ce CPU, c'est que contrairement au 6809 ou ce qu'on met dans les registres est important, sur 6502 les registres sont juste des trucs temporaires pour les calculs. Les vraies valeurs importantes sont la page zéro. Avec elle on dépasse les limites inhérente au cpu en lui donnant la possibilité de faire à peu près tout ce qu'un cpu 16 bit ferait. C'est vraiment une autre façon de penser par rapport au 6809 et je comprends pourquoi Dominique avait autant de mal avec l'asm 6809 qui ne passe que très rarement par la page zéro.
Samuel.
A500 Vampire V2+ ^8^, A1200 (030@50mhz/fpu/64mb/cf 8go),
A500 GVP530(MMU/FPU) h.s., R-Pi, TO9, TO8D, TO8.Démos
Avatar de l’utilisateur
6502man
Messages : 12312
Inscription : 12 avr. 2007 22:46
Localisation : VAR
Contact :

Re: Bug dans la wiki 6502?

Message par 6502man »

Comme je le disais précédemment le 6502 n'a aucun registre 16 bits et oui il faut ruser :wink:

Effectivement c'est une toute autre façon de penser par rapport aux autres CPU, avec le 6502 ni addition, ni soustraction en 16 bits et encore moins de multiplication :lol:

Comme tu le précises les registres n'ont pas vocations à être conservés, d'ailleurs il n'y en a pas beaucoup, la page zéro est très pratique mais limitée, l''indexage indexé par la page zéro est très pratique mais le mode d'adressage le plus lent (de mémoire), donc il faut trouver des astuces pour optimiser dans tous les cas.

Il n'y a pas autant d'instructions que sur un Z80 par exemple, mais les instructions sont bien pensés et rapides :D

Personnellement je suis pas un grand fan de CC65, mais je pense que tu as effectivement pas mal de routine toutes prêtes bien utile pour commencer.

Par curiosité tu t'intéresses au 6502 pour quelle plateforme ?
Phil.

www.6502man.com

To bit or not to bit.
1 or 0.
__sam__
Messages : 7964
Inscription : 18 sept. 2010 12:08
Localisation : Brest et parfois les Flandres

Re: Bug dans la wiki 6502?

Message par __sam__ »

Je m'y intéresse juste pour la culture générale de sorte à pouvoir lire plus facilement certains cours ASM d'Hebdogiciel ou des sources d'effets trouvés sur le web :mrgreen:
Samuel.
A500 Vampire V2+ ^8^, A1200 (030@50mhz/fpu/64mb/cf 8go),
A500 GVP530(MMU/FPU) h.s., R-Pi, TO9, TO8D, TO8.Démos
Répondre