- Posté le 02/09/2010 à 22:49 Membre depuis le 10/06/2001, 30518 messages
Folco (./83) :
Le cast en long permet de bosser classiquement sur des entiers non signés
un long, c'est un signed long.
- Posté le 02/09/2010 à 23:01 Membre depuis le 18/06/2001, 30136 messages
Erf, c'est vrai, merci bien. Mais mon code est bien en unsigned. Mais c'est vrai, j'avais pas fait gaffe. cheeky
avatar <<< Kernel Extremist©®™ >>>
Saint Qt, priez pour nous.
- Posté le 02/09/2010 à 23:02 Membre depuis le 10/06/2001, 30518 messages
Biennnnnn embarrassed
- Posté le 02/09/2010 à 23:09 Membre depuis le 18/06/2001, 30136 messages
Tiens, euh, d'ailleurs, à propos de cast ##sifflote##

J'ai écrit ça :
void *kernel_LibsPtr(LibRef *lib asm("a0"), short function asm("d0"));             // kernel.c de PreOS

*(long*)((long) Data + *Offset) = kernel_LibsPtr(Descriptor, (short) *Func);

C'est précisément là que j'enregistre mes pointeurs de fonction dans le stackframe.
Ca compile, mais j'ai un warning "Assignment makes integer from pointer without a cast".
Donc je crée un pointeur à partir d'un entier sans cast ?
Où ça ??

Dans l'ordre, on a :
Data est un pointeur de structure casté en long (pour pouvoir faire l'addition de l'offset).
*Offset est un unsigned short
kernel_LibsPtr est un void*
Descriptor est un Libref*, attendu par LibsPtr
*Func est un char casté en short

Le problème vient de la valeur de gauche, l'appel a kernel_LibsPtr seul compile sans warning.
Donc on a :
((long) Data + *Offset) => addition d'un long et d'un short promu en long, ça fait un long
(long*) => il est casté en pointeur
* => c'est là qu'on y met le résultat

Pourquoi ça merde ?


(en asm, ça se résume à move.l a0,offset(a6). C'est rageant de savoir ce que l'on veut et de pas savoir l'écrire. :/)
avatar <<< Kernel Extremist©®™ >>>
Saint Qt, priez pour nous.
- Posté le 02/09/2010 à 23:22 Membre depuis le 10/06/2001, 30518 messages
L'addition doit être prioritaire sur le cast.
Essaie :
((long) Data) + *Offset
pour voir.
- Posté le 02/09/2010 à 23:24 Membre depuis le 10/06/2001, 30518 messages
PS : là, tu castes aussi en signed long, c'est voulu ?
Ta structure pointe peut-être sur un signed long, mais le cast pour l'addition devrait probablement être un unsigned long ! Là, tu cours le risque que ((long)Data) soit négatif...
Bon, sur TI, de mémoire les adresse sont sur 24 bits donc ça ne risque rien*, mais c'est une très mauvaise habitude.


* sauf, bien sûr, si tu utilises l'octet libre pour stocker des trucs ##modpo##
- Posté le 03/09/2010 à 00:00 Membre depuis le 18/06/2001, 30136 messages
Pen^2 (./94) :
L'addition doit être prioritaire sur le cast.

Ce n'est pas ça sad
Pen^2 (./95) :
* sauf, bien sûr, si tu utilises l'octet libre pour stocker des trucs /sp/img/modpo.img

Hihi grin tu as bien raison sur le principe, mais de toute façon, j'imagine qu'un cast de pointeur en long n'est absolument par portable, par exemple sur 64 bits. Mais t'as raison, c'est sale ^^
avatar <<< Kernel Extremist©®™ >>>
Saint Qt, priez pour nous.
- Posté le 03/09/2010 à 00:06 - Edité par Pen^2 le 03/09/2010 à 00:13 Membre depuis le 10/06/2001, 30518 messages
Ah, je crois que j'ai trouvé :
kernel_LibsPtr renvoie un void*
Or tu stockes ce void* dans un *(long*), autrement dit, un long.
Essaie de caster la valeur de retour de kernel_LibsPtr en long explicitement.
*(long*)(((unsigned long)Data) + *Offset) = (long)kernel_LibsPtr(Descriptor, (short) *Func);


PS : J'ai laissé ton signed long pour ne pas casser ta structure, mais c'est la mort dans l'âme... tongue (je n'avais pas vu que kernel_* renvoyait un pointeur)
- Posté le 03/09/2010 à 00:10 Membre depuis le 10/06/2001, 30518 messages
Folco (./96) :
Hihi /v31/gfx/s/biggrin.gif tu as bien raison sur le principe, mais de toute façon, j'imagine qu'un cast de pointeur en long n'est absolument par portable, par exemple sur 64 bits. Mais t'as raison, c'est sale ^^

Faut voir, c'est possible (et même probable) qu'un long devienne 64 bits aussi. Je n'ai plus tout ça en tête, et puis je ne crois pas que ça soit défini de toute façon. L'idée est plutôt du genre (en sizeof) : char <= short <= int <= long, enfin, quelque chose de ce genre.
- Posté le 03/09/2010 à 00:14 Membre depuis le 18/06/2001, 30136 messages
(le long est passé en unsigned long, et toute façon c'est un pointeur de fonction, mais j'écris dedans avec un offset, comme si c'était une simple zone de mémoire et pas une structure ##triange##
Pen^2 (./97) :
kernel_LibsPtr renvoie un void*
Or tu stockes ce void* dans un *(long*), autrement dit, un long.
Essaie de caster la valeur de retour de kernel_LibsPtr en long explicitement.

Ah, bien vu, c'est ça !

Mais je suis étonné, je croyais qu'en C, void* se castait en n'importe quoi automatiquement, tant que c'est un pointeur. Hors là, je le castais en long*. Mais bon, merci. #top#

cross:
char <= short <= int <= long, enfin, quelque chose de ce genre.

Avec sizeof(char) == 1 et sizeof(long) >= 2 (je crois).
avatar <<< Kernel Extremist©®™ >>>
Saint Qt, priez pour nous.
- Posté le 03/09/2010 à 08:02 Membre depuis le 16/06/2001, 59933 messages
sur x86_64 les long font en effet 64 bits aussi. c'est probablement fait exprès pour que ce genre de cast marche encore grin
- Posté le 03/09/2010 à 09:00 Membre depuis le 28/10/2001, 7568 messages
sur x86_64 les long font en effet 64 bits aussi.

Si on tourne un *nix (LP64), oui. Si on tourne un Win64 (LLP64), non smile
avatar Membre de la TI-Chess Team.
Co-mainteneur de GCC4TI (documentation en ligne de GCC4TI), TIEmu et TILP.
Co-admin de TI-Planet.
- Posté le 03/09/2010 à 09:01 Membre depuis le 16/06/2001, 59933 messages
##trisick## c'est vrai
- Posté le 03/09/2010 à 15:19 Membre depuis le 24/04/2002, 4656 messages
Ben oui, les gens s'étaient trop habitués à sizeof(int)==sizeof(long)...
Ils devraient programmer sur TI plus souvent.
avatar Maintenant j'ai la flemme de garder une signature à jour sur ce site. Je n'ai même plus ma chaîne Exec sous la main.
- Posté le 03/09/2010 à 15:23 Membre depuis le 10/06/2001, 30518 messages
Ah ? Sur TI c'est pas 32 bits pour les deux ? #confus#
- Posté le 03/09/2010 à 16:07 Membre depuis le 24/04/2002, 4656 messages
Il me semble bien que sur TI les int font 16 bits, comme les short. Je me suis déjà fait avoir avec ça...
avatar Maintenant j'ai la flemme de garder une signature à jour sur ce site. Je n'ai même plus ma chaîne Exec sous la main.
- Posté le 03/09/2010 à 16:09 Membre depuis le 10/06/2001, 30518 messages
Possible.
- Posté le 03/09/2010 à 16:41 Membre depuis le 10/06/2001, 34958 messages
Pen^2 (./97) :
Essaie de caster la valeur de retour de kernel_LibsPtr en long explicitement.
*(long*)(((unsigned long)Data) + *Offset) = (long)kernel_LibsPtr(Descriptor, (short) *Func);

Il est plus propre d'utiliser void ** à gauche (à la place de long *).

Folco (./99) :
Mais je suis étonné, je croyais qu'en C, void* se castait en n'importe quoi automatiquement, tant que c'est un pointeur. Hors là, je le castais en long*.

Le problème n'est pas là, il est dans l'affectation d'un void à une lvalue de type long (pas long *).

Link (./105) :
Il me semble bien que sur TI les int font 16 bits, comme les short.

Exact.
avatar Mes news pour calculatrices TI: Ti-Gen (fr/en), MobiFiles (de)
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é
- Posté le 03/09/2010 à 20:19 Membre depuis le 18/06/2001, 30136 messages
Kevin Kofler (./107) :
Il est plus propre d'utiliser void ** à gauche (à la place de long *).

Ah bien vu en effet, je n'avais pas pensé à ça !

extern void CommandHelp(char);
extern void CommandAbout(char);
extern void CommandConfig(char);
extern void CommandFlags(char);

J'ai une erreur parce que je ne passe pas de nom à ce paramètre qui ne m'intéresse pas. La solution élégante du C++ qui consiste à ne pas mettre de nom de variable provoque une erreur en C.
Comment faire, mettre une instruction bidon, genre "char truc++;" dans la fonction ? C'est sale...
avatar <<< Kernel Extremist©®™ >>>
Saint Qt, priez pour nous.
- Posté le 04/09/2010 à 14:09 - Edité par Folco le 04/09/2010 à 17:09 Membre depuis le 18/06/2001, 30136 messages
Bon, ben j'ai adopté la solution crade pour le moment, faute de mieux grin

Sinon, comment peut-on faire pour merger ça :

const char* str = "abc\0def\0ghi\0jkl\0"

et :

const char* str1 = "abc"
const char* str2 = "def"
const char* str3 = "ghi"
const char* str4 = "jkl\0"

? C'est vraiment dommage de devoir doubler les données, sous prétexte qu'en C on ne peut pas mettre de label au milieu sad
Quand à faire du (str+n), même pas la peine, c'est trop crade.
avatar <<< Kernel Extremist©®™ >>>
Saint Qt, priez pour nous.
- Posté le 04/09/2010 à 16:53 Membre depuis le 10/06/2001, 30518 messages
mmm, un truc dans ce genre ? Tu ne dois jamais accéder à str directement, bien sûr. Essaie de le cacher au mieux cheeky (c'est pour ça que j'ai écrit private et public, même si ce n'est pas valide en C)
private const char* const str= "abcdcfghijkl" ;
012345678901
public const char* const s1= str+0 ;
public const char* const s2= str+3 ;
public const char* const s3= str+6 ;
public const char* const s4= str+9 ;

C'est pas si moche que ça tant que les offsets sont centralisés — en tout cas, c'est déjà mieux que de dupliquer si tu veux mon avis tongue

(Par contre ta déclaration j'espère que c'est du pseudo-code : \d, \g et \j ne correspondent à rien. Et c'est inutile d'ajouter un \0, c'est fait automatiquement par les guillemets.)
- Posté le 04/09/2010 à 17:11 Membre depuis le 18/06/2001, 30136 messages
Oui, en fait je voulais écrire ça :
const char* str = "abc\0def\0ghi\0jkl\0"

C'est en fait des chaines de caractères qui se suivent, terminées par deux \0 (fin du bloc de chaines).
En asm ça donne ça :
dc.b "abc",0,"def",0,"ghi",0,0

Et ok pour les offsets, faut juste pas se planter à compter (les chaines sont un peu plus complexes que "abcdef..." grin).
avatar <<< Kernel Extremist©®™ >>>
Saint Qt, priez pour nous.
- Posté le 04/09/2010 à 17:28 Membre depuis le 10/06/2001, 30518 messages
Folco (./111) :
faut juste pas se planter à compter (les chaines sont un peu plus complexes que "abcdef..." /v31/gfx/s/biggrin.gif ).

À la rigueur s'il y en a beaucoup tu peux te faire un petit programme annexe qui te concatène tout ça smile
- Posté le 04/09/2010 à 17:31 Membre depuis le 10/06/2001, 30518 messages
Sinon pour la question d'origine, je me demande si dans une structure l'ordre des champs est garanti ou pas...
ça pourrait résoudre ton problème facilement

du genre :
struct {
const char* s1= "huhu" ;
const char* s2= "hoho" ;
char s3= '\0' ;
}


J'en sais trop rien en fait cheeky
- Posté le 04/09/2010 à 17:32 Membre depuis le 18/06/2001, 30136 messages
Tout à fait, ça serit super facile comme ça. Je vais voir si je peux trouver ce que dit la norme à ce niveau.
avatar <<< Kernel Extremist©®™ >>>
Saint Qt, priez pour nous.
- Posté le 04/09/2010 à 17:42 Membre depuis le 18/06/2001, 30136 messages
Bon, alors dans mon bouquin, je lis ça :
- les champs d'une structure sont alloués suivant l'odre de leur déclaration
- l'adresse de la structure est l'adresse de son premier élément (donc pas d'octet de padding en début de structure)
- les octets de paddings sont autorisés pour des contraintes d'alignement

Evidemment, ça ne devrait pas être le cas pour des char sur TI. Mais si demain les char sur TI font deux octets, ça pètera. Et si le compilateur décide d'aligner les strings sur des adresses paires parce que ça lui chante, ça pètera aussi, a priori rien ne lui interdit.
avatar <<< Kernel Extremist©®™ >>>
Saint Qt, priez pour nous.
- Posté le 04/09/2010 à 19:58 Membre depuis le 28/10/2001, 7568 messages
Folco: une possibilité, pour avoir des sortes de tableaux de strings plus efficaces est utilisée notamment dans le tuto TICT S1P6 et dans Ice Hockey 68k smile
avatar Membre de la TI-Chess Team.
Co-mainteneur de GCC4TI (documentation en ligne de GCC4TI), TIEmu et TILP.
Co-admin de TI-Planet.
- Posté le 04/09/2010 à 20:00 Membre depuis le 18/06/2001, 30136 messages
Ah merci super, je cours y voir. Faisant du C que depuis récemment, je ne me suis penché sur ces tutos qu'une fois, très rapidement.
avatar <<< Kernel Extremist©®™ >>>
Saint Qt, priez pour nous.
- Posté le 04/09/2010 à 20:06 Membre depuis le 28/10/2001, 7568 messages
Il me semble que ces softs utilisent tous les deux un bout d'ASM, mais il doit pouvoir être remplacé par une expression C, moins compliquée que DEREFSMALL.
avatar Membre de la TI-Chess Team.
Co-mainteneur de GCC4TI (documentation en ligne de GCC4TI), TIEmu et TILP.
Co-admin de TI-Planet.
- Posté le 04/09/2010 à 22:19 Membre depuis le 30/06/2001, 57366 messages
Pen^2 (./113) :
Sinon pour la question d'origine, je me demande si dans une structure l'ordre des champs est garanti ou pas...
ça pourrait résoudre ton problème facilement

du genre :
struct {
const char* s1= "huhu" ;
const char* s2= "hoho" ;
char s3= '\0' ;
}


J'en sais trop rien en fait cheeky

Il est garanti sinon on utiliserais pas une simple struct pour lire un BMP par example.

Par contre l'endianess il faut faire gaffe
avatar
Proud to be CAKE©®™
The cake is a lie! - Love your weighted companion cube

->986-Studio's Wonder Project!<-
- Posté le 04/09/2010 à 22:59 Membre depuis le 18/06/2001, 30136 messages
Ok, donc l'endianness c'est bon à retenir pour les cas généraux, mais codant ti-only ici je m'en fous.

Et les BMP c'est quoi ? Réellement une structure, pas un tableau ? J'ai jamais travaillé dessus en fait ^^ Même avec la SDL, il me suffisait de fournir un fichier en entrée, et la structure qui résultait de la création du sprite était opaque.
avatar <<< Kernel Extremist©®™ >>>
Saint Qt, priez pour nous.