détourner l'interruption du clavier

détourner l'interruption du clavier - ASM - Programmation

Marsh Posté le 18-07-2004 à 18:49:20    

Bonjour
J'ai besoin de détourner l'interruption de clavier afin de gérer les touches "manuellement" et d'une manière efficace pour mon programme. Je suis en mode protégé (avec dos4gw).
Je n'ai aucun problème pour parametrer le vecteur d'interruption:
mov ax,205h
mov bl,09
mov cx,cs
lea edx,int9
int 31h
Par contre au moment de l'execution du programme, l'interruption est bien appelée quand j'appuie sur une touche, tout ce passe normalement sauf au moment du iret qui renvoie n'importe où et provoque une erreur (retour au bureau de windows).
voici l'interruption:
 
int9 proc far              
cli
push edi
push eax
lea edi,touches
in al,60h
cmp al,128
jae relache
 
xor ah,ah
push ax
xor eax,eax
pop ax
add edi,eax
mov byte ptr [edi],1
jmp fin_int9
 
relache:
xor ah,ah
push ax
xor eax,eax
pop ax
sub ax,128
add edi,eax
mov byte ptr [edi],0
 
fin_int9:
mov al,20h
out 20h,al
pop eax
pop edi
sti
iret
int9 endp
 
Merci de votre aide
chep

Reply

Marsh Posté le 18-07-2004 à 18:49:20   

Reply

Marsh Posté le 18-07-2004 à 20:34:24    

parceque c'est iretD qu'il faut et non iret ;)

Reply

Marsh Posté le 18-07-2004 à 20:39:16    

sinon je supposes que t'as zieuté l'archivé 7-zip que je t'avais filé ?
passque dans mon code c'était bien un iretd.

Reply

Marsh Posté le 19-07-2004 à 19:50:49    

j'avais pas zieuté j'aurais du mais comme ça marchait je me suis diit que j'avais autre choses a faire. Comme quoi je suis bien con, j'aurais gagné du tps! Merci bien!

Reply

Marsh Posté le 19-07-2004 à 21:04:05    

Et la sauvegarde des flags ? Elle est où ?

Reply

Marsh Posté le 20-07-2004 à 03:26:34    

exact :D

Reply

Marsh Posté le 20-07-2004 à 03:28:56    

non pas exact les flags sont automatiquement pushés/popés à l'interruption et au iret.

Reply

Marsh Posté le 20-07-2004 à 08:09:07    

Exact : Une IRET fait ceci (j'avais oublié, cela fait longtemps que je ne m'était plus penché sur les IRQ)
pushl   EFLAGS
pushl   CS
pushl   EIP
 
Par contre y a comme un bug.
Ton prog assume le fait que le segment est sélectionné (ES/DS). Erreur !
Il faut tjrs le sélectionner manuellement.
 
Avec DJGPP :
pushl     %eax
pushw     %ds
movw      ___djgpp_ds_alias, %ax
movw      %ax,%ds
 
Up> Attention, certains serveurs DPMI refuse CLI/STI
Pour ma part, avec DGJPP, mon moteur multi-tâche fonctionnait parfaitement sous Windows 98. Je viens de tester sous XP. Et ça ne se lance pas.


Message édité par christophe_d13 le 20-07-2004 à 08:16:27
Reply

Marsh Posté le 20-07-2004 à 12:08:17    

Merci pour tout, mais j'ai encore plusieurs questions:
1) quelle est la différence entre iret et iretd?
2) c'est quoi pushl et pushw?
Je vais voir pour DS c'est vrai que pour l'instant c'est un peu a l'arrache mais dejà ça fonctionne. Je tiens à dire que l'assembleur de DJGPP est un peu chelou pour pas grand chose:
movw %ax,%ds
à la place de
mov ds,ax
ca fait bizarre, déjà que l'assembleur est long à taper et qu'on se retrouve facilement avec des milliers de lignes...

Reply

Marsh Posté le 20-07-2004 à 12:54:02    

1> iret et iretd
Aucune différence c'est le même op-code (0xCF). C'est simplement une dénomination pour le mode protégé où les registres sont en 32 bits. Donc IRET = IRETD. Il existe également IRETW (toujours opcodé 0xCF).
C'est juste une appelation différente pour spécifié un modèle de fonctionnement. Fait une recherche sur google.
 
2>Un peu "chelou" ? Nuance, c'est la norme at&t...
Intel = mov eax, [esi]
AT&T = movl (%esi), %eax
 
Dans la norme AT&T appliquée au x86, on spécifie toujours la taille des opérandes de manière explicite : l pour long (32 bits), w pour word (16 bits) et b pour byte (8 bits).
Ainsi "pushw" = "push word"
Cela parait lourd au début, mais cela évite les erreurs du genre :
La norme intel a un défaut :
  mov [esi], 0x12 - 8, 16 ou 32 bits ?
  mov dword ptr [esi], 0x12 - 32 bits
La norme AT&T est plus explicite :
  movl $0x12, (%esi) - 32 bits

Reply

Marsh Posté le 20-07-2004 à 12:54:02   

Reply

Marsh Posté le 20-07-2004 à 13:17:23    

je vois, chacun son truc, moi je préfère la norme intel, c'est comme ça que j'ai commencé et je suis habitué...
 
J'ai une erreur dans mon prog qui arrive de tps en tps, jamais au meme moment et j'ai vérifié mon code, je pense que ça viens de ma nouvelle int9.
A mon avis cela vient de DS qui n'est pas "bon" pour modifier ma variable touches. J'avais déjà détourné cette int en mode réel et j'avais résolu le pb comme ça
 
dw ?
int9 proc far
push ax
push bx
push ds
xor bx,bx
mov ax,cs:[bx]
mov ds,ax
...
 
bien sur le segment de code commençait comme ça et j'avais, au moment de détourner l'interruption, mis le contenu de ds dans cs:[0]. Comme ça ds pointait tjs vers mon segment de données pendant l'int9.
J'ai tenté de faire pareil en mode protégé mais quand je modifie des octets de cs (je n'ai pas placé la variable au debut de segment cette fois) mon prog plante. Or cs est le seul point commun entre mon prog et l'int9. Comment je peux faire pour sauvegarder ds? (en norme intel, lol)

Reply

Marsh Posté le 20-07-2004 à 13:31:37    

J'ai aussi commencé avec la norme intel et je bosse aussi bien dans l'une que l'autre.
 
Ton compilateur doit fournir le segment DS correctement. Tu dois trouver une variable qui le contient et faire si c'est possible d'un code modifiable :
_MaLigneModifiable:
mov ax, 0x2345
mov ds, ax
 
Pour modifier mov ax, 0x2345, tu fait :
mov ax, _MaLigneModifiable
add ax, 2 //C'est 2 normalement pour le modRM : reg, imm
mov bx, ds
mov cs:[ax], bx  
 
Si c'est pas 2, c'est 1 mais je suis quasiment sur que c'est 2.

Reply

Marsh Posté le 20-07-2004 à 13:55:25    

Le pb c'est que dès que je mais une ligne du style:
mov cs:[...],...
mon programme plante et reviens à windows...
Je sais que c'est cette ligne qui plante, je débug avec soft ice et quand j'arrive sur cette ligne je me retrouve avec un changement de segment de code, il fait quelques instructions, un ret et hop me voila sur le bureau!

Reply

Marsh Posté le 20-07-2004 à 14:02:34    

Et oui, sous Windows, c'est logique pour lui un segment de code est read-only et execute-only.
 
Il faut trouver le moyen avec le compilateur qu'il te remplisse la variable comme je le fais avec DJGCC :
mov ax, ___djgpp_ds_alias
mov ds, ax
 
Tu dois avoir une variable globale à mettre. Faut juste que tu trouves le nom de cette dernière.

Reply

Marsh Posté le 20-07-2004 à 14:08:08    

bin en fait l'astuce, c'est qu'en mode protégé avec Dos4gw tu ne changes jamais de DS.
 
donc potentiellement quand une interruption est issue est en mode protégé y'a beaucoup de chances que le DS soit à celui du code normal du code.
 
mais je suis d'accord il vaux mieux mettre DS au sélecteur du code normal.
 
ceci dit mon handler de clavier en mode protégé que j'utilisais avec DOS4W n'avait pas de problèmes de stabilités.
 

Reply

Marsh Posté le 20-07-2004 à 15:06:56    

Ben chaque fois que je break sur mon int9, ds est correct.
Mon prog tourne sans pb si je ne touche pas le clavier, et quand j'appuie sur une touche qui ne "fait rien" l'int9 remplit bien la case de mon tableau 'touches' correspondante et le prog continue normalement. Si je reste appuyé sur cette touche inutile, le prog finit par planter. C'est pour ça que je pense que ça vient de là...

Reply

Marsh Posté le 20-07-2004 à 23:00:32    

en fait dans ton code propre, tu as peu de raisons de changer DS (et c'est toi qui le sais).
après au niveau du Dos-Extender, quand c'est son code qui s'éxécute, là c'est l'inconnue, donc c'est vrai que ce serait judicieux d'avoir une variable globale pour obtenir un DS sain.

Reply

Marsh Posté le 21-07-2004 à 13:56:32    

ça serait judicieux mais je ne sais pas comment faire.
je ne peux pas modifier le segment de code (j'ai essayé push cs, pop ds et de modifier avec mov ds:[edi],... mais ça plante pareil), je ne peux pas utiliser la pile puisque je ne sais pas quand l'int a lieu et je ne peux bien sur pas sauvegarder ds dans une variable puisque si ds change, je n'aurais plus accès à la variable.

Reply

Marsh Posté le 21-07-2004 à 14:14:03    

déjà tu ne peux pas copier CS dans DS.
CS est un sélecteur sur du code.
DS est un sélecteur sur des données.

Reply

Marsh Posté le 21-07-2004 à 14:16:56    

sinon tu utilises la technique de christophe pour modifier le code de l'interruption à l'initialisation.

Reply

Marsh Posté le 21-07-2004 à 19:39:00    

je viens de résoudre mon probleme mais je ne sais pas si ça va tjs fonctionner ou si c'est un coup de chance.
En debugant avec soft ice, je me suis rendu compte que pendant l'execution de mon prog, les données placées dans ds:offset étaient les même que cs:offset.
j'ai donc placé une variable sauve_ds qui contient ds:
lea edi,sauve_ds
mov ds:[edi],ds
et pendant l'int9 j'y accède avec cs:
lea edi,sauve_ds
mov ax,cs:[edi]
mov ds,ax)
la variable sauve_ds est placée au milieux de mon code (juste avant le début de l'int9 exactement) et maintenant tout fonctionne. Est-ce que c'est un grand coup de chance ou bien est-ce que cs et ds correspondent tjs comme ça?

Reply

Marsh Posté le 21-07-2004 à 20:31:01    

oui ! je suis con.
 
avec DOS4G(W) et beaucoup d'autres Dos-Extenders (pour CwsDpmi livré avec djgpp je sais pas), le segment de code et de donnée commençent en 0.
 
donc un offset donnera la même adresse physique avec CS et DS.
 
c'est juste que contrairement au mode réel, en mode protégé tu n'as pas le droit de copier CS dans DS. (à la .com)

Reply

Marsh Posté le 22-07-2004 à 09:21:53    

Pour DJGPP, il faut utiliser ___djgpp_ds_alias

Reply

Marsh Posté le 22-07-2004 à 14:51:13    

mais c'est quoi une constante, ou une variable globale ? (je suis jamais tombé sur la même chose avec le watcom)

Reply

Marsh Posté le 22-07-2004 à 19:34:01    

moi non plus

Reply

Marsh Posté le 22-07-2004 à 21:02:58    

chistophe ça te fait quoi un mov avec immédiat ou un mov avec offset ? (ce qui serait po logique ce qui réponds à ma question :D)

Reply

Marsh Posté le 22-07-2004 à 21:13:59    

___djgpp_ds_alias est un immédiat remplit lors du chargement de l'application (comme pour les CALL et JMP FAR) via la table de redirection.

Reply

Marsh Posté le 22-07-2004 à 22:53:05    

oki.
ceci expliquant cela.
 
avec Dos4Gw + Watcom, j'ai jamais vu de truc similaire, donc autant rester sur la technique de l'immédiat modifié à l'init à travers un label, ou une variable globale accédée par CS.


Message édité par bjone le 22-07-2004 à 23:00:20
Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed