Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Portabilité du *concept* des fonctions "naked"

40 réponses
Avatar
Patrick Brunet
Bonjour.

Je voudrais faire un tour des différentes plates-formes sous C pour savoir
s'il y existe des équivalents d'une extension Microsoft, les fonctions
"naked".

Une fonction dotée de cet attribut est appelée extérieurement selon la
convention dite cdecl (le code appelant empile les arguments puis la partie
externe de la stackframe, et fait le ménage au retour), mais par contre
aucune stackframe n'est créée du côté interne.

Le but est de laisser le programmeur faire ce qu'il veut ex-nihilo,
généralement avec de l'assembleur inline. C'est très utile dans certains
contextes (drivers par exemple).

Pour ma part, j'y vois une possibilité d'implémentation de la technique
d'enfilage de pseudo-instructions, avec par rapport au goto l'avantage de la
récursivité.

Merci de me dire si vous connaissez des concepts similaires sur les
principales plates-formes (système + compilo) autres que (Windows + Cµsoft).

Merci beaucoup de votre aide.
Cordialement,

Patrick Brunet

10 réponses

1 2 3 4
Avatar
Patrick BRUNET
Bonsoir.

"Gabriel Dos Reis" a écrit dans le message
news:
"Patrick Brunet" <Patrick.Brunet @ cned.fr> writes:

| Arnaud Boulan a évoqué la possibilité (gcc) d'avoir l'adresse d'un
simple

| label. Je cherche actuellement à savoir si ça c'est normalisé.

Prendre l'adresse d'un label est un des GNUismes que je voudrais voir
confiner au niveau -10. C'est une merde totale ce truc.



J'avais vérifié entre-temps que ça n'a rien d'un idiome standard.

Mais dans mon cas, ça m'aurait bien dépanné pour faire du goto calculé (je
rappelle que dans mon contexte, le C n'est pas un langage source mais une
cible intermédiaire, donc la programmation structurée est hors de propos).

Je trouverai un autre moyen ...

Cordialement,

PZB

Avatar
Gabriel Dos Reis
"Patrick BRUNET" <zener-fusekey @ fr.st> writes:

| Mais dans mon cas, ça m'aurait bien dépanné pour faire du goto calculé (je
| rappelle que dans mon contexte, le C n'est pas un langage source mais une
| cible intermédiaire, donc la programmation structurée est hors de propos).

Quel est le point technique fondamental qui empêche une programmation
structurée ?

-- Gaby
Avatar
Emmanuel Delahaye
In 'fr.comp.lang.c', "Patrick BRUNET" <zener-fusekey @ fr.st> wrote:

Mais dans mon cas, ça m'aurait bien dépanné pour faire du goto calculé (je
rappelle que dans mon contexte, le C n'est pas un langage source mais une
cible intermédiaire, donc la programmation structurée est hors de propos).


Un pointeur de fonction ne va pas?

<HS>
Si tu manques de pile, tu peux toujours la réinitialiser après. J'ai utilisé
cette technique un peu barbare dans du code d'init un peu velu de logiciel
embarqué. Ca fonctionne.
</HS>

--
-ed- [remove YOURBRA before answering me]
The C-language FAQ: http://www.eskimo.com/~scs/C-faq/top.html
<blank line>
FAQ de f.c.l.c : http://www.isty-info.uvsq.fr/~rumeau/fclc/

Avatar
Patrick BRUNET
Bonsoir.

"Emmanuel Delahaye" a écrit dans le message news:

In 'fr.comp.lang.c', "Patrick BRUNET" <zener-fusekey @ fr.st> wrote:

Mais dans mon cas, ça m'aurait bien dépanné pour faire du goto calculé
(je


rappelle que dans mon contexte, le C n'est pas un langage source mais
une


cible intermédiaire, donc la programmation structurée est hors de
propos).



Un pointeur de fonction ne va pas?



C'est pourquoi je suis parti sur l'idée des fonctions *naked* et je cherche
un concept équivalent *conceptuellement* portable (ie: C ANSI).

<HS>
Si tu manques de pile, tu peux toujours la réinitialiser après. J'ai
utilisé

cette technique un peu barbare dans du code d'init un peu velu de logiciel
embarqué. Ca fonctionne.
</HS>



Pas de problème de pile a priori. Le but des naked n'est pas d'alléger la
pile mais de limiter au strict minimum le coût en temps de calcul de chaque
enfilage.

Si je ne trouve pas de solution clean pour mon goto calculé, je devrai me
résigner à utiliser des fonctions ordinaires à signature uniforme void(
void).

Cordialement,

PZB


Avatar
Gabriel Dos Reis
"Patrick BRUNET" <zener-fusekey @ fr.st> writes:

| Bonsoir.
|
| "Gabriel Dos Reis" a écrit dans le message
| news:
| > "Patrick BRUNET" <zener-fusekey @ fr.st> writes:
| >
| > | Mais dans mon cas, ça m'aurait bien dépanné pour faire du goto calculé
| (je
| > | rappelle que dans mon contexte, le C n'est pas un langage source mais
| une
| > | cible intermédiaire, donc la programmation structurée est hors de
| propos).
| >
| > Quel est le point technique fondamental qui empêche une programmation
| > structurée ?
|
| Il y en a deux :
|
| 1) l'algorithme est composé dynamiquement (au runtime), et donc implémenté
| par enfilage de p-instructions,

ceci en soit n'est pas une raison qui élimine une programmation
structurée.

| 2) pour des raisons commerciales qui vont immanquablement faire hurler
| certains, il y a un objectif cryptographique.

au risque de te décevoir, un goto calculé n'est pas un moyen de
cryptage :-/

| Pour autant, le code C qui sert de cible intermédiaire est bien destiné à
| être ensuite compilé en un exécutable.

aucun de points (1) et (2) n'implique que « la programmation
structurée est hors de propos ».

| Le but de cette étape C est
| d'apporter une solution de portabilité quasi universelle, irréalisable avec
| de l'assembleur.

dans ce cas, tu ne cherches pas un goto calculé :-)


| C'est pourquoi j'ai besoin d'un goto calculé performant implémentable en C
| standard.

-- Gaby
Avatar
Patrick BRUNET
Bonjour.

"Gabriel Dos Reis" a écrit dans le message
news:
"Patrick BRUNET" <zener-fusekey @ fr.st> writes:

| Bonsoir.
|
| "Gabriel Dos Reis" a écrit dans le
message

| news:
| > "Patrick BRUNET" <zener-fusekey @ fr.st> writes:
| >
| > | Mais dans mon cas, ça m'aurait bien dépanné pour faire du goto
calculé

| (je
| > | rappelle que dans mon contexte, le C n'est pas un langage source
mais

| une
| > | cible intermédiaire, donc la programmation structurée est hors de
| propos).
| >
| > Quel est le point technique fondamental qui empêche une programmation
| > structurée ?
|
| Il y en a deux :
|
| 1) l'algorithme est composé dynamiquement (au runtime), et donc
implémenté

| par enfilage de p-instructions,

ceci en soit n'est pas une raison qui élimine une programmation
structurée.



Au niveau de chaque p-instruction peut-être, mais au niveau de leur enfilage
c'est différent.
Si en effet au runtime l'algorithme était généré en C puis compilé, je
pourrais faire l'effort de générer du code "structuré et humainement
lisible".
Mais comme il est compilé à l'avance et que seul l'aiguillage se fait au
runtime, l'enfilage est AMHA le seul moyen d'espérer une bonne efficacité.



| 2) pour des raisons commerciales qui vont immanquablement faire hurler
| certains, il y a un objectif cryptographique.

au risque de te décevoir, un goto calculé n'est pas un moyen de
cryptage :-/



En soi non, mais au total, ça dépend de comment il est calculé, Gnark!²


| Pour autant, le code C qui sert de cible intermédiaire est bien destiné
à

| être ensuite compilé en un exécutable.

aucun de points (1) et (2) n'implique que « la programmation
structurée est hors de propos ».



Mes deux réponses combinées semblent justifier le contraire, au moins donc
pour l'assemblage des p-instructions.
Pour leur code interne, dans mon propre intérêt, c'est différent.

| Le but de cette étape C est
| d'apporter une solution de portabilité quasi universelle, irréalisable
avec

| de l'assembleur.

dans ce cas, tu ne cherches pas un goto calculé :-)



J'en cherche une implémentation standardisable en C ANSI.

Comment nommerais-tu un algorithme mutant réalisé par enfilage au runtime de
sections de code prédéfinies, elles-mêmes fournies comme les sections d'un
monobloc de C compilé (même si les codes effectifs se retrouvent finalement
dans des fonctions interchangeables invoquées par les sections du monobloc)
?


| C'est pourquoi j'ai besoin d'un goto calculé performant implémentable en
C

| standard.



Merci pour tes précieux conseils.

PZB

Avatar
Patrick Brunet
Bonjour.

"Gabriel Dos Reis" a écrit dans le message
news:
"Patrick BRUNET" <zener-fusekey @ fr.st> writes:

[...]


Je fais la différence entre "code structuré" et "code structuré et
humainement lisible". Un code généré automatiquement par des outils
n'a pas forcément besoin d'être dans la deuxième catégorie.



Oui, je sens ce que tu veux dire.
Il s'agit pour l'intérieur de mes p-instructions d'un code très court, qui
donc relève d'un "sous-algorithme" très élémentaire, voire d'une séquence de
quelques instructions C. Pour l'algorithme général par contre, sa
présentation ressemblera à la maquette que je vais donner plus bas, et là
c'est plus vraiment structuré (dans la mesure où c'est de la salade de goto
réputée "à éviter pour les humains", mais nécessité technique oblige pour
mon compilo).

[...]

| > | Le but de cette étape C est
| > | d'apporter une solution de portabilité quasi universelle,
irréalisable

| avec
| > | de l'assembleur.
| >
| > dans ce cas, tu ne cherches pas un goto calculé :-)
| >
|
| J'en cherche une implémentation standardisable en C ANSI.


Je ne sais pas si ce que je vais te dire va beaucoup t'aider :

Le comité C considère qu'il est lui-même en mode maintenance en ce
qui concerne le core language. Je doute très fortement qu'il ait
envie d'ajouter des goto calculés au langage -- cela a beaucoup
d'implication que tu ne le penses.



J'imagine bien, mal maîtrisé, c'est une cata en perspective.

Y a-t-il des comités qui étudient sérieusement C considéré comme une cible
intermédiaire pour des compilateurs de langages divers de plus haut niveau ?
L'intérêt est double :
- assurer la portabilité implicite de ces langages sur la plupart des
plates-formes,
- d'un point de vue juridicommercial, apporter une solution intermédiaire à
l'obligation de délivrer les sources (le dernier numéro de MISC déballe à ce
propos tout l'imbroglio du droit à la décompilation et c'est pas triste).

Evidemment, une telle solution peut être moins performante (pas trop tout de
même) que la génération directe de code machine, mais selon l'intérêt
pratique du fameux langage de haut niveau, la performance brute peut devenir
une sous-priorité...


Mais en fait je n'attends pas du comité C la normalisation du goto calculé.
Je me contenterais d'une possibilité de l'implémenter moi-même de manière
standard, donc sans assembleur.


| Comment nommerais-tu un algorithme mutant réalisé par enfilage au
runtime de

| sections de code prédéfinies, elles-mêmes fournies comme les sections
d'un

| monobloc de C compilé (même si les codes effectifs se retrouvent
finalement

| dans des fonctions interchangeables invoquées par les sections du
monobloc)

| ?

cela me fait penser au mécanisme de fonctions virtuelles en C++. Mais
je présume que j'ai besoin d'avoir une description plus précise avant
de me prononcer.



Voilà une petite maquette pour préciser les idées :
- le code effectif des p-instructions peut éventuellement être déporté dans
des fonctions (avec une petite perte de performance),
- goto [Next] symbolise ce que je veux implémenter. Le choix de la cible
n'est déterminé qu'au runtime.

static char WorkSpace[ENOUGH_BYTES];
static char * pxCurrentPosition;

void main( ...)
{
/* Some initialization code */
goto [Next];
Instruction1:
/* Code for p-instruction 1 */
/* operates on WorkSpace[] at pxCurrentPosition
then prepares them for the next p-instruction
then computes the result for [Next] below : */
goto [Next];
Instruction2:
/* Code for p-instruction 2 */
/* similar */
goto [Next];
...
InstructionN:
/* Code for p-instruction N */
/* similar */
goto [Next];
Termination:
/* Some exit code */
}

Une implémentation possible est d'utiliser un tableau de N pointeurs de
fonctions à signature identique void(void).
J'éssaie seulement de limiter le surcoût en performances des appels. C'est
pourquoi je m'intéressais au *concept* des fonctions *naked* qui justement
semblent avoir été introduites dans ce but pour l'écriture de drivers.

Merci pour tes précieux conseils.

Cordialement,

PZB

Avatar
Patrick Brunet
Bonjour.

"Richard Delorme" a écrit dans le message news:
3f4f25be$0$20950$

Bonjour.

Je voudrais faire un tour des différentes plates-formes sous C pour
savoir


s'il y existe des équivalents d'une extension Microsoft, les fonctions
"naked".

Une fonction dotée de cet attribut est appelée extérieurement selon la
convention dite cdecl (le code appelant empile les arguments puis la
partie externe de la stackframe, et fait le ménage au retour), mais par
contre aucune stackframe n'est créée du côté interne.


A propos de naked, la doc de microsoft dit :
« For functions declared with the naked attribute, the compiler generates
code without prolog and epilog code. You can use this feature to write
your

own prolog/epilog code using inline assembler code. Naked functions are
particularly useful in writing virtual device drivers. »

A propos de prolog et d'epilog, elle dit

prolog :
push ebp ; Save ebp
mov ebp, esp ; Set stack frame pointer
sub esp, localbytes ; Allocate space for locals
push <registers> ; Save registers

epilog :
pop <registers> ; Restore registers
mov esp, ebp ; Restore stack pointer
pop ebp ; Restore ebp
ret ; Return from function


l'effet de naked est donc plus ou moins équivalent à l'effet de l'option
-fomit-frame-pointer de gcc (sauf que cela affecte toutes les fonctions du
programmes).



Pas moyen de faire ça localement avec un pragma ?
Ou à la limite sur un seul fichier, à condition de pouvoir appeler sa
fonction de tête à partir du reste du code compilé normalement (ce qui est
sans doute requis par diverses librairies) ?

Merci.

Cordialement,

PZB


Avatar
Emmanuel Delahaye
In 'fr.comp.lang.c', "Patrick Brunet" <Patrick.Brunet @ cned.fr> wrote:

Pas moyen de faire ça localement avec un pragma ?


Les pragmas sont des extensions des compilateurs, donc par définition non
portables.

--
-ed- [remove YOURBRA before answering me]
The C-language FAQ: http://www.eskimo.com/~scs/C-faq/top.html
<blank line>
FAQ de f.c.l.c : http://www.isty-info.uvsq.fr/~rumeau/fclc/

Avatar
Richard Delorme

Voilà une petite maquette pour préciser les idées :
- le code effectif des p-instructions peut éventuellement être déporté
dans des fonctions (avec une petite perte de performance),
- goto [Next] symbolise ce que je veux implémenter. Le choix de la cible
n'est déterminé qu'au runtime.

static char WorkSpace[ENOUGH_BYTES];
static char * pxCurrentPosition;

void main( ...)
{
/* Some initialization code */
goto [Next];
Instruction1:
/* Code for p-instruction 1 */
/* operates on WorkSpace[] at pxCurrentPosition
then prepares them for the next p-instruction
then computes the result for [Next] below : */
goto [Next];
Instruction2:
/* Code for p-instruction 2 */
/* similar */
goto [Next];
...
InstructionN:
/* Code for p-instruction N */
/* similar */
goto [Next];
Termination:
/* Some exit code */
}

Une implémentation possible est d'utiliser un tableau de N pointeurs de
fonctions à signature identique void(void).
J'éssaie seulement de limiter le surcoût en performances des appels. C'est
pourquoi je m'intéressais au *concept* des fonctions *naked* qui
justement semblent avoir été introduites dans ce but pour l'écriture de
drivers.


Pourquoi pas un switch case ?

for(;;) {
switch(next) {
case INSTRUCTION_1:
/* Code for p-instruction 1 */
/* operates on WorkSpace[] at pxCurrentPosition
then prepares them for the next p-instruction
then computes the result for the next case : */
break;
case INSTRUCTION_2:
/* Code for p-instruction 2 */
break;

...
case INSTRUCTION_N:
/* Code for p-instruction n */
break;
default: /* termination */
return;
}
}

--
Richard

1 2 3 4