Le mécanisme de callback mode réel DPMI autorise un client DPMI mode protégé à être appelé comme un sous-programme par des programmes mode réel de manière transparente. Ainsi,un programme mode réel peut utiliser le callback pour transmettre des information au client DPMI, ou obtenir des services fournis par ce client, sans necessairement être au fait du mode protégé ou de la memoire etendue . Le mécanisme de callback peut être vu comme la réciproque des Int 31H Fonctions DPMI 0300H, 0301H, and 0302H, qui autorise un client DPMI à transmettre des informations à un programme mode réel , ou obtenir des services d'un programme mode réel,d'une manière transparente.
Pour rendre le callback mode réel accessible, le client DPMI doit d'abord appeler l'Int 31H Fonction 0303Havec le selecteur et l'offset de la routine en mode protégé qui recevra le contrôle quand le callback est amorcé, et le selecteur et l'offset d'une structure de données mode réel (dans le même format que celui utilisé pour Int 31H Fonctions 0300H, 0301H, et 0302H). La Fonction 0303H renvoie une addresse mode réel (segment:offset) pour le point d'entrée callback qui peut être transmis au programme mode réel par une interruption logicielle ou un far call (Int 31H Fonctions 0300H, 0301H, ou 0302H), un bloc de mémoire DOS,ou un autre mécanisme convénient.
Quand le programme mode réel execute un FAR CALL vers L'adresse callback mode réel qui lui est fournie par le client DPMI,l'hôte DPMI sauve le contenu de tout les registres mode réel dans la structure de données mode réel du client, bascule le CPU en mode protégé,et entre dans la routine callback du client DPMI avec les conditions suivantes:
La procédure callback peut alors extraire ses paramètres de la structure de données mode réel et/ou copier les paramètres de la pile mode réel à la pile mode protégé. Rapellez-vous que le champ registre de segment de la structure de données mode réel contient des addresses de segment ou de paragraphe qui ne sont pas valides en mode protégé. Les pointeurs far transmis à la structure de données mode réel doivent être traduits en addresses virtuelles avant de pouvoir être utilisés. La procédure recommendée est pour le client DPMI d'allouer un selecteur pour cet usage pendant son initialisation, puis employer l'Int 31H Fonction 0007H dans la procédure de callback pour régler la base du segment à 16 fois la valeur trouvée dans le segment de registre en mode réel . Le client DPMI ne doit PAS utiliser l'Int 31H Fonction 0002 pour cet usage, car les selecteurs alloués par la Fonction 0002 ne peuvent jamais être libérés.
Offset Longueur Contenus 00H 4 DI ou EDI 04H 4 SI ou ESI 08H 4 BP ou EBP 0CH 4 reservé,doit être zéro 10H 4 BX ou EBX 14H 4 DX ou EDX 18H 4 CX ou ECX 1CH 4 AX ou EAX 20H 2 flags etat CPU 22H 2 ES 24H 2 DS 26H 2 FS 28H 2 GS 2AH 2 IP 2CH 2 CS 2EH 2 SP 30H 2 SS
La procédure callback se termine en executant une IRET avec l'addresse de la structure de données mode réel en ES:(E)DI,transmettant l'information à l'appelant en mode réel en modifiant le contenu de la structure de données mode réel et/ou en manipulant le contenu de la pile mode réel . La procédure callback est responsable de la gestion des bonnes addresses dans la structure de données mode réel pour la reprise de l'execution en mode réel; habituellement, ceci est accompli par l'extraction de l'addresse de retour de la pile en mode réel et le placement d'icelle dans les champs CS:IP de la structure de données mode réel . Après l' IRET, l'hôte DPMI bascule le CPU en mode réel,charge tous les registres (inclus CS:IP) avec le contenu de la structure de données mode réel , et finallement rends le contrôle au programme en mode réel .
Bien que la structure d'appel mode réel et le selecteur utilisé pour SS en mode réel soient statiques,il convient de prendre soin en écrivant des procédures callback qui peuvent être réentrées (par exemple, dans un programme mode réel qui gére des interruptions matérielles). La méthode la plus simple pour éviter la réentrance est de laisser les interruptions désactivées pendant l'entière procédure callback. Neammoins, si la quantité de code executé par le callback est elevée, le client peut préferer copier la structure de données mode réel dans un buffer alloué dynamiquement ,réactiver les interruptions et ne pas utiliser DS. La structure de données mode réel pointée par ES:(E)DI après retour de la procédure callback n'aPAS besoin d'être à la même addresse que la structure de données mode réel.
Les hôtes DPMI doivent fournir un minimum de 16 addresses callback par machine virtuelle. Les callbacks mode réel sont une ressource sytème limitée. Le client DPMI doit toujours utiliser l'Int 31H Fonction 0304H pour libérer les callbacks qui ne sont plus utilisés.
Exemple: Le code suivant est un exemple de détournement d'interruption en mode réel. Il détourne l'Int 21h de DOS et retourne une erreur pour la d'effacement de fichier (AH=41H). Les autres appels sont transmis directement auDOS. Cet exemple démontre les techniques emplyoées pour détourner une interruption en mode réel. Notez que comme les appels DOS sont reflétés du mode protége au mode réel, le code suivant interceptera tous les appels DOS du mode réel et du mode protégé.
;****************************************************** ; ; Cette procédure obtient le Seg:Offset courant de l'Int 21H en mode réel ;,alloue une addresse de call-back mode réel, ; et fixe le vecteur de l'Int 21H en mode réel à ; l' addresse de call-back. ; ;****************************************************** Initialization_Code: ; Crée un alias de segment de code pour ; y sauvegarder les données mov ax, 000Ah mov bx, cs int 31h jc ERROR mov ds, ax assume ds:_TEXT ; Obtient le SEG:OFFSET de l'Int 21H en mode réel ; mov ax, 0200h mov bl, 21h int 31h jc ERROR mov [Orig_Real_Seg], cx mov [Orig_Real_Offset], dx ; Alloue une addresse de call-back mode réel ; mov ax, 0303h push ds mov bx, cs mov ds, bx mov si, OFFSET My_Int_21_Hook pop es mov di, OFFSET My_Real_Mode_Call_Struc int 31h jc ERROR ; Detourne l'int 21H sur l'adresse ; de callback ; mov ax, 0201h mov bl, 21h int 21h jc ERROR ;****************************************************** ; ; Voici le code de détournement de l'int21H. Il renvoie ; un "accès refusé" pour les appels mode réel D'effacement ; de fichier. Les autres appels sont transmis au DOS. ; ; ; ENTREE: ; DS:SI -> SS:SP en mode réel ; ES:DI -> structure d'appel du mode réel ; Interruptions désactivées ; ; SORTIE: ; ES:DI -> structure d'appel du mode réel ; ****************************************************** My_Int_21_Hook: cmp es: [di.RealMode_AH], 41h jne Chain_To_DOS ; ; En cas de tentativ d'effacement de fichier (AH=41h), ; on simiule un iret sur la pile mode réel, ; pose le flag carry, ; et transmets la valeur 5 dans AX ; pour indiquer une erreur "accès refusé". ; cld lodsw ; Obtient l'adresse de retour IP mode réel mov es:[di.RealMode_IP], ax lodsw ; Obtient l'adresse de retour CS mode réel mov es:[di.RealMode_CS], ax lodsw ; Lis les flags mode réel or ax,1 ; Pose le flag carry mov es:[di.RealMode_Flags], ax add es:[di.RealMode_SP], 6 mov es:[di.RealMode_AX], 5 jmp My_Hook_Exit ; ; Chainage original du vecteur de l'Int 21h en remplacant ; CS:IP en mode réel avec le Seg:Offset originel. ; Chain_To_Dos: mov ax, cs:[Orig_Real_Seg] mov es:[di.RealMode_CS], ax mov ax, cs:[Orig_Real_Offset] mov es:[di.RealMode_IP], ax My_Hook_Exit: iret