1

Je suis emmerdé avec les flags, j'ai écrit des fonctions pour lire des nombres décimaux et hexadécimaux, mais je ne sais pas comment détecter un overflow.
Voici le bout de code qui résume les différents problèmes :
	move.l	d0,d2				; *1
	add.l	d0,d0				; *2
	bvs.s	\OverFlow
	lsl.l	#3,d2				; *8
	bvs.s	\OverFlow
	add.l	d2,d0				; 8+2 == 10
	bvc.s	\Loop
\OverFlow:

L'idée, c'est que si le résultat du lsl dépasse 32 bits, on a un overflow. Mais la doc dit ça :
        V - Set if the most significant bit was changed during the operation.
            Cleared else.

ie si j'ai $10000000, mon lsl va en faire un $80000000. Donc le most significant bit va changer durant l'opération, alors qu'en réalité, je n'aurai pas d'overflow. Comment faire ? Que des add, et tester à chaque fois l'overflow ?

Il y aurait bien ça :
	move.l	d0,d2				; *1
	add.l	d0,d0				; *2
	bvs.s	\OverFlow
	lsl.l	#2,d2				; *4
	bcs.s	\OverFlow			; Si add d0,d0 a marché, je peux avoir au pire un bit en trop
						; Donc là si le bit #31 est 1, ça passera pas après
	add.l	d2,d2				; *8
	bvs.s	\OverFlow			; 
	add.l	d2,d0				; 8+2 == 10
	bvc.s	\Loop
\OverFlow:

Mais c'est lourd et crade, il n'y a pas moyen de faire mieux ?

(ps -> strtol, dans PedroM, c'est du C sad)

2

Tu peux pas tester tout bêtement le carry ? confus
avatar
Zeroblog

« Tout homme porte sur l'épaule gauche un singe et, sur l'épaule droite, un perroquet. » — Jean Cocteau
« Moi je cherche plus de logique non plus. C'est surement pour cela que j'apprécie les Ataris, ils sont aussi logiques que moi ! » — GT Turbo

3

Tu peux pas utiliser le strtol de PedroM ? Ca prendrait en plus moins de place.

4

bvs/bvc, c'est pour les débordements signés. Les débordements non signés, c'est bcs/bcc effectivement.
avatar
Mes news pour calculatrices TI: Ti-Gen
Mes projets PC pour calculatrices TI: TIGCC, CalcForge (CalcForgeLP, Emu-TIGCC)
Mes chans IRC: #tigcc et #inspired sur irc.freequest.net (UTF-8)

Liberté, Égalité, Fraternité

5

- C-flag (Carry). Works as carry is used to work. If you add two 8 bit numbers,
  the C-flag will be the 9th bit. Also used with shift and rotation.

et
LSL

FLAGS:  X - The last bit that was sent out of the operand. Unaffected if
            number of steps is 0.
        N - S
        Z - S
        C - Same as X

Si j'ai d0==$40000000, et que je fais un LSL #3,d0 je vais me retrouver avc d0 == 0.

Dans l'ordre, on va avoir 0,1,0 qui vont sortir.
Comme un 0 va sortir en dernier, le C flag sera à 0, donc j'aurais pas connaissance que j'ai eu un overflow.

Je me fais mieux comprendre ?
PpHd (./3) :
Tu peux pas utiliser le strtol de PedroM ? Ca prendrait en plus moins de place.

Si PedroM gère le décimal et l'hexa, et si il n'attend pas une chaine terminée par un 0, pourquoi pas, j'y ai même pas pensé en allant voir son source hier soir. ^^

6

Si j'ai d0==$40000000, et que je fais un LSL #3,d0 je vais me retrouver avc d0 == 0.

V n'est pas mis à 1, dans ce cas-là ?
avatar
Membre de la TI-Chess Team.
Co-mainteneur de GCC4TI (documentation en ligne de GCC4TI), TIEmu et TILP.
Co-admin de TI-Planet.

7

LSL
        V - Set if the most significant bit was changed during the operation.
            Cleared else.

Si je lis bien, si je passe de $10000000 à $80000000, je vais avoir V à 1, oui, mais pas d'overflow en réalité...

Je vais faire des tests.

8

D'où ce qu'écrit Kevin en ./3:
bvs/bvc, c'est pour les débordements signés. Les débordements non signés, c'est bcs/bcc effectivement.
avatar
Membre de la TI-Chess Team.
Co-mainteneur de GCC4TI (documentation en ligne de GCC4TI), TIEmu et TILP.
Co-admin de TI-Planet.

9

D'où ceci :
Folco (./5) :
Si j'ai d0==$40000000, et que je fais un LSL #3,d0 je vais me retrouver avc d0 == 0.

Dans l'ordre, on va avoir 0,1,0 qui vont sortir. Comme un 0 va sortir en dernier, le C flag sera à 0, donc j'aurais pas connaissance que j'ai eu un overflow.

Donc dmc un bcc/bcs qui n'y verra que du feu.

10

Mouais, vu grin

Pour détecter les overflows lors des multiplications, shifts vers la gauche, et autres opérations qui produisent un résultat comportant plus de bits que les entrées, le plus simple et le plus correct (mais c'est un peu plus lent, bien sûr) me paraît être d'utiliser des routines qui prennent des entrées 32 bits et produisent des résultats sur 64 bits (ou moins - par exemple, l'addition de deux nombres de 32 bits génère un résultat sur 33 bits).
Profite donc du fait de coder en ASM: tu peux utiliser des conventions d'appel non C (retour dans plusieurs registres) oui
avatar
Membre de la TI-Chess Team.
Co-mainteneur de GCC4TI (documentation en ligne de GCC4TI), TIEmu et TILP.
Co-admin de TI-Planet.

11

Lionel Debroux (./10) :
Mouais, vu biggrin.gif

Ouais ! \o/ Je pensais être le seul à mal lire ou à ne pas comprendre la doc ! grin

Je pense que pour une forme hexadécimale à convertir (multiplication pas 16), je vais faire un truc comme ça :
move.l d0,d2                        ; sauvegarde
andi.l #$F0000000,d2                ; si un des quatre bits les plus haut est à 1, ça va déborder.
bne.s Overflow                      ; merde (© PpHd dans les routines de sprites de Genlib #trilove#)
lsl.l #4,d0                         ; sinon on peut y aller

Overflow:


ie si on a un des trois bits supérieurs à 1, on sait que ça passera pas. Sinon, on fonce.

Pour une conversion de décimal, je vais vérifier la seconde solution postée dans ./1 Pas envie de me faire suer avec des multiplications de long long dont je ne comprends pas les algorithmes, malgré le fait que j'ai passé 1 heure dans Long.asm (je suis pas un bon mathématicien...).

Merci !

12

Ce ne sont pas des multiplications de long long, ce sont des multiplications de long qui produisent un long long. C'est différent, et plus facile wink
avatar
Membre de la TI-Chess Team.
Co-mainteneur de GCC4TI (documentation en ligne de GCC4TI), TIEmu et TILP.
Co-admin de TI-Planet.

13

Et tu penses pas que ce que j'ai fait est plus rapide/facile ? Vraie question, hein. grin

14

Tu _peux_ utiliser le code posté en ./11 pour la conversion hexa, bien sûr smile
Mais il faudra quand même que tu codes quelque part, en plus du code spécifique à la conversion hexa, une routine générique qui sache détecter l'absence de débordement dans (0xABCD << 16) et le débordement de (0xABCD << 17).
avatar
Membre de la TI-Chess Team.
Co-mainteneur de GCC4TI (documentation en ligne de GCC4TI), TIEmu et TILP.
Co-admin de TI-Planet.

15

Ouep... Toute façon, je vais me retrouver coincé quand je ferai les multiplications. rage

Mais bon, déjà, faisons ça, c'est optimisé pour ce cas-là, les multiplications viendront plus tard, dans la résolution de mon estack.

16

Bon, pour la partie hexédécimale, j'ai utilisé la méthode que j'ai proposée plus haut (un poil optimisée, on peut faire une copie de byte et non de longword à la fin, étant donné que seuls les 4 bits inférieurs seront affectés).
Par contre, j'ai sorti le grand jeu pour la lecture de valeurs décimales :
;==================================================================
;	ReadDecimal
;------------------------------------------------------------------
; 	Read a decimal immediate value
;
;	input	a0	*decimal value
;	output	d0.l	value
;		a0	*first char after the value
;	destroy	d1-d2
;==================================================================
ReadDecimal:
	moveq.l	#0,d0				; Init value
	moveq.l	#0,d1				; Clear 3 upper bytes
\Loop:	move.b	(a0)+,d1			; Read a char
	subi.w	#'0',d1				; 0
	bmi.s	\Invalid
	cmpi.b	#9,d1
	bhi.s	\Invalid
	move.l	d0,d2				; copy
	add.l	d2,d2				; *2
	bcs.s	\OverFlow
	add.l	d2,d2				; *4
	bcs.s	\OverFlow
	add.l	d2,d2				; *8
	bcs.s	\OverFlow
	add.l	d0,d0				; *2
	bcs.s	\OverFlow
	add.l	d2,d0				; 8+2 == 10
	bcs.s	\OverFlow
	add.l	d1,d0				; Add new char
	bcc.s	\Loop
\OverFlow:
	THROW_STDOUT	16

\Invalid:
	subq.l	#1,a0				; Restore ptr
	rts					; And quit

La classe, non ? tripo

(et ça marche)

17

[nosmiley]
Folco (./5) :
Si PedroM gère le décimal et l'hexa, et si il n'attend pas une chaine terminée par un 0, pourquoi pas, j'y ai même pas pensé en allant voir son source hier soir. ^^


oui et oui. Extrait du manuel:
      La  fonction  strtol()  convertit  la chaîne nptr en un entier long en fonction de l’argument base, qui doit
       être dans l’intervalle 2 à 36 (bornes comprises), ou avoir la valeur spéciale 0.

       La chaîne peut commencer par un nombre quelconque d’espaces ou de caractères interprétés comme tels par iss&#8208;
       pace(3).  Un  signe  éventuel  « + »  ou  « -»  peut suivre. Si base vaut 0 ou 16, la chaîne peut inclure un
       préfixe «0x » et le nombre sera interprété en base 16. Sinon, une base valant zéro est interprétée comme  10
       (décimale) sauf si le caractère suivant est «0 », auquel cas la base est 8 (octale).

       Le  reste  de  la chaîne est converti en une valeur long int, en s’arrêtant au premier caractère qui ne soit
       pas un chiffre valide dans cette base. Dans les bases supérieures à 10, la lettre « A » (majuscule ou minus&#8208;
       cule) représente 10, « B » représente 11, et ainsi de suite jusqu’à « Z » représentant 35.

       Si  endptr  n’est  pas  NULL, strtol() stocke l’adresse du premier caractère invalide dans *endptr. S’il n’y
       avait aucun chiffre valide, strtol() stocke la valeur originale de nptr dans *endptr (et renvoie 0). En par&#8208;
       ticulier, si *nptr n’est pas « \0 » et si **endptr vaut « \0 » en retour, la chaîne entière est valide.

et sa copine, strtoul

18

Pas pensé à regarder la page de man... Merci

19

Les algorithmes de multiplication sont pourtant simples, c'est juste la distributivité (a+b)(c+d)=ac+ad+bc+bd.
avatar
Mes news pour calculatrices TI: Ti-Gen
Mes projets PC pour calculatrices TI: TIGCC, CalcForge (CalcForgeLP, Emu-TIGCC)
Mes chans IRC: #tigcc et #inspired sur irc.freequest.net (UTF-8)

Liberté, Égalité, Fraternité

20

Oui, mais il y a le fait que ce soit réparti sur 2 registres qui est un peu casse-pieds.
avatar
Zeroblog

« Tout homme porte sur l'épaule gauche un singe et, sur l'épaule droite, un perroquet. » — Jean Cocteau
« Moi je cherche plus de logique non plus. C'est surement pour cela que j'apprécie les Ataris, ils sont aussi logiques que moi ! » — GT Turbo

21

Merci Kevin, je me demandais comment j'allair attaquer. smile

22

Folco : j'ai codé une routine de multiplication 32x32->64 non signée en ASM 68k il y a quelques temps, je peux la poster si ça t'intéresse (mais il me semble que celle utilisée dans TIGCC est plus courte).
avatar
Zeroblog

« Tout homme porte sur l'épaule gauche un singe et, sur l'épaule droite, un perroquet. » — Jean Cocteau
« Moi je cherche plus de logique non plus. C'est surement pour cela que j'apprécie les Ataris, ils sont aussi logiques que moi ! » — GT Turbo

23

Merci mille fois, mais je préfère chercher moi-même. grin

24

Celle de TIGCC est plus courte parce qu'elle n'est que 32×32→32. Il y a ça et 64×64→64, il n'y a pas de routine 32×32→64 dans TIGCC.
avatar
Mes news pour calculatrices TI: Ti-Gen
Mes projets PC pour calculatrices TI: TIGCC, CalcForge (CalcForgeLP, Emu-TIGCC)
Mes chans IRC: #tigcc et #inspired sur irc.freequest.net (UTF-8)

Liberté, Égalité, Fraternité

25

Kevin Kofler (./19) :
Les algorithmes de multiplication sont pourtant simples, c'est juste la distributivité (a+b)(c+d)=ac+ad+bc+bd.

Merci Kevin !

Ca a tout de suite éclairé ma lanterne. grin
http://www.mirari.fr/NmAh?a=view&nowrap=0&showln=0&tablen=8

Et pour une division 32x32 bits, quel est l'indice ? grin

26

Bon en fait, j'ai trouvé un super indice qui s'appelle _ds32s32 zzz