IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Assembleur Discussion :

Mode d'affichage graphique 13h ?


Sujet :

Assembleur

  1. #1
    Candidat au Club
    Inscrit en
    Février 2005
    Messages
    12
    Détails du profil
    Informations forums :
    Inscription : Février 2005
    Messages : 12
    Points : 2
    Points
    2
    Par défaut Mode d'affichage graphique 13h ?
    Bonjour,

    Je suis un débutant en ASM PC, j'ai programmé il y a 15 ans en ASM sur Z80, c'était déjè bien sympas. Je me remet à l'ASM sur PC ... voilà ma question :

    le mode graphique 13h (320x200x256 colors) semble être LE mode graphique. Y a-t-il un moyen d'afficher plus de 256 couleurs à la fois sur l'écran, oubien afficher 256 couleurs dans une résolution plus élevée ?

    J'ai l'impresion que non, mais si tel est le cas, alors comment sont fait les jeux vidéos (relativement) recents, genre METAL SLUG, etc ?

    Même question pour les jeux 3D recents dont l'affichage me semble être dans une résolution bien plus élevée que 320x200 ?

    La question peut paraître stupide pour quelqu'un d'expérimenté, mais il y a un commencement à tout !

    Xavier

  2. #2
    Responsable Pascal, Lazarus et Assembleur


    Avatar de Alcatîz
    Homme Profil pro
    Ressources humaines
    Inscrit en
    Mars 2003
    Messages
    7 940
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 57
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ressources humaines
    Secteur : Service public

    Informations forums :
    Inscription : Mars 2003
    Messages : 7 940
    Points : 59 409
    Points
    59 409
    Billets dans le blog
    2
    Par défaut
    Bonjour et bienvenue !

    Tu peux déjà trouver de bonnes pistes de réponses en faisant une recherche avancée sur le forum avec le mot-clé VESA.
    Dans la foulée, il est très probable également que tu doives te documenter sur le mode protégé.
    Règles du forum
    Cours et tutoriels Pascal, Delphi, Lazarus et Assembleur
    Avant de poser une question, consultez les FAQ Pascal, Delphi, Lazarus et Assembleur
    Mes tutoriels et sources Pascal

    Le problème en ce bas monde est que les imbéciles sont sûrs d'eux et fiers comme des coqs de basse cour, alors que les gens intelligents sont emplis de doute. [Bertrand Russell]
    La tolérance atteindra un tel niveau que les personnes intelligentes seront interdites de toute réflexion afin de ne pas offenser les imbéciles. [Fiodor Mikhaïlovitch Dostoïevski]

  3. #3
    Membre habitué Avatar de Nico*3-3
    Inscrit en
    Octobre 2004
    Messages
    164
    Détails du profil
    Informations forums :
    Inscription : Octobre 2004
    Messages : 164
    Points : 145
    Points
    145
    Par défaut
    Bonjour !

    Effectivement c'est le standard VESA (Video Electronics Standard Association) qui permet des résolutions beaucoup plus élevées jusqu'en 32 bits pour les couleurs (24 en fait, et 8 qui ne servent à rien)...

    On appelle les fonctions de la carte VESA par l'intermédiaire de la fonction 4Fh de l'Int 10h, avec al pour le numéro de la sous-fonction.
    En VESA, la mémoire vidéo prend donc presque toujours plus de 64 Ko, il y a donc un système de fenêtres très logiques (qui n'a rien à voir avec les fenêtres Windows) pour pouvoir tout adresser...

    Mais tout cela est expliqué dans de très bons tutoriels :

    - http://www-evasion.imag.fr/Membres/A...s/vesa.fr.html Très bien expliqué...
    - http://www.chez.com/pageasm/docs/dos/vesa.htm Il y a aussi de trucs sur le mode protégé...

    Cela fait une très bonne base pour débuter là-dedans !

    Salut !
    Tout a une fin, sauf l'infini...
    Projet SKAN : Développement commun d'OS

    Nico*3-3

  4. #4
    Candidat au Club
    Inscrit en
    Février 2005
    Messages
    12
    Détails du profil
    Informations forums :
    Inscription : Février 2005
    Messages : 12
    Points : 2
    Points
    2
    Par défaut Merci !
    Bonjour,


    Merci à vous 2 pour m'avoir éclairer, je vais de ce pas étudier la question.

    A très bientôt.

    Xavier


  5. #5
    Candidat au Club
    Inscrit en
    Février 2005
    Messages
    12
    Détails du profil
    Informations forums :
    Inscription : Février 2005
    Messages : 12
    Points : 2
    Points
    2
    Par défaut
    Bon, les liens que vous m'avez fournis sont supers, j'ai un petit problem de base d'assembleur pour récupérer les fonctions VESA supportées par ma carte graphique. La doc dit de faire ce quit suit :

    Entrée :
    AH = 4Fh
    AL = 00h
    ESI = Pointeur FAR sur le buffer Info
    Sortie : AX = status
    INT 10h

    • BUFFER INFOS :
      Offset Type Contenu
      00h DB "VESA" Signature VESA
      03h DB ? Version VESA, Numéro de version principal
      04h DB ? Version VESA, Numéro de version secondaire
      05h DD ? Pointeur FAR sur chaîne ASCII contenant le nom du fabricant
      09h DD ? Performances de l'environnement vidéo
      0Dh DD ? Pointeur FAR sur liste contenant les numéros des modes vidéo reconnus
      11h DW ? Nombre de chunks de 64 Ko
      13h DB 236 DUP (?) Reste du buffer


    Pour récupérer ces infos, mon code est le suivant (sur MASM 6.15) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
     
    PBYTE TYPEDEF PTR BYTE
     
    .data
    	msgOK BYTE "Le vesa est present",13,10,0
    	msgBlem BYTE "Le vesa n'est present",13,10,0
    	buffer BYTE 256 dup(?)
    	ptr1 PBYTE buffer
    .code
     
    main PROC
    	mov ax,@data
    	mov ds,ax
     
    	call Set_Video_Mode	;Affiche le mode graphique
     
    	;RECUPERE LES INFOS VESA
    	mov ax,OFFSET ptr1
    	mov es,ax
    	mov di,0
    	mov ah,4Fh
    	mov al,0
    	int 10h
    	cmp ax, 004fh
    	je VESA_PRESENT
     
    	mov dx,OFFSET msgBlem
    	call WriteString  ; Affiche la chaine commencant à l'adresse [dx]
    	exit
    VESA_PRESENT:
    	;AFFICHE QUE VESA EST PRESENT
    	mov dx,OFFSET msgOK
    	call WriteString
     
    	;TENTATIVE DE RECUPERATION DE LA SIGNATURE VESA
    	mov dx,OFFSET ptr1
    	call WriteString ;   ->  RIEN N'E S'AFFICHE	
     
    	;TENTATIVE DE RECUPERATION DU FABRICANT
    	mov dx,OFFSET ptr1
    	add dx,5
    	call WriteString ;  ->  RIEN N'E S'AFFICHE
     
    	exit
    main ENDP
    Est-ce que quelqu'un d'expérimenté peut me dire quelle est l'erreur dans ce code et les correction à apporter ? Je supose qu'il s'agit d'une erreur de définition du pointeur FAR ...

    Merci d'avance pour de l'aide.


  6. #6
    Membre éclairé
    Profil pro
    Inscrit en
    Juillet 2002
    Messages
    842
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2002
    Messages : 842
    Points : 696
    Points
    696
    Par défaut
    Peut être une erreur d'interprétation, mais je ne vois pas l'interet d'un pointeur sur le "buffer". En effet, si le "buffer" est donné en entrée, ca veut dire que vous devez fournir le buffer, et donc, directement, pas besoin de repasser par un pointeur intermédiaire.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    mov ax,OFFSET ptr1 
    mov es,ax
    Un offset dans es ?? C'est tout à fait incohérent. ^^

    • es doit contenir le segment
    • di doit contenir l'offset


    si vous n'êtes pas tout à fait familier avec ces notions, la FAQ assembleur vous aidera. Il faut que es:di pointe vers votre buffer :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    mov ax, @data
    mov es, ax
    mov di, offset Buffer
    es contient bien le segment, puisque votre buffer est déclaré dans le segment "data", et di contient bien l'offset de "Buffer".

    Pour ce qui est du sens de pointeur far, c'est juste segment:offset. La donnée des deuxest un pointeur far.

  7. #7
    Candidat au Club
    Inscrit en
    Février 2005
    Messages
    12
    Détails du profil
    Informations forums :
    Inscription : Février 2005
    Messages : 12
    Points : 2
    Points
    2
    Par défaut
    Merci pour votre réponse, ça fonctionne parfaitement en procédant simplement comme décrit dans votre réponse.

    J'avoue que la notion de segment n'est pas très claire pour moi, je vais donc faire un petit tour du côté de la FAQ.

    Merci encore.

    Xavier


  8. #8
    Candidat au Club
    Inscrit en
    Février 2005
    Messages
    12
    Détails du profil
    Informations forums :
    Inscription : Février 2005
    Messages : 12
    Points : 2
    Points
    2
    Par défaut
    Bon ... Je bute péniblement sur un autre point : Voici mon code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
     
    INCLUDE Irvine16.inc
     
    .data
    	msgNBChuncks BYTE "Nombre de Chunks disponibles : ",0
    	msgBUFCONSTR BYTE "Pointeur vers le Nom du constructeur : ",0
    	msgBUFMODE BYTE "Pointeur sur la liste des modes disponibles : ",0
    	msgOK BYTE "Le vesa est present !",13,10,0
    	msgSPACE BYTE " - ",0
    	msgBlem BYTE "Le vesa n'est present ... HHHAARRRRGGG !",13,10,0
    	buffer BYTE 256 dup(?)
    .code
     
    main PROC
    	mov ax,@data
    	mov ds,ax
    	mov es,ax
    	mov di,OFFSET buffer
     
    	;TEST SI LE MODE VESA EST SUPORTE
    	mov ah,4Fh
    	mov al,0
    	int 10h
    	cmp ax, 004fh
    	je VESA_PRESENT
     
    	mov dx,OFFSET msgBlem
    	call WriteString
    	exit
    VESA_PRESENT:
     
    	;AFFICHE QUE VESA EST PRESENT
    	mov dx,OFFSET msgOK
    	call WriteString
     
    	;AFFICHE L'ENTETE VESA
    	mov dx,OFFSET buffer
    	call WriteString
    	call CrLf	
     
    	; AFFICHE LE NOMBRE DE CHUNCKS DE 64 Ko
    	mov dx,OFFSET msgNBChuncks
    	call WriteString
    	mov bx,OFFSET buffer+11h
    	mov eax,[bx]
    	call writeInt
    	call CrLf
     
    	;AFFICHE LE POINTEUR VERS LA LISTE DES MODES DISPO
    	mov dx,OFFSET msgBUFMODE
    	call WriteString
    	mov bx,OFFSET buffer+0Dh
    	mov ax,[bx]
    	call writeHex
    	call CrLf
    	exit
     
    main ENDP
    END main
    Dans ce buffer, à l'offset 0Dh est stocké un Pointeur Far vers la liste des Modes disponibles : Je n'arrive pas à comprendre comment récupérer la liste de ces modes :

    Dans un premier temps, si je comprends correctement, j'obtient à l'offset 0Dh du buffer l'adresse du segment vers lequel la liste des modes dispo est contenu :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    mov bx,OFFSET buffer+0Dh
    mov ax,[bx]
    AX contient-il le segment ou l'Offset dans le segment actuel C'est très confus pour moi, malgré ma lecture de la FAQ.

    Dans un 2ème temps, comment puis-je récupérer dans un registre la permier mode disponible par exemple (Les autres seront facile à récupérer !)

    Merci d'avance.

  9. #9
    Membre éclairé
    Profil pro
    Inscrit en
    Juillet 2002
    Messages
    842
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2002
    Messages : 842
    Points : 696
    Points
    696
    Par défaut
    Bonsoir,

    Je vais tenter de rappeller très brièvement ce que sont l'offset et le segment. Pour accèder à une donnée en mémoire, il faut avoir le moyen de la "nommer".C'est à dire que si la mémoire contient un million d'octet, il faut dire auquel (auxquels) on veut accèder. Pour ca, on va pas s'embêter, on va les numéroter de 0 à 999 999. Pour acceder au dixième, il suffira de dire qu'on veut acceder au dixième ^^

    Seulement, on ne dispose que de registres 16 bits. C'est ennuyeux, puisqu'on ne peut donc donner que des valeurs de 0 à 65 536. Ce qui n'est pas beaucoup. Historiquement, et c'est malheureusement toujours le cas en mode réel (le mode dans lequel vous travaillez pour l'instant) vous ne pouvez acceder qu'a 1 Mo de Mémoire, c'est à dire que si l'on voulait donner un numéro à chaque octet, il nous faudrait 20 bits pour contenir le numéro du dernier octet.

    On ne va pas s'arrêter à ce problème. Pour pouvoir acceder à toute la mémoire, on va utiliser simplement deux registres. Comme ca, on aura deux fois plus de bits pour adresser la mémoire. Mais deux fois plus, ca fait 32, soit 4 Go de mémoire. On en a qu'un seul Mo, donc, on va faire un peu différement. On ne va pas faire :

    Registre 1 x 10000h + Registre 2

    qui couvrirait les valeurs de 0000 0000h - ffff ffffh

    Mais plutôt :

    Registre 1 x 10h + Registre 2

    qui va couvrir la plage 0 0000h - f ffffh soit nos 20 bits (4 bits par chiffre hexa si vous n'êtes pas encore familier avec ca).

    Par contre, on remarque directement, qu'il y a plusieures manières de "nommer" ou d'"adresser" un octet. Si on veut acceder à l'octet 112h par exemple on pourra choisir les combinaisons :

    11h x 10h + 2h
    10h x 10h + 12h
    9h x 10h + 22h
    8h x 10h + 32h
    etc.

    Mais le fait que les combinaisons ne sont pas uniques, ne nous gêne pas. On va pouvoir appeller désormais Registre 1, le registre "segment", et le registre 2 étant l'"offset". Ce qui nous donne la formule :

    Adresse = Segment x 10h + Offset

    Tout ça, normalement, ce ne sont que des rappels.

    En pratique, pour un programme ne contenant que du code, nous allons désigner un segment de code, avec un offset de départ. Seulement, le processeur est capable de modifier l'offset à chaque instruction (si une instruction fait deux octet, le pointeur d'instruction étant l'offset sur le code, se déplacera de +2), ou de faire des sauts à des offset différents (jmp label : saut à l'adresse de label, donc l'ofest prend la valeur de label) il n'est pas directement capable de changer de segment. Pour changer de segment, il faut utiliser des jmp far, qui sont longs à executer. En pratique donc, le segment de code change très rarement, il n'y a que l'offset qui varie. On a donc une sorte de de fenêtre définie par le segment, qui est ouverte sur une certaine partie de la mémoire :

    Ouverture de l'addresse Segment x 10h à l'adresse Segment x 10h + ffffh

    dans lequel l'offset se déplace pour choisir ce que l'on veut dans la fenêtre. Pour le code, et la pile, c'est le système identique. On a un fenêtre sur la pile, et une fenêtre sur les données. Chacune de ses fenêtre à un registre perso :

    cs -> Segment de code
    ss -> Segment de pile
    ds -> Segment de donnée
    es -> Segment bonus ^^

    Le dernier registre est à la diposition du programmeur. Il est impossible d'accèder à des données ou du code autrement qu'en utilisant ces registres segment.

    Remarque : Rien n'affire que si la fenêtre dont je parle à une ouverture de 1 000h octets, que tous ces octets appartiennent à votre programme. Seuls les premiers octets en réalité.

    Exemples :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    Variable dw 1234h
     
    ...
     
    mov ax, ds:[Variable] ; Met dans ax, la valeur contenue à l'adresse ds:variable.
    mov ax, [Variable] ; L'instruction est identique à la précédente
     
    mov di, offset Variable
    mov ax, [di] ; Même résultat, mais pas strictement identique
    mov ax, ds:[di] ; Identique à la ligne précédente
     
    mov ax, ds
    mov es, ax
    mov ax, es:[Variable] ; Même résultat encore ^^
     
    mov ax, ss:[0] ; Met dans ax, la dernière valeur de la pile
    Il faut expliquer quelques détails maintenant ^^

    • Quand on accède à des données, par

      mov ax, [Variable]

      le ds: est implicite ! Mais c'est comme s'il y était. Par défaut, vous accèdez toujours au segment désigné par ds (et c'est pour ca qu'il est capital de le définir au début de votre programme)
    • L'offset peut être définit de deux manières différentes, ce qu'on appelle l'adressage direct et l'adressage indirect :
      [list:9514ca9974]
    • Adressage direct : Vous donnez explicitement l'offst. Par exemple : mov ax, [Variable]. Variable désigne l'offset.
    • Adressage indirect : Vous donnez l'offset à calculer, en fonction de registres. Par exemple : mov ax, [di+bp]
    [/list:u:9514ca9974]

    Bon, ca ne répond pas encore à la question, on y arrive ^^

    Admettez que vous vouliez désigner à un autre programme qui ne connait pas vos segments, une adresse en mémoire. Vous devrez alors lui donner, le segment, et l'offset. Deux manières de faire :

    [list][*]Vous prenez comme convention que le segment que vous vouler désigner est dans un registre segment et que l'offset est dans un registre d'index ou de base. Par exemple, vous dites que l'adresse est contenue dans es:di[*]Vous stockez un pointeur far quelque part, afin de ne pas modifier vos registres segment. Vous devrez alors en mémoire mettre les deux valeurs :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    Segment dw 0123h
    Offset dw 1234h
     
    ...
     
    PointeurFar dd ?
     
    ...
     
    mov ax, [Segment]
    mov word ptr [PointeurFar + 2], ax
    mov ax, [Offset]
    mov word ptr [PointeurFar], ax
    Le pointeur far contient dans les 16 bits de poid fort le segment, et dans les 16 bits de poid faible, l'offset.

    Dans les interruptions que vous trouverez, ce sera soit l'une, soit l'autre méthode qui sera utilisée, que ce soit en entrée ou en sortie. Vous, pas de chance, vous avez les deux : Vous deviez fournir un pointeur far par la première méthode, et la fonction vous renvoie un pointeur far par la seconde ^^

    Reprenons votre proposition :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    mov bx,OFFSET buffer+0Dh 
    mov ax,[bx]
    Si vous avez bien compris ce que je vous ai dit, vous pouvez raccourcir un peu la ligne. Buffer est un offset explicite, vous pouvez donc mettre directement dans ax, l'offset. Mais, on va plutôt mettre l'offset dans si, pour pouvoir se servir de si comme index, et si je ne me trompe pas, on peut directement mettre le segment dans un registre segment :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    mov si, [Buffer + 0Dh]
    mov es, [Buffer + 0Dh + 2]
    Le registre es (extra segment) tombe à pic, puisqu'on va pouvoir l'utiliser comme segment, sans modifier ds.

    ax devrait contenir donc, le premier mode.

    Je pense que ca répond à votre question, mais je dois rajouter quelques trucs :

    • Je n'ai pas du tout vérifié le fonctionement de l'interruption, je vous fait donc confiance pour l'interprétation, je me suis juste contenté de dire comment. S'il y a une erreur dans l'interprétation de l'interruption, ca ne risque pas de marcher ^^
    • Je ne sais pas (plus) quel assembleur vous utilisez. Ce qui pose quelques problèmes. Il y a deux conventions d'écriture :

      mov ax, Variable = mov ax, [Variable]

      Pour MASM & TASM, qui utilisent cette syntaxe très proche des langages évolués, ce qui permet d'inclure très facilement l'assembleur dans le le C/C++/Delphi.

      L'autre convention est :

      mov ax, Variable = mov ax, offset Variable

      Qui permet d'éviter certaines confusions. En revanche

      mov ax, [offset Variable] = mov ax, [Variable]

      toujours puisque Variable entre crochet ne peux avoir d'autre sens (c'est dans ce cas, qu'on comprend la confusion possible avec la première forme de MASM & TASM)


    J'espère avoir répondu à votre question ^^

  10. #10
    Candidat au Club
    Inscrit en
    Février 2005
    Messages
    12
    Détails du profil
    Informations forums :
    Inscription : Février 2005
    Messages : 12
    Points : 2
    Points
    2
    Par défaut
    Bonsoir !

    Merci d'avoir pris le temps de donner une réponse aussi précise et détaillée. Cela me semble clair, mais ces notions ne sont que très fraiches pour moi, j'ai donc besoin d'un peu de temps pour bien comprendre et assimiler tout ce que contient votre post.

    Donc je reviens en ligne dans très peu de temps ... dès que cela est bien clair !

    PS : Juste votre annotation ^^, je ne la comprends pas ??? Aussi, j'utilise MASM 6.15.

    Merci encore et à très bientôt.

    Xavier


  11. #11
    Membre éclairé
    Profil pro
    Inscrit en
    Juillet 2002
    Messages
    842
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2002
    Messages : 842
    Points : 696
    Points
    696
    Par défaut
    L'anotation, c'est un smiley :p

  12. #12
    Membre habitué Avatar de Nico*3-3
    Inscrit en
    Octobre 2004
    Messages
    164
    Détails du profil
    Informations forums :
    Inscription : Octobre 2004
    Messages : 164
    Points : 145
    Points
    145
    Par défaut
    Bonsoir !

    Alors quelques précisions :

    -Blustuff : Petite rectification, on ne peut mettre dans un registre de segment qu'un registre général, il faut donc modifier ça :
    Par :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    mov  ax, #N° Segment
    mov  es, ax
    -Blustuff : 2ème petite rectification, les deux conventions :
    L'une (Tasm et Masm) :

    Mettra dans ax la valeur de Variable, et :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    mov  ax, offset Variable
    Mettra dans ax l'offset de Variable par rapport à ds

    L'autre (Fasm et Nasm) :

    Mettra dans ax l'offset de Variable par rapport à ds, et :
    Mettra dans ax la valeur de Variable.

    Je ne vois pas de confusion...


    - Ensuite, je vais tenter quelques précisions pour que la notion de segment soit plus claire...

    Avec un registre de segment à zéro, on peut adresser tout le segment "N° 0" donc : de 0 à 65535
    On pourrait donc penser que le deuxième segment ("N° 1") se trouve après le premier segment, donc 65536 à 131071

    Or non Car les segments peuvent se chevaucher et en réalité, si un registre de segment est égal à :
    - 0 : la base du segment est 0
    - 1 : la base du segment est 16
    - 2 : la base du segment est 32
    - 3 : la base du segment est 48
    ...

    Pour obtenir une adresse réelle (linéaire) il faut donc faire :

    (registre de segment * 16 (ou 10h)) + offset
    Par exemple : es=0A000h, di=00FAh
    [es:di] = (0A000h*16)+00FAh
    = 0A0000h+00FAh
    = 0A00FAh

    On ne peut donc adresser que : FFFF:FFFF
    (FFFF*16)+FFFF
    FFFF0+FFFF
    1 114 095 octets. C'est-à-dire un Méga-Octet

    Tout cela ne s'applique qu'au mode réel (en mode protégé, on peut adresser 4 Giga-Octets, mais tout est différent).

    J'espère avoir été plus clair...
    Sinon le tutoriel de Benoît-M explique très bien toutes ces notions...

    Si c'est encore flou pour toi n'hésite pas !

    Salut !
    Tout a une fin, sauf l'infini...
    Projet SKAN : Développement commun d'OS

    Nico*3-3

  13. #13
    Membre éclairé
    Profil pro
    Inscrit en
    Juillet 2002
    Messages
    842
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2002
    Messages : 842
    Points : 696
    Points
    696
    Par défaut
    Citation Envoyé par Nico*3-3
    on ne peut mettre dans un registre de segment qu'un registre général
    L'opération est au contraire tout à fait licite et correspond à l'instruction :

    8E /r MOV Sreg, r/m16

    Citation Envoyé par Nico*3-3
    Mettra dans ax l'offset de Variable par rapport à ds
    Rien n'oblige ds à coincider avec le segment. C'est par rapport au début du segment dans lequel il est déclaré quelqu'il soit. (Même segment de code)


    Citation Envoyé par Nico*3-3
    Je ne vois pas de confusion...
    La confusion est explicitée un peu en dessous. Pour MASM, on peut écrire invariablement :

    ou

    ce qui peut provoquer la confusion suivante : L'identificateur "Variable" correspond à son adresse ou à la valeur contenue à l'adresse ? La première ligne montre que Variable ici sera l'adresse, et la seconde qu'elle représentera la valeur.

    Cette confusion n'existe pas dans la syntaxe NASM, où l'identificateur représente dans tous les cas, l'adresse. (On a alors que le mot clé offset devient implicite)


    Blustuff.

  14. #14
    Membre habitué Avatar de Nico*3-3
    Inscrit en
    Octobre 2004
    Messages
    164
    Détails du profil
    Informations forums :
    Inscription : Octobre 2004
    Messages : 164
    Points : 145
    Points
    145
    Par défaut
    Il suffit alors dans MASM de ne jamais utiliser de crochets, seulement "Variable" ou "offset Variable"...

    Mais ce n'est pas mon assembleur et ce n'est pas non plus le sujet de ce thread...
    Tout a une fin, sauf l'infini...
    Projet SKAN : Développement commun d'OS

    Nico*3-3

  15. #15
    Membre éclairé
    Profil pro
    Inscrit en
    Juillet 2002
    Messages
    842
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2002
    Messages : 842
    Points : 696
    Points
    696
    Par défaut
    Ne sachant pas quel assembleur est utilisé, il est capital que l'auteur de la question sache comment interpreter les exemples qui lui sont donnés.

  16. #16
    Candidat au Club
    Inscrit en
    Février 2005
    Messages
    12
    Détails du profil
    Informations forums :
    Inscription : Février 2005
    Messages : 12
    Points : 2
    Points
    2
    Par défaut
    Bonjour,

    J'ai étudié le post de Blustuf qui est très clair et limpide. HHHHAAAARRRGGG, il ne faut pas bacler la lecture des premières pages des bouquins qui contiennent la base !

    Je pense avoir clairement compris, et malgré tout, je n'arrive pas à récupérer les données transmises dans le Pointeur Far, lui même transmis à mon buffer. En tout cas, elles ne correspondent pas à des modes connues de la doc (si mon code est correct ).

    Au risque de paraître "lourdeau" et difficile à la détente :pingoin: , je me permet donc une petite récapitulation pour m'assurer de l'exactitude de ma compréhension.

    Voici mon code avec MASM 6.15 :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
     
     
    	; RECUPERATION DES INFO DES MODES VESA SUPPORTES
     
    .data
     	buffer BYTE 256 dup(?) 	; taille requise par l'interruption
    .code
     	mov AX,@data    	; pointe le registre DS vers mes donnés.
     	mov DS,AX
     	mov ES,AX		    ; L'interruption requière que ES:DI pointe sur le buffer
     	            		; qui recevra les données, soit buffer
     	mov DI,OFFSET buffer
     
     	;APPELLE DE LA FONCTION
     	mov ah,4Fh
    	mov al,0
    	int 10h				; Pour simplifier la compréhension du code, j'enlève le test de présence du mode VESA
    Désormais, buffer contient les infos VESA, j'en ai la certitude puisque je récupère les toutes les infos autres que les pointeur FAR.

    l'Interruption place, par exemple, à un OFFSET de 05h un pointeur far sur 32 bits vers le nom du constructeur de la carte.
    A titre d'exercice, pour récupérer ce nom, j'ai le code suivant ;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    	mov BX, OFFSET buffer+05h+2
    	mov AX,[BX]					; Ces 2 lignes équivalent à mov AX,[buffer+05h+2],
    	           					; mais MASM ne semble pas l'accepter !
    	mov ES,AX					  ; ES <-- SEGMENT du pointeur far
    	mov BX,OFFSET buffer+05h	; SI <-- OFFSET du pointeur far
    	mov SI,[BX]
    	mov AH,ES:[SI]
    AH Devrait donc contenir le premier caractère du nom du constructeur, es:[SI+1] le second et ainsi de suite.

    Ai-je raison ?

    Par ailleurs, quand j'affiche SEGMENT:OFFSET ça ressemble à 00F8h:0C800h. Bien que je ne connaissent pas à l'avance les valeurs du segment et de l'offset correspondant au pointeur FAR, j'ai quand même l'impression que 0C800h est plutôt le segment et F8h l'OFFSET, est-ce correct ? Si tel est le cas, l'OFFSET est stocker dans les 16 bits de poids fort et non pas faible : : : C'est une question et pas une affirmation !

    Mais dans les 2 cas, le nom du constructeur n'est pas valide, à moins que le nom ne soit pas un vrai nom mais plutôt un code constructeur.

    Il en est de même quand à la liste des modes retournés, ils ne correspondent à aucun des modes fournis par la doc ? J'en déduit une erreur de ma part.


  17. #17
    Membre habitué Avatar de Nico*3-3
    Inscrit en
    Octobre 2004
    Messages
    164
    Détails du profil
    Informations forums :
    Inscription : Octobre 2004
    Messages : 164
    Points : 145
    Points
    145
    Par défaut
    Bonjour !

    L'erreur est dans le deuxième extrait, effectivement...
    Mais je n'ai pas compris si tu peut le compiler...

    Pour être que MASM l'accepte, tu peut faire de la façon suivante (je pense, je n'utilise pas MASM...) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    mov  bx, offset Buffer
    add  bx, 5
    mov  es, [bx]
    mov  di, [bx+2]
    Après, oui, ah doit contenir le premier caractère, mais il y a peut-être une autre erreur : Je crois que l'offset en mémoire est stocké avant le segment (mais je ne suis pas sûr, c'est comme ça pour les vecteurs d'interruption), il faudrait donc essayer dans l'autre sens...

    Je pense que ça doit fonctionner... Je le ferai bien avec FASM mais je ne connais vraiment pas bien la syntaxe MASM, désolé.

    J'espère que ça aura résolu ton problème.

    A bientôt !
    Tout a une fin, sauf l'infini...
    Projet SKAN : Développement commun d'OS

    Nico*3-3

  18. #18
    Candidat au Club
    Inscrit en
    Février 2005
    Messages
    12
    Détails du profil
    Informations forums :
    Inscription : Février 2005
    Messages : 12
    Points : 2
    Points
    2
    Par défaut
    Bonjour,

    En fait, j'arrive à compiler mon code, mais ça ne marche. J'ai essayé votre code, mais ca ne parche pas non plus (en récupérant l'OFSSET dans les 16 bits de poids faible ou fort, mais, il semble que ce soit dans faible). :

    Quelle différence y-a-til entre
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    mov  bx, offset Buffer 
    add  bx, 5 
    mov  es, [bx]
    et
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    mov  bx, offset Buffer+5
    mov  es, [bx]
    C'est très frustrant de ne pas comprendre l'erreur.


  19. #19
    Membre éclairé
    Profil pro
    Inscrit en
    Juillet 2002
    Messages
    842
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2002
    Messages : 842
    Points : 696
    Points
    696
    Par défaut
    Donnez plutôt l'erreur exacte d'assemblage de MASM, on s'en sortira mieux.

    Pour ce qui est de votre problème, la documentation que j'ai, précise 06h et non 05h pour le pointeur far :

    00h Signature VESA ("VESA") 4 BYTE
    04h Version VESA, Numéro de version principal 1 BYTE
    05h Version VESA, Numéro de version secondaire 1 BYTE
    06h Pointeur FAR sur chaîne ASCIIZ contenant le nom du fabricant de cartes 1 DWORD
    0Ah Flag indiquant les performances de la carte. Actuellement inutilisé, donc 0000h.
    0Eh Pointeur FAR sur liste contenant les numéros de code des modes vidéo reconnus 1 DWORD
    une meilleure solution serait donc :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    mov es, word ptr [Buffer+08h]
    mov si, word ptr [Buffer+06h]
     
    mov ah, es:[si]
    (qui semble être accepté par MASM)

  20. #20
    Membre habitué Avatar de Nico*3-3
    Inscrit en
    Octobre 2004
    Messages
    164
    Détails du profil
    Informations forums :
    Inscription : Octobre 2004
    Messages : 164
    Points : 145
    Points
    145
    Par défaut
    Bonsoir !

    L'adresse du pointeur far est bien 06h et pas 05h...

    J'ai un peu creusé la question et voilà un code complet qui fonctionne au poil avec FASM (tu n'auras le tester) que tu n'auras plus qu'a traduire en MASM, car je n'en connais pas bien la syntaxe :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
                            Format          MZ
     
                            FarPointer      equ                             06h
     
    segment Code_Seg
     
      Start:
     
                            mov             bx, Buffer_Info                 ;Préparation du buffer
                            mov             es, bx
                            mov             di, Buffer
                                                                            ;Appel de la fonction
                            mov             ax, 4F00h
                            int             10h
     
                            mov             ax, 0003h                       ;Je ne sais pas pour vous, mais chez moi
                            int             10h                             ;Ca passe directement en mode graphique, il
                                                                            ;faut donc réinitialiser le mode texte
                            mov             eax, [es:di+FarPointer]
                            mov             dx, ax                          ;On met dans ds:dx l'adresse du buffer du constructeur
                            sar             eax, 16
                            mov             ds, ax
     
                            mov             ax, 0B800h
                            mov             es, ax
                            mov             cx, 256
                            mov             si, dx
                            xor             di, di
      loop0:
     
                            mov             al, [ds:si]
                            or              al, al
                            jz              next
                            mov             ah, 0Fh
                            mov             [es:di], ax
                            inc             si
                            add             di, 2
                            loop            loop0
     
      next:
     
                            mov             ah, 08h
                            int             21h
     
                            mov             ax, 4C00h
                            int             21h
     
    segment Buffer_Info
     
      Buffer                rb              256
    Il y a peut-être quelques absurdités car c'est fait à la va-vite mais je n'est malheureusement pas le temps de tout expliquer...
    Blusuff voudra peut-être...

    Quelques précisions tout de même :

    - Int 21h / ah=08h -> Attendre qu'un touche soit pressée au clavier
    - Instruction sar -> Instruction qui décale les bits d'un registre vers la droite

    S'il y a d'autres incompréhensions n'hésite pas !

    Blustuff : Peut-être pourrais-tu prendre le relai pour lui expliquer les instructions et les autres truc peut-être délicats... Merci !

    Au fait, en mémoire le segment est stocké après l'offset, mais c'est en fait une question de little endian :

    0123:4567h
    sera en fait en mémoire représenté comme suit : 67h 45h 23h 01h
    Mais lorsque l'on charge eax avec, il aura bien 01234567h.
    C'est une question de façon de voirle chose, si on se représente la mémoire avec l'adresse 0 commençant à droite et en partant ensuite vers la gauche, tout rentre dans l'ordre...

    Salut !
    Tout a une fin, sauf l'infini...
    Projet SKAN : Développement commun d'OS

    Nico*3-3

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. [Free Pascal] Mode d'affichage de la fenêtre graphique
    Par diden138 dans le forum Free Pascal
    Réponses: 5
    Dernier message: 09/06/2006, 18h55
  2. [DEBUG.EXE] pour un mode graphique (13h)
    Par powerpsy dans le forum Assembleur
    Réponses: 9
    Dernier message: 19/04/2006, 15h42
  3. [MFC Visual C++]conseil sur affichage graphiques
    Par C++beginner dans le forum MFC
    Réponses: 6
    Dernier message: 10/01/2006, 06h47
  4. Affichage graphique sous forme de tableau.
    Par eulone dans le forum C++
    Réponses: 2
    Dernier message: 24/11/2004, 20h34
  5. [TP]Affichage graphique
    Par maleklegolas dans le forum Turbo Pascal
    Réponses: 5
    Dernier message: 02/11/2003, 19h42

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo