Derniers sujets
Qui est en ligne ?
Il y a en tout 2 utilisateurs en ligne :: 0 Enregistré, 0 Invisible et 2 Invités Aucun
Le record du nombre d'utilisateurs en ligne est de 29 le Mer 25 Fév 2015 - 14:01
Connexion
Statistiques
Nous avons 243 membres enregistrésL'utilisateur enregistré le plus récent est paul225l
Nos membres ont posté un total de 8922 messages dans 811 sujets
besoin d'un affichage printf plus rapide
+3
retroric
Ladywasky
goyo
7 participants
Forum Oric :: Forums :: Forum Public :: Programmation en C
Page 1 sur 1
besoin d'un affichage printf plus rapide
Hello,
j'ai vite codé un mini visualiseur de mémoire mais l'affichage avec printf est lent pour visualiser les valeurs Int et Char (adresse mémoire et sa valeur). Y aurait il en C un moyen d'optimiser la chose .. ?
j'ai vite codé un mini visualiseur de mémoire mais l'affichage avec printf est lent pour visualiser les valeurs Int et Char (adresse mémoire et sa valeur). Y aurait il en C un moyen d'optimiser la chose .. ?
- Code:
#include <lib.h>
void MemoryDisplay(unsigned int currentAddr,char mode)
{
int x;
int y;
int rowCount=24;
int colCount=40;
unsigned char byte;
unsigned int addrIndex=currentAddr;
x=2;
while(x<colCount)
{
y=4;
while(y<rowCount)
{
byte=peek(addrIndex);
if (byte<30||byte>126)
byte='.';
if (mode==0)
{
gotoxy(x,y);
printf("%x=",addrIndex);
}
gotoxy(x+6,y);printf("%d ",byte);
gotoxy(x+10,y);putchar(byte);
addrIndex++;
y++;
}
x+=13;
}
}
void main()
{
unsigned int currentAddr=0x1c0;
unsigned int pokeAddr;
unsigned int currentAddrSave;
char mode;
int i=0;
unsigned char flagFin;
char a;
unsigned char byte;
poke(0x26A,10);
poke(0x24E,8);
poke(0x24F,6);
flagFin=1;
mode=1;
cls();
MemoryDisplay(currentAddr,0);
gotoxy(0,0);printf("'O'-60 'P'+60 'G'Goto 'C'POKE (Q)uit");
do{
currentAddrSave=currentAddr;
a=key();
if( a != 0 )
{
if(a== 'Q' || a=='A')
{
flagFin=0;
}
if(a==11)
{
if (currentAddr>0)
{
currentAddr--;
}
}
if(a==10)
{
if (currentAddr<65535)
{
currentAddr++;
}
}
if(a== 'O'|| a==8)
{
if (currentAddr>0)
{
currentAddr-=60;
}
}
if(a== 'P'|| a==9)
{
if (currentAddr<65535)
{
currentAddr+=60;
}
}
if(a== 'G')
{
gotoxy(2,26);printf("GOTO ADDR(hex):");
scanf("%x", ¤tAddr);
cls();
MemoryDisplay(currentAddr,0);
}
if (a=='C'|| a=='K')
{
gotoxy(2,24);printf("POKE ADDR(hex):");
scanf("%x", &pokeAddr);
gotoxy(2,25);printf("VALUE (dec):");
scanf("%d", &byte);
poke(pokeAddr,byte);
gotoxy(2,24);printf(" ");
gotoxy(2,25);printf(" ");
gotoxy(2,26);printf("POKE ADDR : %x = %d ",pokeAddr,byte);
MemoryDisplay(currentAddr,0);
}
}
if (currentAddrSave==currentAddr)
mode=1;
else
mode=0;
//gotoxy(2,25);printf("key=%d ",a);
MemoryDisplay(currentAddr,mode);
} while(flagFin);
}
goyo- Messages : 199
Date d'inscription : 02/05/2014
Age : 52
Localisation : Massy
Re: besoin d'un affichage printf plus rapide
On peut trouver ça dans l'OSDK.
Mais je ne pense pas que dans ce cas ce soit l'affichage le plus lent mais la conversion du printf des adresses (qui sont des entiers) en chaînes de caractères affichable.
Mais je ne pense pas que dans ce cas ce soit l'affichage le plus lent mais la conversion du printf des adresses (qui sont des entiers) en chaînes de caractères affichable.
Ladywasky- Messages : 240
Date d'inscription : 25/08/2018
Age : 53
Re: besoin d'un affichage printf plus rapide
Salut Gweg / Goyo,
Je vois qu'il y a beaucoup (trop ?) d'appels à gotoxy() dans ton code et que tu pourrais sans doute en éviter certains.
Et que tu fais également des appels à printf() ET à putchar(), que tu pourrais sans doute rassembler dans un seul printf()
Exemple:
gagnerait sans doute (à voir... et sous réserve que printf() dans l'OSDK accepte l'argument numérique pour les spécificateurs de type) à être transformé en:
Par ailleurs, je ne sais pas comment est défini peek (si c'est un #define ou une fonction), mais si c'est une fonction, l'overhead est énorme et il vaut mieux utiliser le #define suivant :
Après, printf() est évidemment très lent vu qu'il doit interpréter de façon complexe une chaîne de caractères avec une multitude d'arguments possibles, donc tu ferais sans doute mieux de te définir un équivalent de la fonction putchar() pour afficher un nombre décimal...
Exemple naïf en C pour afficher un nombre positif entre 0 et 255 (qui d'après ce que j'ai compris est ton besoin):
Je suis pas sûr que ce soit hyper performant en C, mais c'est peut-être déjà plus performant que printf(), et sinon ça peut se recoder en asm 6502 assez facilement (sauf pour les divisions )...
Voilà, ce n'est sans doute pas la réponse avec la solution miracle que tu attendais, mais j'espère quand même t'avoir un peu aidé
A+
Laurent
Je vois qu'il y a beaucoup (trop ?) d'appels à gotoxy() dans ton code et que tu pourrais sans doute en éviter certains.
Et que tu fais également des appels à printf() ET à putchar(), que tu pourrais sans doute rassembler dans un seul printf()
Exemple:
- Code:
gotoxy(x+6,y);printf("%d ",byte);
gotoxy(x+10,y);putchar(byte);
gagnerait sans doute (à voir... et sous réserve que printf() dans l'OSDK accepte l'argument numérique pour les spécificateurs de type) à être transformé en:
- Code:
gotoxy(x+6,y);printf("%3d %c", byte, byte); // affichage de la 1ere valeur avec padding sur 3 caractères
Par ailleurs, je ne sais pas comment est défini peek (si c'est un #define ou une fonction), mais si c'est une fonction, l'overhead est énorme et il vaut mieux utiliser le #define suivant :
- Code:
#define peek(x) (*x)
Après, printf() est évidemment très lent vu qu'il doit interpréter de façon complexe une chaîne de caractères avec une multitude d'arguments possibles, donc tu ferais sans doute mieux de te définir un équivalent de la fonction putchar() pour afficher un nombre décimal...
Exemple naïf en C pour afficher un nombre positif entre 0 et 255 (qui d'après ce que j'ai compris est ton besoin):
- Code:
/* Affichage d'un entier entre 0 et 255 */
void putdec(unsigned char n) {
if (n > 99) { // affichage chiffre des centaines
putchar('0' + n / 100);
}
if (n > 9) { // affichage chiffre des dizaines
putchar('0' + (n % 100) / 10);
}
putchar('0' + n % 10); // affichage du chiffre des unités
}
Je suis pas sûr que ce soit hyper performant en C, mais c'est peut-être déjà plus performant que printf(), et sinon ça peut se recoder en asm 6502 assez facilement (sauf pour les divisions )...
Voilà, ce n'est sans doute pas la réponse avec la solution miracle que tu attendais, mais j'espère quand même t'avoir un peu aidé
A+
Laurent
Dernière édition par laurentd75 le Jeu 29 Nov 2018 - 15:37, édité 1 fois
Re: besoin d'un affichage printf plus rapide
Après réflexion, petit "refactoring" de la fonction d'affichage d'un entier pour éviter les divisions:
- Code:
/* Affichage d'un entier entre 0 et 255 */
void putdec(unsigned char n) {
// affichage chiffre des centaines
if(n > 199) {
putchar('2');
n -= 200;
}
else if (n > 99) {
putchar('1');
n -= 100;
}
// affichage des dizaines
if (n > 89) putchar('9');
else if (n > 79) putchar('8');
else if (n > 69) putchar('7');
else if (n > 59) putchar('6');
else if (n > 49) putchar('5');
else if (n > 39) putchar('4');
else if (n > 29) putchar('3');
else if (n > 19) putchar('2');
else if (n > 9) putchar('1');
// affichage du chiffre des unités
putchar('0' + n % 10);
}
Re: besoin d'un affichage printf plus rapide
Merci Laurent pour ces infos.laurentd75 a écrit:Après réflexion, petit "refactoring" de la fonction d'affichage d'un entier pour éviter les divisions:
- Code:
/* Affichage d'un entier entre 0 et 255 */
void putdec(unsigned char n) {
// affichage chiffre des centaines
if(n > 199) {
putchar('2');
n -= 200;
}
else if (n > 99) {
putchar('1');
n -= 100;
}
// affichage des dizaines
if (n > 89) putchar('9');
else if (n > 79) putchar('8');
else if (n > 69) putchar('7');
else if (n > 59) putchar('6');
else if (n > 49) putchar('5');
else if (n > 39) putchar('4');
else if (n > 29) putchar('3');
else if (n > 19) putchar('2');
else if (n > 9) putchar('1');
// affichage du chiffre des unités
putchar('0' + n % 10);
}
j'ai essayé la méthode putdec() mais elle s'avère plus lente que le printf("%d",byte);
je pense qu'il faudrait la faire en assembleur c'est la seule solution que je vois.
goyo- Messages : 199
Date d'inscription : 02/05/2014
Age : 52
Localisation : Massy
Re: besoin d'un affichage printf plus rapide
Bizarre, je pensais pourtant que ce serait plus performant, même avec plusieurs tests et appels à putchar() !!
==> j'ai qd même l'impression que ce compilo est vraiment naze, car je vois pas comment des appels à des fonctions peuvent être plus lents qu'une division en 6502 ??!! (car je suppose que printf "%d" réalise des divisions...)
Autre piste avant de se lancer dans l'ASM:
Utiliser puts() et itoa() au lieu de printf() , normalement ça fait au moins gagner le temps de l'analyse syntaxique du printf()...:
==> Au lieu de
Essaie ça pour voir:
NB: tu dois ajouter l'include suivant pour itoa() :
==> j'ai qd même l'impression que ce compilo est vraiment naze, car je vois pas comment des appels à des fonctions peuvent être plus lents qu'une division en 6502 ??!! (car je suppose que printf "%d" réalise des divisions...)
Autre piste avant de se lancer dans l'ASM:
Utiliser puts() et itoa() au lieu de printf() , normalement ça fait au moins gagner le temps de l'analyse syntaxique du printf()...:
==> Au lieu de
- Code:
printf("%d",byte);
Essaie ça pour voir:
- Code:
puts(itoa(byte));
NB: tu dois ajouter l'include suivant pour itoa() :
- Code:
#include <stdlib.h>
Re: besoin d'un affichage printf plus rapide
ps - je me rappelle plus si c'est cc65 dans l'OSDK, mais is c'est le cas, le source de printf() est en ASM, pas en C, ceci explique sans doute que le printf() était + performant que mon "optimisation"...:
cf. https://github.com/cc65/cc65/blob/master/libsrc/common/_printf.s
cf. https://github.com/cc65/cc65/blob/master/libsrc/common/_printf.s
Re: besoin d'un affichage printf plus rapide
Vous pouvez aussi utiliser sprintf, en mettant en addresse de destination la position écran voulue:
sprint((char*)0xbb80+x+(y*40),"%d",valeur)
ca a le mérite de ne pas utiliser la fonction d'affichage du BASIC, ca tappe directement en mémoire.
Après si le but c'est juste de débogger, le plus rapide c'est d'afficher en hexadécimal, ca aussi le mérite de faire en sorte de pouvoir tout aligner a l'écran sans problème.
sprint((char*)0xbb80+x+(y*40),"%d",valeur)
ca a le mérite de ne pas utiliser la fonction d'affichage du BASIC, ca tappe directement en mémoire.
Après si le but c'est juste de débogger, le plus rapide c'est d'afficher en hexadécimal, ca aussi le mérite de faire en sorte de pouvoir tout aligner a l'écran sans problème.
Dbug- Messages : 248
Date d'inscription : 06/01/2013
Re: besoin d'un affichage printf plus rapide
laurentd75 a écrit:Après réflexion, petit "refactoring" de la fonction d'affichage d'un entier pour éviter les divisions:
- Code:
/* Affichage d'un entier entre 0 et 255 */
void putdec(unsigned char n) {
// affichage chiffre des centaines
if(n > 199) {
putchar('2');
n -= 200;
}
else if (n > 99) {
putchar('1');
n -= 100;
}
// affichage des dizaines
if (n > 89) putchar('9');
else if (n > 79) putchar('8');
else if (n > 69) putchar('7');
else if (n > 59) putchar('6');
else if (n > 49) putchar('5');
else if (n > 39) putchar('4');
else if (n > 29) putchar('3');
else if (n > 19) putchar('2');
else if (n > 9) putchar('1');
// affichage du chiffre des unités
putchar('0' + n % 10);
}
j'ai fait quelques tests à l'aide de la fonction clock();
voici les valeur de temps écoulé:
avec "for()"
gotoxy(x,y); puts(itoa(byte)); = 527
gotoxy(x,y);printf("%d",byte); = 431
gotoxy(x,y); putdec(byte); = 513
avec "do while()"
gotoxy(x,y);printf("%x",byte); = 412
gotoxy(x,y);putdec(byte); = 490
donc "do while()" + "printf("%d",valeur) semble le plus rapide
code utilisé:
for(j=0;j<16;j++)
{
for(y=1;y<25;y++)
{
for(x=2;x<39;x+=12)
{
gotoxy(x,y);printf("%d",byte);
}
}
}
goyo- Messages : 199
Date d'inscription : 02/05/2014
Age : 52
Localisation : Massy
Re: besoin d'un affichage printf plus rapide
Incroyable... Comme quoi, l'optimisation, c'est pas juste théorique, faut toujours valider par la pratique !!! :-)
Honnêtement, j'en reviens pas que puts(itoa(byte)) soit plus lent que printf(), c'est juste dingue, ça veut dire en gros que l'overhead de l'appel de fonction à itoa() est plus important que le temps d'analyse syntaxique de la chaîne de format passée à printf() !! Et du coup je trouve aussi bizarre que ma fonction putdec(byte) soit plus rapide que puts(itoa(byte)), alors que ma fonction réalise de 1 à 3 appels à putchar() !?
En tous cas, je vais me replonger dans les articles du CEO Mag sur les différents compilateurs (cc65, lcc) , et je ferai un peu de "métrologie" de mon côté également pour comparer le comportement et les perfs de chaque compilo...
Honnêtement, j'en reviens pas que puts(itoa(byte)) soit plus lent que printf(), c'est juste dingue, ça veut dire en gros que l'overhead de l'appel de fonction à itoa() est plus important que le temps d'analyse syntaxique de la chaîne de format passée à printf() !! Et du coup je trouve aussi bizarre que ma fonction putdec(byte) soit plus rapide que puts(itoa(byte)), alors que ma fonction réalise de 1 à 3 appels à putchar() !?
En tous cas, je vais me replonger dans les articles du CEO Mag sur les différents compilateurs (cc65, lcc) , et je ferai un peu de "métrologie" de mon côté également pour comparer le comportement et les perfs de chaque compilo...
Re: besoin d'un affichage printf plus rapide
PS - quoi qu'il en soit, je rejoins DBug sur le fait que si ton programme est destiné à être un outil de dev, il est sans doute préférable d'afficher les valeurs en hexa plutôt qu'en décimal, ça ira plus vite (un chiffre de moins à afficher en général), ce sera aligné, et généralement c'est plus intéressant d'avoir la valeur en hexa qu'en décimal...
En revanche, à part économiser un appel de fonction et l'overhead associé, je ne vois pas trop le gain d'utiliser sprintf() par rapport à printf()... Je pense (j'espère même) que gotoxy() est optimisée et ne fait pas appel à une routine lente de la ROM... Et je ne suis pas persuacdé que le compilo C optimise la multiplication par 40...
En revanche, à part économiser un appel de fonction et l'overhead associé, je ne vois pas trop le gain d'utiliser sprintf() par rapport à printf()... Je pense (j'espère même) que gotoxy() est optimisée et ne fait pas appel à une routine lente de la ROM... Et je ne suis pas persuacdé que le compilo C optimise la multiplication par 40...
Re: besoin d'un affichage printf plus rapide
laurentd75 a écrit:Incroyable... Comme quoi, l'optimisation, c'est pas juste théorique, faut toujours valider par la pratique !!! :-)
Honnêtement, j'en reviens pas que puts(itoa(byte)) soit plus lent que printf(), c'est juste dingue, ça veut dire en gros que l'overhead de l'appel de fonction à itoa() est plus important que le temps d'analyse syntaxique de la chaîne de format passée à printf() !! Et du coup je trouve aussi bizarre que ma fonction putdec(byte) soit plus rapide que puts(itoa(byte)), alors que ma fonction réalise de 1 à 3 appels à putchar() !?
En tous cas, je vais me replonger dans les articles du CEO Mag sur les différents compilateurs (cc65, lcc) , et je ferai un peu de "métrologie" de mon côté également pour comparer le comportement et les perfs de chaque compilo...
Cela dépend comment c'est codé puts. Dans cc65, c'est du C qui appelle _write. Dans certaines libs, (conio) dans cc65, cela appelle cputc (affiche un caractère) quand on appelle cputs. Donc, les comportements sont différents en fonction des libs et des compilateurs.
Jede- Messages : 308
Date d'inscription : 20/04/2016
Localisation : Var
Re: besoin d'un affichage printf plus rapide
Il y a des options de compilation qui permettent d'optimiser un peu le code généré: -Or, -Oi, -Os par exmple pour cc65.
Il y a aussi d'autres optimisations simples qui sont possibles avant de s'attaquer aux librairies du compilateur ou de passer à l'assembleur.
Par exemple utiliser des variables de type unsigned char à la place de variables de type int quand c'est possible, ce qui est le cas ici pour x et y.
Ou encore remplacer:
En cumulant uniquement ces 2 modifications, les affectations et les tests sont simplifiés et il y a moins d'appels à des sous routines, et comme ces opérations sont faites à chaque itération de boucle, la boucle devrait tourner plus rapidement.
Par exemple, l'instruction y++ donne successivement:
Aucune modification:
Utilisation de -Or:
Utilisation de unsigned char y (plus d'instructions mais aucun appel de routines)
Le même avec l'option -Or:
On arrive à des optimisations similaires pour les tests des boucles while
Par exemple, on passe de
à
en cumulant l'utilisation de #define et de unsigned char et des options de compilation.
Après, il reste aussi les routines des libraries qui ne sont pas toujours optimisées pour la vitesse d'exécution ou la taille du code généré, mais en faisant ces quelques modification, les boucles devraient gagner un peu en rapidité.
Il est toujours intéressant devoir le code produit par le compilateur dans plusieurs cas de figures, ça permet de voir quelles corrections apporter pour améliorer son programme.
Il y a aussi quelques trucs marrants dans le code généré suivant les options utilisées, il reste parfois des instructions inutiles et qui penvent donc être supprimées... à la main...
Et une fois que toutes les optimisations en C auront été faites, l'étape suivante sera de passer à l'assembleur avec aussi son lot de trucs et astuces divers et variés, et la traque de la moindre micro seconde perdue
Il y a aussi d'autres optimisations simples qui sont possibles avant de s'attaquer aux librairies du compilateur ou de passer à l'assembleur.
Par exemple utiliser des variables de type unsigned char à la place de variables de type int quand c'est possible, ce qui est le cas ici pour x et y.
Ou encore remplacer:
- Code:
int rowCount = 24;
int colCount = 40;
- Code:
#define rowCount 24
#define colCount 40
En cumulant uniquement ces 2 modifications, les affectations et les tests sont simplifiés et il y a moins d'appels à des sous routines, et comme ces opérations sont faites à chaque itération de boucle, la boucle devrait tourner plus rapidement.
Par exemple, l'instruction y++ donne successivement:
Aucune modification:
- Code:
;
; y++;
;
L000C: ldy #$05
jsr ldaxysp
sta regsave
stx regsave+1
jsr incax1
ldy #$04
jsr staxysp
lda regsave
ldx regsave+1
Utilisation de -Or:
- Code:
;
; y++;
;
L000C: ldy #$05
jsr ldaxysp
jsr incax1
L0017: ldy #$04
jsr staxysp
Utilisation de unsigned char y (plus d'instructions mais aucun appel de routines)
- Code:
;
; y++;
;
L000A: ldy #$00
ldx #$00
lda (sp),y
pha
clc
adc #$01
ldy #$00
sta (sp),y
pla
Le même avec l'option -Or:
- Code:
;
; y++;
;
L0014: lda (sp),y
clc
adc #$01
L0017: sta (sp),y
On arrive à des optimisations similaires pour les tests des boucles while
Par exemple, on passe de
- Code:
;
; while(y<rowCount)
;
L000E: ldy #$05
jsr ldaxysp
jsr pushax
ldy #$05
jsr ldaxysp
jsr tosltax
jne L000C
à
- Code:
;
; while(y<rowCount)
;
cmp #$18
bcc L0014
en cumulant l'utilisation de #define et de unsigned char et des options de compilation.
Après, il reste aussi les routines des libraries qui ne sont pas toujours optimisées pour la vitesse d'exécution ou la taille du code généré, mais en faisant ces quelques modification, les boucles devraient gagner un peu en rapidité.
Il est toujours intéressant devoir le code produit par le compilateur dans plusieurs cas de figures, ça permet de voir quelles corrections apporter pour améliorer son programme.
Il y a aussi quelques trucs marrants dans le code généré suivant les options utilisées, il reste parfois des instructions inutiles et qui penvent donc être supprimées... à la main...
Et une fois que toutes les optimisations en C auront été faites, l'étape suivante sera de passer à l'assembleur avec aussi son lot de trucs et astuces divers et variés, et la traque de la moindre micro seconde perdue
assinie- Messages : 271
Date d'inscription : 09/02/2014
Re: besoin d'un affichage printf plus rapide
Apparemment mon message a été incompris...
Afficher du decimal ca demande de faire des division et modulos par dix, alors que l'hexa c'est juste masquer 4 bit et utiliser une table d'affichage 0123456789ABCDEF pour afficher directos le nibble.
sprintf n'affiche rien: Ca écrit dans un buffer, donc ca n'appelle pas la ROM pour faire quoi que ce soit.
Après, si au lieu de mettre un buffer on met une adresse écran, ca afficher sur l'écran, sans passer par la ROM.
Concernant Gotoxy, je vous invite a regarder le code plutôt qu'imaginer ce que le code fait: Tout le code source est dans OSDK/Lib:
Le but de l'hexa vis a vis du decimal c'est la performance, et pas seulement "un chiffre de moins a afficher". C'est aux moins 10 fois plus rapide.laurentd75 a écrit:PS - quoi qu'il en soit, je rejoins DBug sur le fait que si ton programme est destiné à être un outil de dev, il est sans doute préférable d'afficher les valeurs en hexa plutôt qu'en décimal, ça ira plus vite (un chiffre de moins à afficher en général), ce sera aligné, et généralement c'est plus intéressant d'avoir la valeur en hexa qu'en décimal...
Afficher du decimal ca demande de faire des division et modulos par dix, alors que l'hexa c'est juste masquer 4 bit et utiliser une table d'affichage 0123456789ABCDEF pour afficher directos le nibble.
laurentd75 a écrit:En revanche, à part économiser un appel de fonction et l'overhead associé, je ne vois pas trop le gain d'utiliser sprintf() par rapport à printf()... Je pense (j'espère même) que gotoxy() est optimisée et ne fait pas appel à une routine lente de la ROM...
sprintf n'affiche rien: Ca écrit dans un buffer, donc ca n'appelle pas la ROM pour faire quoi que ce soit.
Après, si au lieu de mettre un buffer on met une adresse écran, ca afficher sur l'écran, sans passer par la ROM.
Concernant Gotoxy, je vous invite a regarder le code plutôt qu'imaginer ce que le code fait: Tout le code source est dans OSDK/Lib:
- Code:
; Do not print on the first screen columns. Screen attributes will be destroyed
_gotoxy
ldy #$0 ; Grab first 8-bit parameter
lda (sp),y
sta tmp ; Store column number (0-based)
iny
iny
lda (sp),y ; Grab second 8-bit parameter
sta tmp+1 ; Move it to the X register
lda $026a ; Disable the cursor
pha
and #$fe
sta $026a
lda #$00
jsr $f801
lda tmp ; Reload column number
sta $0269 ; Store it where the OS can find it
lda tmp+1 ; Now play with the row number
sta $0268 ; Store it for the OS's sake
jsr $da0c ; Calculate screen row address
lda $1f ; Update pointers
ldy $20
sta $12
sty $13
pla ; Restore state of cursor
sta $026a
lda #$01
jmp $f801
Le but est évidement pas de faire la multiplication, c'est un example: Si tu initializes ton pointeur a BB80 au début de ton écran, il te suffit de faire +=40 pour passer a la ligne suivante, ou de rajouter juste l'offset horizontal pour écrire plus loin sur la même ligne. Et quand tu fais ton sprintf y'a plus rien a calculer, tu passes juste ton pointeur comme étant l'adresse d'affichage.laurentd75 a écrit:Et je ne suis pas persuacdé que le compilo C optimise la multiplication par 40...
Dbug- Messages : 248
Date d'inscription : 06/01/2013
Re: besoin d'un affichage printf plus rapide
Salut,
Pour l'hexa tu as raison DBug bien sûr, je n'avais même pas réfléchi au fait que c'était + performant car aucun besoin de division ou de modulo pour afficher les valeurs, du coup c'est clair que "le chiffre en moins à afficher" devient anecdotique :-) !
A propos de modulo, je n'avais pas réfléchi non plus pour ma routine d'affichage que le modulo est une opération aussi complexe que la division pour un 6502, donc si on veut vraiment afficher du décimal 0..255 il faudrait reprendre ma routine et modifier les tests pour les dizaines pour retrancher systématiquement la valeur des dizaines, de façon à pouvoir juste afficher ensuite les unités qui restent plutôt que d'avoir à faire un modulo.
(ex: if(n > 89} { cputchar('9'); n -= 90; })
Pour gotoxy(), ne pouvant pas vérifier moi-même au moment de ma réponse comment était codée cette routine j'ai voulu précisément suggérer de regarder comment c'était codé pour vérifier si c'était efficace ou pas. Et je voulais donc dire que si gotoxy() était efficace, du coup le sprintf() n'avait pas d'intérêt par rapport au printf(), puisque printf() écrit lui directement dans la mémoire de l'écran, tout comme sprintf() si on lui donne en argument une adresse mémoire écran plutôt que l'adresse d'une chaîne...
Par ailleurs... Merci beaucoup assinie pour toutes ces infos sur les optimisations, c'est vraiment très intéressant et instructif (ça pourrait même faire un très bon article pour le Mag je trouve... ) . En tous cas ça me sera très utile je pense, et je creuserai le sujet car j'avoue ne m'être jamais intéressé encore aux options du compilateur...
Pour l'hexa tu as raison DBug bien sûr, je n'avais même pas réfléchi au fait que c'était + performant car aucun besoin de division ou de modulo pour afficher les valeurs, du coup c'est clair que "le chiffre en moins à afficher" devient anecdotique :-) !
A propos de modulo, je n'avais pas réfléchi non plus pour ma routine d'affichage que le modulo est une opération aussi complexe que la division pour un 6502, donc si on veut vraiment afficher du décimal 0..255 il faudrait reprendre ma routine et modifier les tests pour les dizaines pour retrancher systématiquement la valeur des dizaines, de façon à pouvoir juste afficher ensuite les unités qui restent plutôt que d'avoir à faire un modulo.
(ex: if(n > 89} { cputchar('9'); n -= 90; })
Pour gotoxy(), ne pouvant pas vérifier moi-même au moment de ma réponse comment était codée cette routine j'ai voulu précisément suggérer de regarder comment c'était codé pour vérifier si c'était efficace ou pas. Et je voulais donc dire que si gotoxy() était efficace, du coup le sprintf() n'avait pas d'intérêt par rapport au printf(), puisque printf() écrit lui directement dans la mémoire de l'écran, tout comme sprintf() si on lui donne en argument une adresse mémoire écran plutôt que l'adresse d'une chaîne...
Par ailleurs... Merci beaucoup assinie pour toutes ces infos sur les optimisations, c'est vraiment très intéressant et instructif (ça pourrait même faire un très bon article pour le Mag je trouve... ) . En tous cas ça me sera très utile je pense, et je creuserai le sujet car j'avoue ne m'être jamais intéressé encore aux options du compilateur...
Re: besoin d'un affichage printf plus rapide
dans l'OSDK, il y a un exemple "Advanced Print" qui permet d'afficher une chaîne à une position X,Y. Cette fonction s'appuie sur un tableau de pointeurs de lignes. Ce qui évite toute multiplication. Ca occupe quelques octets pour le tableau.
Mais sinon, une multiplication par 40, ça ne me parait pas sorcier :
X * 40 = X * 8 * (2 + 2 + 1)
R0 = X*8 : 3 décalages à gauche
R1 = R0*2
Puis additionner : R0+R1+R1.
L'opération ne prend que quelques octets en assembleur et aucun appel de routine.
Mais c'est plus long que le tableau de pointeurs.
Mais sinon, une multiplication par 40, ça ne me parait pas sorcier :
X * 40 = X * 8 * (2 + 2 + 1)
R0 = X*8 : 3 décalages à gauche
R1 = R0*2
Puis additionner : R0+R1+R1.
L'opération ne prend que quelques octets en assembleur et aucun appel de routine.
Mais c'est plus long que le tableau de pointeurs.
drpsy- Messages : 208
Date d'inscription : 20/07/2014
Age : 52
Localisation : Lagny sur Marne
Re: besoin d'un affichage printf plus rapide
Oui, DrPsy, effectivement, le mieux est de passer par un tableau avec les adresses de début de chaque ligne...
Sinon, la multiplication par 40, oui ça peut se faire par décalages et additions, mais seulement pour X <= 6, sinon après ça se complique un peu
Sinon, la multiplication par 40, oui ça peut se faire par décalages et additions, mais seulement pour X <= 6, sinon après ça se complique un peu
Dernière édition par laurentd75 le Sam 8 Déc 2018 - 13:04, édité 1 fois
Re: besoin d'un affichage printf plus rapide
Ma multiplication par 40 sur 2 octets avec la transformation de x,y en adresse écran. Ca ne doit pas être optimal encore... Le résultat est dans la variable tmp0. Et bon, ce serait plutôt à mettre dans le forum ASSEMBLEUR !
- Code:
clc
lda #0
sta tmp1+1
lda _y ;;; la position y
sta tmp1 ;;; *8
asl tmp1
rol tmp1+1
asl tmp1
rol tmp1+1
asl tmp1
rol tmp1+1
lda tmp1 ;;; sauve
sta tmp3
lda tmp1+1
sta tmp3+1
asl tmp1 ;;; *4
rol tmp1+1
asl tmp1
rol tmp1+1
lda tmp1 ;;; addition de (8*x) et de 4*(8*x)
clc
adc tmp3
sta tmp3
lda tmp1+1
adc tmp3+1
sta tmp3+1
;;; fin de la multiplication par 40
clc ;;; +x
lda _x ;;;
adc tmp3
sta tmp0
lda tmp3+1
adc #0
sta tmp0+1
clc ;;; +addr debut ecran hires A000
lda #0 ;;; octet de poids faible. #$80 pour texte
adc tmp0
sta tmp0
lda #$A0 ;;; octet de poids fort. #$BB pour texte
adc tmp0+1
sta tmp0+1
drpsy- Messages : 208
Date d'inscription : 20/07/2014
Age : 52
Localisation : Lagny sur Marne
Re: besoin d'un affichage printf plus rapide
J'ai fait une fonction en assembleur appelable en C (OSDK) pour afficher un caractère en Hires :
Ca m'a permis d'écrire du texte en hires avec un jeu de caractères spécial (d'où le 21...) sur 2 octets de large.
- Code:
extern unsigned char PGS_putc(unsigned char x, unsigned char y, unsigned char c);
PGS_putc( 5 , 50 , 21 );
Ca m'a permis d'écrire du texte en hires avec un jeu de caractères spécial (d'où le 21...) sur 2 octets de large.
drpsy- Messages : 208
Date d'inscription : 20/07/2014
Age : 52
Localisation : Lagny sur Marne
Re: besoin d'un affichage printf plus rapide
Merci DrPsy pour ta routine de multiplication en asm, c'est là qu'on voit que c'est quand même assez vite très fastidieux le 6502, et encore, là c'est un cas particulier et assez "simple"... J'avoue que quand je suis passé au 68000 sur Atari ST en sortant de l'Oric à l'époque, je n'ai pas trop regretté le 6502 !!
A part ça, on dirait que tu es en train de nous préparer un jeu sympa dis-donc...
A part ça, on dirait que tu es en train de nous préparer un jeu sympa dis-donc...
Re: besoin d'un affichage printf plus rapide
A noter que la routine qui fait la multiplication par 40 et ajoute l'adresse écran. occupe 76 octets, donc pour le mode TEXT, le gain de place est minimal et la performance dramatiquement pire.
En mode HIRES, ca se défend, mais uniquement si on est limite en mémoire
Un avantage supplémentaire de la table, c'est la possibilité de gérer les dépassements de facon invisible en ayant de 200 a 255 les valeurs qui pointent vers un buffer "poubelle", ca simplifie le clipping
En mode HIRES, ca se défend, mais uniquement si on est limite en mémoire
Un avantage supplémentaire de la table, c'est la possibilité de gérer les dépassements de facon invisible en ayant de 200 a 255 les valeurs qui pointent vers un buffer "poubelle", ca simplifie le clipping
Dbug- Messages : 248
Date d'inscription : 06/01/2013
Re: besoin d'un affichage printf plus rapide
laurentd75 a écrit:Salut,
Par ailleurs... Merci beaucoup assinie pour toutes ces infos sur les optimisations, c'est vraiment très intéressant et instructif (ça pourrait même faire un très bon article pour le Mag je trouve... ) . En tous cas ça me sera très utile je pense, et je creuserai le sujet car j'avoue ne m'être jamais intéressé encore aux options du compilateur...
Le plus simple au niveau des optims, c'est tout de même de passer les déclarations en unsigned char quand on sait qu'on ne dépassera pas 255.
Je pense qu'Assinie aime bien regarder le code source généré par cc65, donc, il est assez bien placé pour expliquer comment coder tel truc avec cc65. De mon coté, j'ai plutôt tendance à passer directement en asm certaines fonctions, quand je sais ou quand je vois que ça rame.
De mon coté, je connais plus (+) les libs cc65, donc je sais que les appels que je fais peuvent être plus ou moins long. C'est souvent le cas avec cc65 : les fonctions peuvent être assez lourdes car c'est un compilo générique qui cible toutes (bcp) les targets 6502. Par exemple, il n'y a pas de proto simple pour afficher une string, j'ai donc des extern de fonctions pour appeler directement des routines plus rapides à l'affichage.
Les libs conio et tgi de CC65 sont lentes car elles ne sont pas adaptées aux machines (on passe parfois par plusieurs variables avant d'appeler une routine), les proto ne sont pas adaptés. Mais comme évoqué plus haut, cela permet de prototyper rapidement des trucs avant de remplacer les appels par des trucs plus rapides.
Il serait possible de faire une lib "TGI" dédiée à l'atmos qui serait beaucoup plus rapide par exemple.
Jede- Messages : 308
Date d'inscription : 20/04/2016
Localisation : Var
Re: besoin d'un affichage printf plus rapide
@Laurent : l'idée d'un nouveau jeu vient de ma fille, elle a des talents indéniables de scénariste. Le dessin de la police est de mon fils. LOL.
@Dbug : oui ok. je préfère aussi la table. C'était juste pour l'exercice de style. Mais par rapport à la proc gotoxy, j'avoue que je n'aime pas trop les appels aux routines en ROM du BASIC.
@Dbug : oui ok. je préfère aussi la table. C'était juste pour l'exercice de style. Mais par rapport à la proc gotoxy, j'avoue que je n'aime pas trop les appels aux routines en ROM du BASIC.
drpsy- Messages : 208
Date d'inscription : 20/07/2014
Age : 52
Localisation : Lagny sur Marne
Forum Oric :: Forums :: Forum Public :: Programmation en C
Page 1 sur 1
Permission de ce forum:
Vous ne pouvez pas répondre aux sujets dans ce forum
|
|
Dim 31 Mar 2024 - 14:35 par kenneth
» Bla Bla général du Jury
Jeu 21 Mar 2024 - 8:51 par Dom50
» carte mère Oric (re)tracée
Mar 5 Mar 2024 - 18:54 par kenneth
» Meurtre à Grande Vitesse
Dim 25 Fév 2024 - 5:09 par Iurius
» ORIC-1 sur LE BON COIN
Ven 23 Fév 2024 - 23:01 par Mcar
» ORIC ATMOS sur LE BON COIN
Dim 4 Fév 2024 - 12:06 par kiwilevrai
» Problème d'affichage des couleurs avec un Oric Atmos
Sam 27 Jan 2024 - 1:26 par pierbail
» Bienvenue dans le Forum des Oriciens
Mar 9 Jan 2024 - 12:33 par Dom50
» Rencontre avec Laurant Weill, co-fondateur de Loriciel, et mon garçon de 12 ans
Ven 29 Déc 2023 - 14:13 par Arcade-des-Monts
» Bonnes fêtes
Mar 26 Déc 2023 - 10:21 par Dom50
» Murders in Venice / Meutres à Venise
Sam 18 Nov 2023 - 22:44 par retroric
» Un clavier PS/2 pour tester un ORIC
Dim 27 Aoû 2023 - 9:49 par Voyageur
» Disquette 3" Sedoric
Mar 1 Aoû 2023 - 14:22 par AtomeX
» faire un 6502 avec des phototransistor
Dim 16 Juil 2023 - 17:26 par Voyageur
» Oricutron linux et DSK
Jeu 29 Juin 2023 - 18:34 par Voyageur