1

Yop,

Je suis, pour un autre problème, confronté à un problème de structurations de mes données. En assembleur, j'écrivais ceci :
DataSection	MainMenu
		.even
		.word	2

		.word	ExecCfgFlagsMenu-PC_Table
		.word	ExecCfgEVMenu-PC_Table
		.word	Quit-PC_Table

		.asciz	"Configure flags"
		.asciz	"Configure environment variables"

			.asciz	"Flags : AutoArc, OffSwitch,"
			.asciz	"GetKeySwitch, StatusError"
		.byte 0
			.asciz	"Variables : apd, start, home, temp,"
			.asciz	"args, fkey[n]"
		.byte 0

Ca représente en fait une structure :
- 2 + 1 offsets dans une table de saut
- 2 chaines "principales"
- 2 chaines commentaires

Le truc commode, c'est qu'un menu se suffisait à lui-même pour dire ce qu'il devait advenir, suivant qu'on sélectionnait une option ou l'autre (deux premiers offset), ou qu'on appuyait sur ESC (dernier offset dans la table de saut, pc-relative évidemment). Ca permet une profondeur infinie de menu sans écrire une ligne de code. Suffit de rajouter du texte et des labels.

Comment faire un truc similaire en C ?
Pour les chaines, pas de souci, je fais une structure de tableaux, ça devrait le faire. Par contre, pour rajouter à chaque élément de ma structure ce qui doit être exécuté, comment faire ?
j'imagine que si j'écris le nom de la fonction, ou un pointeur vers la fonction, je vais y arriver. Mais au fait, comment exécuter du code à un endroit dont on connait l'adresse ? Sans passer par asm() évidemment grin Et comment y passer de manière non-récursive, de manière à ne pas empiler les adresses de retour sur la pile ? ie comment faire un jmp vers un jmp vers une fonction quand on connait son adresse, st non un jsr ?
Le top : comment faire pour avoir une table de relogement pc-relative pour sauter à la fonction qu'on veut ? Avec encore en plus le côté plus "bra" que "bsr" ?

Autre question, et peut-être la seule la vraie : Comment voir les choses avec un oeil Ciste et non assembleuriste ? grin

2

Je ne suis pas sûr que je comprends très bien, mais est-ce que tes sous-fonctions sont utilisées à un unique endroit dans le code ? si oui tu peux les déclarer comme static inline et elles ne seront alors pas compilées comme des fonctions, mais mises directement dans la table de saut qui les appelle. J'ai fait ça partout dans foblub.

Sinon pour ce qui est de remplacer le bsr par bra, c'est le boulot de l'optimiseur ça (l'option -fomit-frame-pointer ou quelque chose du genre est peut-être nécessaire), ça n'est pas une question à te poser quand tu écris le programme.

Pour exécuter du code à un endroit dont tu connais l'adresse (tu as donc un pointeur de fonction vers cette endroit ?) ben tu fais juste l'appel de fonction normal avec la variable qui contient l'adresse. Si tu connais l'adresse et que tu veux en faire un pointeur de fonction, il faut caster (c'est comme ça que fait tigcclib pour les ROM call), avec une syntaxe imbitable. Et bien indiquer dans le type du cast quelle est la convention d'appel et tout, pour s'assurer que le compilateur appellera la fonction correctement.
avatar
« Le bonheur, c'est une carte de bibliothèque ! » — The gostak distims the doshes.
Membrane fondatrice de la confrérie des artistes flous.
L'univers est-il un dodécaèdre de Poincaré ?
(``·\ powaaaaaaaaa ! #love#

3

Sinon, n'y-t-ia pas longjump, ou un truc du genre ? Mais je déconseille complètement grin
avatar
Que cache le pays des Dieux ? - Forum Ghibli - Forum Littéraire

La fin d'un monde souillé est venue. L'oiseau blanc plane dans le ciel annonçant le début d'une longue ère de purification. Détachons-nous à jamais de notre vie dans ce monde de souffrance. Ô toi l'oiseau blanc, l'être vêtu de bleu, guide nous vers ce monde de pureté. - Sutra originel dork.

4

mais longjmp ça sert pas à exécuter du code binaire dont tu connais l'adresse, c'est un truc beaucoup plus compliqué que ça je crois, enfin je me trompe peut-être ^^
avatar
« Le bonheur, c'est une carte de bibliothèque ! » — The gostak distims the doshes.
Membrane fondatrice de la confrérie des artistes flous.
L'univers est-il un dodécaèdre de Poincaré ?
(``·\ powaaaaaaaaa ! #love#

5

En trifouillant les structures JMP_BUF, tu dois pouvoir arriver à faire exécuter du code binaire dont tu connais l'adresse... mais c'est sale grin

@Martial: ce que tu veux faire est plus compliqué qu'un switch / case...
avatar
Membre de la TI-Chess Team.
Co-mainteneur de GCC4TI (documentation en ligne de GCC4TI), TIEmu et TILP.
Co-admin de TI-Planet.

6

Merde, j'ai l'impression que je me suis over-mal exprimé, j'ai pas trop de réponse, là grin
mais est-ce que tes sous-fonctions sont utilisées à un unique endroit dans le code ?
Oui.
si oui tu peux les déclarer comme static inline et elles ne seront alors pas compilées comme des fonctions, mais mises directement dans la table de saut qui les appelle. J'ai fait ça partout dans foblub
Et que signifient static et inline ? Autrement que dans mon bouquin tout foireux ? triso
Sinon pour ce qui est de remplacer le bsr par bra, c'est le boulot de l'optimiseur ça (l'option -fomit-frame-pointer ou quelque chose du genre est peut-être nécessaire), ça n'est pas une question à te poser quand tu écris le programme.
Je parle pas des bsr/rts->bra, mais du fait d'appeler une fonction qui n'a pas re "return" en fait.
Grosso-merdo, si j'ai ça :
void func1 (void);
{...
func2();
...}

func2 a pas besoin de faire de return, mais va jumper directement ailleurs, peut-être même au début de func1. Donc pas la peine d'empiler des adresses de retour à foison.

Et pourquoi longjmp çaylemal ?

7

un mot encore sur le bsr -> bra : ça ne s'appelle pas un appel "non récursif", ça s'appelle récursion terminale (tail-recursion en anglais), ça peut t'aider de savoir ça si tu cherches dans la doc ^^

edit : ah non j'ai mal compris de quoi tu parlais... je pensais au cas où l'appel de func2 est la dernière instruction dans func1 (donc ça ne sert à rien de revenir à func1), c'est ça un appel terminal (et en fait récursion terminale stricto sensu c'est quand func2 = func1, la fonction se rappelle elle-même, éventuellement plein de fois, mais sans encombrer la pile inutilement).

Là si tu veux juste dire que ta fonction func2 ne termine jamais il faut la déclarer avec "attribute __noreturn__" et normalement l'optimiseur se débrouille avec cette info happy
avatar
« Le bonheur, c'est une carte de bibliothèque ! » — The gostak distims the doshes.
Membrane fondatrice de la confrérie des artistes flous.
L'univers est-il un dodécaèdre de Poincaré ?
(``·\ powaaaaaaaaa ! #love#

8

Ben purée, c'est expliqué où tout ça ? les no-return ?

sinon, pour les récursions terminales ou profondes, je connais, j'ai été fan de scheme trilove

9

Ce n'est pas dans l'esprit du C de sauter n'import où n'importe comment, à tel point qu'on dissuade généralement l'utilisation de goto, alors longjump, n'en parlons pas grin
avatar
Que cache le pays des Dieux ? - Forum Ghibli - Forum Littéraire

La fin d'un monde souillé est venue. L'oiseau blanc plane dans le ciel annonçant le début d'une longue ère de purification. Détachons-nous à jamais de notre vie dans ce monde de souffrance. Ô toi l'oiseau blanc, l'être vêtu de bleu, guide nous vers ce monde de pureté. - Sutra originel dork.

10

inline signifie que lorsque ta fonction est appelée, il doit en fait écrire directement le code de la fonction plutôt que de générer un appel de fonction. (Malheureusement c'est seulement une directive et pas un ordre, et le compilo est un peu bouché, j'avais dû jouer sur plusieurs options pour qu'il respecte "inline" (il y a un truc genre -finline-limit qu'il fallait mettre à une très grande valeur genre 100000 pour que ça marche).)

static, alors c'est l'autre sens de static que celui dont j'avais parlé la dernière fois grin, signifie que ta fonction est locale à l'unité de compilation (qui a priori correspond à un fichier .c). Ça a pour effet que si ta fonction n'est pas appelée normalement dans cette unité de compilation (soit elle n'est pas appelée du tout, soit elle est inline), il ne va pas générer de code séparé pour cette fonction.

Donc si une fonction est appelée en tout et pour tout à un endroit, il suffit de la déclarer static inline (et d'utiliser les bonnes options), et il ne créera pas de fonction standalone inutile, il utilisera juste le code de la fonction à l'endroit où on en a besoin. C'est très pratique en combinaison avec des tables de sauts.
avatar
« Le bonheur, c'est une carte de bibliothèque ! » — The gostak distims the doshes.
Membrane fondatrice de la confrérie des artistes flous.
L'univers est-il un dodécaèdre de Poincaré ?
(``·\ powaaaaaaaaa ! #love#

11

./8 > http://tigcc.ticalc.org/doc/gnuexts.html#SEC85 (en fait c'est __attribute__ ((noreturn)) — ça fait longtemps que j'ai utilisé ça cheeky)

pour les fonctions inline : http://tigcc.ticalc.org/doc/gnuexts.html#SEC93
Il est censé y avoir une option -Winline qui te prévient quand il a pas inliné une fonction et te dit pourquoi, mais sur la (vieille maintenant) version de tigcc que j'utilisais ça ne fonctionnait pas sad. Je sais pas si ça a été réparé. L'attribut always inline dont ils parlent ne marchait pas non plus.
avatar
« Le bonheur, c'est une carte de bibliothèque ! » — The gostak distims the doshes.
Membrane fondatrice de la confrérie des artistes flous.
L'univers est-il un dodécaèdre de Poincaré ?
(``·\ powaaaaaaaaa ! #love#

12

./11: inline, -Winline, __attribute__((__always_inline__)) fonctionnent mieux avec le GCC 4.1 de TIGCC / GCC4TI que ce qu'ils fonctionnaient à une époque smile

[EDIT: typo]
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

cool, bonne nouvelle happy
avatar
« Le bonheur, c'est une carte de bibliothèque ! » — The gostak distims the doshes.
Membrane fondatrice de la confrérie des artistes flous.
L'univers est-il un dodécaèdre de Poincaré ?
(``·\ powaaaaaaaaa ! #love#