1

Bonjour/bonsoir,
est-ce qu quelcun pourait m'expliquer pourquoi le premier des deux codes fonctionne dans mon programme mais pas le second (au départ le label "droite" est appelé par un call et ça ne change rien si on revient à l'endroit d'où à été appelé la fonction "droite" ou au label boucle).
L'erreur ce fait quand (hl)>80

droite:
	ld	a,80
	cp	(hl)
	ld	a,(hl)
	jp	m,droite100
retdroite:
	add	a,20
	ld	(hl),a
	ret
droite100:
	sub	80
	ld	(hl),a
	pop	hl
	jp	boucle


droite:
	ld	a,80
	cp	(hl)
	ld	a,(hl)
	jp	p,retdroite
	sub	100
retdroite:
	add	a,20
	ld	(hl),a
	ret



Merci d'avance
Sandro

2

Tu as un "pop hl" qui fait tâche sans "push"...

Enfin je ferais plutôt ça :
droite:
	ld a,(hl)
	cp 80
	jp p,retdroite
	sub 100
retdroite:
	add a,20
	ld (hl),a
	ret

3

Il me semble que
jp p, label

n'est pas l'exact contraire de
jp m, label

A cause du fait que 0 est un nombre positif et lorsque a = (hl) dans un cas ça passe et pas dans l'autre...
J'aimerais bien qu'on me confirme le comportement de ces sauts conditionnels (deeph ou chickendude ou gh par exemple tongue)

Est-ce que tu as bien fait gaffe à ça?
Ce n'est peut-être pas le probleme mais ça mérite d'être soulevé je crois.


edit (cross) : @deeph : peut-être que le push est avant car on ne voit pas le label "boucle" non plus ...

4

Non, désolé, ça ne fait pas le même effet (au contaire, pas moyen de faire déscendre (hl) en dessous de 127 alors que ça devrait être en permanance dans l'interval [1,100]).

Pour le pop hl, il sert à ced que la pile ne s'agrandisse pas quand on ressort de la fonction sans le ret (si (hl)>80).*

Mersi d'avance
Sandro

5

Ah j'avais pas vu, c'est un problème de retour avec le call : à partir du moment où tu as appelé une routine il faut qu'elle rencontre un "ret" pour que l'appel se termine bien, sinon ça va te foutre l’exécution du programme en l'air. Le retour manuel avec un saut n'est pas la même chose, et il faut faire gaffe avec l'utilisation de la pile pendant la routine : lors de l'appel son adresse est mise dans la pile pour savoir où revenir une fois le "ret" rencontré...

6

Je ne comprend pas trop, ça ne fait pas l'affaire si je vire juste la valeur du dessus de la pile et que je reviens avec un saut simple?

Sinon, pour m et p pour les sauts, 0 est-il inclu ou exclu?

Merci d'avance
Sandro

7

Le call sert a entrer dans une sous routine.Perso je l'utilise exprès pour le ret. Si tu peux gerer sans ça bah fait un saut wink

0 est inclus dans un cas (p) et exclus dans l'autre (m) mais je voudrais qu'on me confirme ça si possible.

8

Merci, à l'origine, j'avais mis que des sauts, mais je voulais passer aux call pour optimiser, mais je n'y arrive pas autrement sans que ça modifie le comportement je ne comprend pas pourquoi. mad

Sandro

9

J'ai pas vérifié mais si ça bug c'est que c'est ça. Le mieux serait de mettre l'adresse du label "boucle" dans la pile avant de faire un "ret", mais bon c'est se compliquer la vie je trouve...

Pour ce qui est des sauts avec p/m tout dépend du sign flag, le bit 7 : s'il est à 0 alors le nombre est considéré comme positif et s'il est à 1 alors il est négatif, mais que lorsqu'on parle de nombres signés ( http://www.mworld.fr/html/projects/calc/ti-82/tutoriel/progasm/guide/lesson10.html#flags ).

10

le problème viedrai donc du "ld a,(hl)" ? Mais pourquoi alors ton code ne marcherait pas?

Merci d'avance
Sandro

11

J'ai pas testé mais en théorie ça te donne ça :
droite:
	ld a,80
	cp (hl)
	ld a,(hl)
	jp m,droite100

retdroite:
	add a,20
	ld (hl),a
	ret

droite100:
	sub 80
	ld (hl),a
	pop hl
	ld hl,boucle
	push hl
	ret

Déjà c'est sûr qu'hl n'aura plus la même valeur après la routine (mais la valeur située à l'adresse (hl), elle, non).

Mais je le répète c'est se prendre la tête pour pas grand chose...

12

Merci, ça marche, même si je ne comprend toujours pas à quoi sert le "pop hl ld hl,boucle push hl" alors que ça m'est peu importe si on retourne au label boucle où à l'endroit d'où la fonction est appelée (quelques lignes plus loin, on tombe sur un "jp boucle").

Merci d'avance
Sandro

PS: je cherche à comprendre car à recopier bêtement, on n'apprend pas (chose que les profs on parfois un peu de mal à comprendre).

13

C'est expliqué assez clairement ici : http://www.mworld.fr/html/projects/calc/ti-82/tutoriel/progasm/guide/lesson6.html

En gros lorsque tu fais un "call" ça te met l'adresse actuelle (le PC -Program Counter-) dans la pile afin de se souvenir où il faut reprendre l’exécution après l'appel (ou saut vers la routine), ce dernier se terminant à la rencontre d'un "ret", qu'importe les sauts fais entre deux...

Du coup même si tu retires le PC de la pile ça ne change rien, puisque cette dernière s'accroit "en arrière" ( http://www.mworld.fr/html/projects/calc/ti-82/tutoriel/progasm/guide/lesson12.html#stack ), il y a de fortes chances qu'une valeur aléatoire soit récupérable et prise pour l'adresse de retour au prochain "ret" rencontré.

14

Désolé, mais je ne suis pas trop, quand on fait un call, le PC est stocké eb dernière valeur de la pile (comme si on avait "push pc jp label") donc si on fait un "pop hl", on devrait récupérer la pile commesi on avait fait un saut et donc pouvoir continuer avec un saut.

Voci le bout de code un peu plus élargi:
boucle:
	ld	hl,$0001
	ld	(currow),hl
	ld	hl,(numerau_essaye)
	ld	h,0
	bcall _disphl
	bcall _getkey


	ld	hl,numerau_essaye

	dec	a
	call	z,droite
	dec	a
	jp	z,gauche
	dec	a
	jp	z,haut
	dec	a
	jp	z,bas
	dec	a
	jp	z,entrer


	cp	4
	jp	nz,boucle
	ret	

droite: 
	ld a,80 
	cp (hl) 
	ld a,(hl) 
	jp m,droite100 
 
retdroite: 
	add a,20 
	ld (hl),a 
	ret 
 
droite100: 
	sub 80 
	ld (hl),a 
	pop hl 
	ld hl,boucle 
	push hl 
	ret


Et vue le code, ça ne change rien si après la routine droite, on continue après la ligne "call z,droite" ou au label "boucle".

Sandro

15

Non dans tous les cas il te faut un "ret" pour retourner à l'adresse stockée dans la pile. Mais bon c'est tout simple et y'a pas besoin de jouer avec la pile à mon avis :
boucle: 
	ld hl,$0001
	ld (currow),hl
	ld hl,(numerau_essaye)
	ld h,0
	bcall _disphl
	bcall _getkey
	ld hl,numerau_essaye
	dec a
	push af
	call z,droite ; 'a' est détruit durant la routine donc il vaut mieux le sauver avec la pile
	pop af
	dec a
	; etc...
	cp 4
	jp nz,boucle
	ret

droite:
	ld a,80
	cp (hl)
	ld a,(hl)
	jp m,droite100
	add a,20
	ld (hl),a
	ret

droite100:
	sub 80
	ld (hl),a
	ret ; ici on retourne simplement où l'appel à la routine "droite" a eu lieu...

16

edit : bug

17

Edit : bug ??? qu'est-ce que tu veux dire, ça marche non? en tout as, ça ne bug pas dans mes tests.

Merci beaucoup,
Sandro

18

Non mais j'ai foiré mon post grin

19

Lequel, le 14 ou le 15?

20

Le ./16 mais c'est sans importance.

21

Ha, désolé, j'ai d'abord pensé que c'était por me signaler qu'il y avait un bug dans le 14 et pour attirer mon attention pour le cas où j'aurais déjà lu le 14.

En tout cas merci beaucoup, ce problème est résolut (même si au final j'utilise des jr, ça m'évite de devoir faire le push af/pop af , donc c'est plus optimisé.
Sandro

22

Pas forcément si tu places le "push af" en début de routine et le "pop af" juste avant le/les "ret".

Enfin perso je trouve ça un peu compliqué ce genre de "hack" pour un truc aussi simple.

23

Oui, finalement, j'ai replacer par des jr (et jp quand la distance devient trop grande où que les conditions sont incompatibles), ça me fait un code plus optimisé tout compte fait.

Merci beaucoup pour votre aide
Sandro