web-dev-qa-db-fra.com

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

Je suis très nouveau en C, c'est mon deuxième langage de programmation de haut niveau après Java. J'ai maîtrisé la plupart des bases, mais pour une raison quelconque, je ne peux pas écrire un seul caractère dans la mémoire de l'écran.

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

Pour un système d'exploitation, j'exécute PC-DOS 2000 avec une page de codes ISO chargée. Je cours en mode texte standard à 80 colonnes de style MDA/CGA/EGA/VGA avec couleur.

Voici le programme tel que je l'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 nouveau sur C, donc je m'excuse si mon erreur semble évidente, je n'ai pas pu trouver une source solide sur la façon de faire cela que je pouvais comprendre.

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

J'ai pris en compte la possibilité que l'écran puisse défiler, et donc retirer immédiatement mon personnage lors de l'exécution de deux manières. Pour résoudre ce problème, j'ai essayé:

  • Écrire à plusieurs reprises cette valeur à l'aide d'une boucle
  • Écrivez-le un peu plus bas.

Je peux lire et imprimer la valeur que j'ai écrite dans la mémoire, donc c'est évidemment toujours quelque part en mémoire, mais pour une raison quelconque, je ne reçois rien à l'écran. Je fais évidemment quelque chose de mal, mais je ne sais pas quel pourrait être le problème. Si d'autres détails sont nécessaires, veuillez demander. Merci pour toute aide que vous pourriez apporter.

43
Ampera

En mode réel pour adresser le premier 1 Mo de mémoire plein, un mécanisme appelé segment de 20 bits: décalage est utilisé. 0xb8000 est une adresse de mémoire physique. Vous devez utiliser quelque chose appelé un pointeur far qui vous permet d'adresser la mémoire avec une segmentation en mode réel. Les différents types de pointeurs sont décrits dans ce Stackoverflow Answer

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 * 16 + décalage. 0xb800 * 16 + 0x0000 = 0xb8000. Dans cet esprit, vous pouvez inclure dos.h et utilisez le MK_FP [~ # ~] c [~ # ~] macro pour initialiser un pointeur far vers une telle adresse en fonction du segment et du décalage.

De la documentation MK_FP est défini comme:

MK_FP () Faire un pointeur éloigné

#include   <dos.h>

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

MK_FP () est une macro qui fait un pointeur éloigné de son segment de composant "seg" et décale "off" les pièces.

Renvoie: un pointeur éloigné.

Votre code pourrait ê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;
}
55
Michael Petch

L'adresse du segment 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 contenir l'adresse de segmentation et de décalage, sinon 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 pointeurs proches, lointains et énormes?

4
stacker

Comme l'a souligné @stacker, dans l'environnement 16 bits, vous devez attribuer le pointeur avec soin. AFAIK vous devez mettre le mot-clé FAR (mon Dieu, quelle nostalgie).

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

2
valdo