45 votes

Impossible d'écrire dans la mémoire d'écran en C

Je suis très novice en C, c'est mon deuxième de haut niveau langage de programmation après Java. J'ai obtenu la plupart des bases, mais pour quelque raison que ce soit, je suis incapable d'écrire un seul caractère à la mémoire d'écran.

Ce programme est compilé à l'aide de Turbo C pour DOS sur un Am486-DX4-100 fonctionnant à 120 mhz. La carte graphique est une très standard VLB Diamond Multimedia Stealth SE à l'aide d'un Trio32 puce.

Pour l'OS je suis sous PC-DOS 2000 avec un ISO de page de codes chargé. Je suis en cours d'exécution dans la norme de la MDA/CGA/EGA/VGA style 80 colonnes en mode texte avec la couleur.

Voici le programme que j'ai écrit:

#include <stdio.h>

int main(void) {
    unsigned short int *Video = (unsigned short int *)0xB8000;
    *Video = 0x0402;
    getchar();
    return 0;
}

Comme je l'ai dit, je suis très novice en C, donc je m'excuse si mon erreur semble évident, j'ai été incapable de trouver une bonne source sur la façon de faire ce que je pouvais comprendre.

À ma connaissance, en mode réel sur la plate-forme x86, le souvenir-écran en mode texte commence à 0xB8000. Chaque caractère est stocké dans deux octets, un pour le personnage, et un pour l'arrière-plan/premier plan. L'idée est d'écrire la valeur 0x0402 (qui doit être d'un rouge visage souriant) 0xB8000. Cela devrait le mettre en haut à gauche de l'écran.

J'ai pris en compte la possibilité que l'écran peut être défilement, et donc de supprimer immédiatement mon personnage lors de l'exécution de deux façons. Pour résoudre ce problème, j'ai essayé:

  • À plusieurs reprises d'écrire cette valeur à l'aide d'une boucle
  • L'écrire un peu plus bas.

Je peux lire et imprimer la valeur que j'ai écrit de mémoire, donc il est évidemment toujours quelque part dans la mémoire, mais pour une raison que je ne pas obtenir quoi que ce soit à l'écran. Je suis évidemment faire quelque chose de mal, mais je ne sais pas ce qui pourrait être la question. Si d'autres détails sont nécessaires, veuillez le demander. Merci pour toute aide que vous pouvez donner.

56voto

Michael Petch Points 24066

En mode réel pour de l'adresse de la première 1MiB de la mémoire d'un mécanisme appelé 20 bits segment:offset adressage est utilisé. 0xb8000 est une adresse de mémoire physique. Vous avez besoin d'utiliser quelque chose qui s'appelle un far pointeur qui vous permet d'adresse de la mémoire avec le mode réel de la segmentation. Les différents types de pointeurs sont décrites dans ce Stackoverflow Répondre

0xb8000 peut être représenté comme un segment de 0xb800 et un décalage de 0x0000. Le calcul pour obtenir l'adresse physique est le segment de*16+offset. 0xb800*16+0x0000=0xb8000. Avec cela à l'esprit, vous pouvez inclure d' dos.h et l'utilisation de l' MK_FP C macro pour initialiser un far pointeur vers une adresse de segment et le décalage.

À partir de la documentation MK_FP est défini comme:

MK_FP() Faire un Pointeur Loin

#include   <dos.h>

void       far *MK_FP(seg,off);
unsigned   seg;                         Segment
unsigned   off;                         Offset

MK_FP() est une macro qui rend un pointeur loin de son élément de segment seg' et de compenser les " off " de pièces.

Retourne: Un pointeur loin.

Votre code peut être écrit comme ceci:

#include <stdio.h>
#include <dos.h>
int main(void) {
    unsigned short int far *Video = (unsigned short int far *)MK_FP(0xB800,0x0000);
    *Video = 0x0402;
    getchar();
    return 0;
}

5voto

stacker Points 34209

L'adresse du segment de mémoire dépend du mode vidéo utilisé:

 0xA0000 for EGA/VGA graphics modes (64 KB)
0xB0000 for monochrome text mode (32 KB)
0xB8000 for color text mode and CGA-compatible graphics modes (32 KB)
 

Pour accéder directement à vram, vous avez besoin d'un pointeur 32 bits pour conserver l'adresse de décalage et de décalage, sans quoi vous gâcheriez votre tas. Cela conduit généralement à un comportement indéfini.

 char far *Video = (char far *)0xb8000000;
 

Voir aussi: Quels sont les indicateurs proches, lointains et énormes?

2voto

valdo Points 7322

Comme @stacker l'a souligné, dans l'environnement 16 bits, vous devez attribuer le pointeur avec précaution. Autant que je sache, vous devez mettre FAR mot clé (mon Dieu, quelle nostalgie).

Assurez-vous également de ne pas compiler dans le modèle de mémoire dit "énorme". C'est incompatible avec l'adressage distant, car chaque pointeur 32 bits est automatiquement "normalisé" à 20 bits. Essayez de sélectionner "Grand" modèle de mémoire.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X