[LINUX] LIRE CLAVIER ET ECRIRE CONSOLE

sheorogath Messages postés 2448 Date d'inscription samedi 21 février 2004 Statut Modérateur Dernière intervention 29 janvier 2010 - 16 juil. 2006 à 20:34
_dune2_ Messages postés 141 Date d'inscription mercredi 19 juillet 2006 Statut Membre Dernière intervention 20 avril 2011 - 27 juil. 2006 à 14:44
Cette discussion concerne un article du site. Pour la consulter dans son contexte d'origine, cliquez sur le lien ci-dessous.

https://codes-sources.commentcamarche.net/source/38641-linux-lire-clavier-et-ecrire-console

_dune2_ Messages postés 141 Date d'inscription mercredi 19 juillet 2006 Statut Membre Dernière intervention 20 avril 2011
27 juil. 2006 à 14:44
salut,
merci pour cette précision.
En fait j'ai oublié de mettre les indicateurs de segment, c'est pourquoi les data se trouve en début du segment de code (et c'est pas beau du tout !! :) surtout si on gère le bit de protection d'écriture et execution des zones mémoires !!!).

Mais je garde l'astuce de mettre les variables en fin de code, pour des embryons de test.

dune2.
cs_patatalo Messages postés 1466 Date d'inscription vendredi 2 janvier 2004 Statut Modérateur Dernière intervention 14 février 2014 2
27 juil. 2006 à 14:26
salut,



le probleme est que tu dois specifier l'offset de debut de desassemblage avec ndisasm car sinon, il commence a 0x00000080 au lieu de 0x00000084.

etant donné que tu a un dword data a 0x00000080, ndisasm le prends comme faisant partie du code si non spécifié et tu te retrouve avec:
00000080 000000 add truc,bidule
00000083 00BA80800408 add [edx+0x8048080],bh
00000089 8B1580800408 mov edx,[0x8048080]

ce code serait correctement désassemblé par ndisasm:
_start:
mov edx,monadresse
mov edx,[monadresse]

mov edx,monadresse
mov edx,[edx]

mov eax,1
mov ebx,0
int 80h

monadresse: dd 0

je me rappelle plus l'option pour specifier l'offset ou commencer le desassemblage, "ndisasm" tout court dans une console doit te l'afficher.

@++
_dune2_ Messages postés 141 Date d'inscription mercredi 19 juillet 2006 Statut Membre Dernière intervention 20 avril 2011
27 juil. 2006 à 13:55
re :)

Aprés plusieurs essais, ... je reste perplexe :)
Je ne sais plus vraiement où se cache la vérité ....
Je m'explique :
- Code d'exemple :

monadresse: dd 0
_start:
mov edx,monadresse
mov edx,[monadresse]

mov edx,monadresse
mov edx,[edx]

mov eax,1
mov ebx,0
int 80h

Et voilà le désassemblage de nasm (ndisasm -b32) :

00000083 00BA80800408 add [edx+0x8048080],bh <- décalage de 1 byte ....
démarrage @00000084 = "mov edx,0x8048080"
00000089 8B1580800408 mov edx,[0x8048080]
0000008F BA80800408 mov edx,0x8048080
00000094 8B12 mov edx,[edx]
00000096 B801000000 mov eax,0x1
0000009B BB00000000 mov ebx,0x0
000000A0 CD80 int 0x80

Ce qui semble tout à fait exact.
Maintenant avec objdump :

8048084: ba 80 80 04 08 mov $0x8048080,%edx <- @ de départ correct
8048089: 8b 15 80 80 04 08 mov 0x8048080,%edx
804808f: ba 80 80 04 08 mov $0x8048080,%edx
8048094: 8b 12 mov (%edx),%edx
8048096: b8 01 00 00 00 mov $0x1,%eax
804809b: bb 00 00 00 00 mov $0x0,%ebx
80480a0: cd 80 int $0x80

Mais à priori une subtilité dans la notation porte à confusion, l'absence de '$' devant une adresse semble indiquer la présence d'un pointeur vers la valeur ....

Ceci explique ma confusion ... et donc confirme que l'utilisation de "mov edx,[buflen] est tout à fait correct, et j'en prend note ;)

Merci pour cette mise au point ;)
cs_patatalo Messages postés 1466 Date d'inscription vendredi 2 janvier 2004 Statut Modérateur Dernière intervention 14 février 2014 2
27 juil. 2006 à 00:22
re,



c'est bien de nasm que l'on parle ?

mov edx,buflen -> edx = adresse de la variable buflen
mov edx,[buflen] -> edx = valeur dword a l'adresse buflen

si tu obtient la meme chose au desassemblage, verifie que tu n'ai pas compilé deux fois la meme chose.

tiré de la doc de nasm (Writing 32bits code):

At the other end of the process, to call a C function from your assembly code, you would do something like this:


extern _printf

; and then, further down...

push dword [myint] ; one of my integer variables
push dword mystring ; pointer into my data segment
call _printf
add esp,byte 8 ; `byte' saves space

; then those data items...

segment _DATA

myint dd 1234
mystring db 'This number -> %d <- should be 1234',10,0

@++
sheorogath Messages postés 2448 Date d'inscription samedi 21 février 2004 Statut Modérateur Dernière intervention 29 janvier 2010 17
26 juil. 2006 à 20:57
woaw merci a tous !!!
je vais tout reprendre alors :s

merci encore
bonne soiree
_dune2_ Messages postés 141 Date d'inscription mercredi 19 juillet 2006 Statut Membre Dernière intervention 20 avril 2011
26 juil. 2006 à 16:57
salut,
les arguments à passer en parametres sont :
eax: N° du syscall (4 pour le write)
ebx: N° du filedescriptor (1 pour stdout)
ecx: Pointeur vers le buffer de la chaine
edx: taille de la chaine à afficher

Donc, Patalo confirme bien la nécessité d'utiliser "mov edx,[buflen]" si buflen est déclaré en "dd",
ou alors "movzx edx,byte[buflen]" dans le cas où buflen est déclaré "db".

Suite à des essais de compilations suivi de désassemblage, j'ai constaté la chose suivante :
l'utilisation de label pour réaliser un adressage indirect ne fonctionne pas.
Je m'explique :

"mov edx,[buflen]" donne le même résultat que "mov edx,buflen", or ce n'est pas ce que l'on souhaite !
Dans notre cas, c'est le contenu de l'adresse buflen que nous voulons mettre dans edx, il faut donc proceder
en 2 étape :

"mov edx,buflen"
"mov edx,[edx]"

Ainsi, aprés désassemblage, le résultat est correct :)

et pour le cas de buflen en "db"
"mov edx,buflen"
"movzx edx,byte[edx]"

Ce qui change quelque peu le source original :) Mais, me dira-t-on, pourquoi alors ça fonctionnait ???
Tout simplement car à la place de la taille, nous avions une adresse qui est largement plus grand que la taille de la chaine, mais que la fonction write s'arrête aussi au 1er caractere null de fin de chain, donc bien avant notre taille de chaine éronée.

dune2.
cs_patatalo Messages postés 1466 Date d'inscription vendredi 2 janvier 2004 Statut Modérateur Dernière intervention 14 février 2014 2
26 juil. 2006 à 15:49
salut,




un dd est obligatoire dans le code de sheorogath étant donné qu'apparement, edx est un pointeur vers la taille.

si c'est la taille qui doit etre dans edx, il faut faire
mov edx,[buflen] ou comme precedement mov edx,buflen-buff avec le code donné par _DUNE2_

faudrait dejà connaitre les paramètres à passer a la fonction systeme eax=4, ensuite, faut voir...

@++
_dune2_ Messages postés 141 Date d'inscription mercredi 19 juillet 2006 Statut Membre Dernière intervention 20 avril 2011
25 juil. 2006 à 23:23
Ooops :)
Y-a un warning à la compilation du à la ligne :
; global _start

Il faut retirer le point-virgule de commentaire ... bon ceci dit, y-a qu'un seul _start et le compilo s'en sort plutot bien tout seul :)

dune2

PS: je tiens à exprimer quand même un doute, si quelqu'un peut confirmer, sur la ligne "mov edx,buflen" du code original. En effet, pour moi, ceci aurait pour effet de charger l'adresse "buflen" et non contenu 1024. Pour charger la valeur "1024", j'écrirais plutot : "mov edx,[buflen]" pour charger le contenu de l'adresse buflen (avec les apports de commentaires concernant l'utilisation de movzx bien entendu).
_dune2_ Messages postés 141 Date d'inscription mercredi 19 juillet 2006 Statut Membre Dernière intervention 20 avril 2011
25 juil. 2006 à 23:08
bonjour,
je confirme le raisonnement de Patalo ainsi que de Necromagik.
Je souhaite juste apporter une précision au message de Necromagik :
edx est un registre 32bits. Pour cette raison, l'utilisation de "dd" pour reserver la variable semble plus adapté. Mais l'utilisation de "dw" reste possible, à la différence que c'est une reservation d'un mot 16bits et qu'il faudra utiliser l'intruction "movzx" comme le mentionnait Patalo pour 'étendre' (movzx = mov with zero extension) ta variable 16bits en 32bits dans le registre "edx" en complétant avec des zéro.

une autre solution à ton exemple pour se passer du stockage de la longueur est d'utiliser la soustraction de 2 pointeurs pour calculer la taille de celui-ci dans ton code au moment de la compilation :

; Instruction de compilation :
; NASM -f elf hello_world.asm
; ld -o hello_world hello_world.o
;segment .data ; ; variables initialisées constantes
; buflen: db 1024 ; taille du buffer
segment .bss
buf: resb 1024 ; buffer
buflen:
; on utilisera la soustraction des 2 pointeurs buf et buflen pour calculer
; la taille de buf au moment de la compilation, ce qui évite tout risque
; de modification inattendu de buflen en mémoire
segment .text ; équivalent de main() mais c'est pas une fonction
; global _start
_start: ; programme en lui même
mov eax,3 ;syscall 3 => read
mov ebx,0 ; 0 => lit le clavier
mov ecx,buf ;dans quoi on stock
mov edx,buflen-buf ;taille du buffer calculé à la compilation
int 80h ;on execute en appelant la syscall
mov eax,4 ;syscall 4 => write
mov ebx,1 ;1 => STDOUT
mov ecx,buf ; ecrire quoi ? buf
mov edx,buflen-buf ;taille du buffer calculé à la compilation
int 80h ;appel de syscall
mov eax,1 ; 1 => exit
mov ebx,0 ; 0 code de sortie
int 80h ;fin

dune2.
sheorogath Messages postés 2448 Date d'inscription samedi 21 février 2004 Statut Modérateur Dernière intervention 29 janvier 2010 17
25 juil. 2006 à 19:45
ok merci de ton aide ^^
actuellement je bosse pendant mon temps libre sur une autre source linux qui seras poster mais je galere
je prendrais en compte tes conseil
merci
cs_necromagik Messages postés 3 Date d'inscription dimanche 20 juin 2004 Statut Membre Dernière intervention 25 juillet 2006
25 juil. 2006 à 12:18
Salut

Pas forcément un dd, un dw peut aller.

Voilà les correspondances (je te met aussi l'équivalent en C..)

(unsigned char) - db: 1 octet - 256 valeurs
(unsigned short int) - dw: 2 octets - 65535 valeurs
(unsigned int) - dd: 4 octets - 4 milliards et quelques
sheorogath Messages postés 2448 Date d'inscription samedi 21 février 2004 Statut Modérateur Dernière intervention 29 janvier 2010 17
17 juil. 2006 à 11:52
re, ^^
si j'ai bien compris (ne pouvant tester de suite :() il faut que je remplace mon db par dd ?
sheorogath Messages postés 2448 Date d'inscription samedi 21 février 2004 Statut Modérateur Dernière intervention 29 janvier 2010 17
17 juil. 2006 à 10:20
merci je regarde le tout merci bcp
ca va peut etre m'aider pour le probleme sur mon nouveau prog
asm :p

allez merci je regarde

++
cs_patatalo Messages postés 1466 Date d'inscription vendredi 2 janvier 2004 Statut Modérateur Dernière intervention 14 février 2014 2
17 juil. 2006 à 10:16
re,




je ne devais pas etre réveillé hier soir, un db avec une valeure de 1024 c'est impossible (0..255). Ce code ne doit pas se compiler sans generation d'une erreur.

@++
cs_patatalo Messages postés 1466 Date d'inscription vendredi 2 janvier 2004 Statut Modérateur Dernière intervention 14 février 2014 2
17 juil. 2006 à 01:30
re,


a moins que la valeur a mettre dans edx ne soit un pointeur vers la taille mais je pense que la valeur devrait etre en dword et pas en byte à ce moment, c'est corrigé grace a l'alignement mais si tu met une autre déclaration dans le segment data, ça ne marche plus.

@++
cs_patatalo Messages postés 1466 Date d'inscription vendredi 2 janvier 2004 Statut Modérateur Dernière intervention 14 février 2014 2
17 juil. 2006 à 01:21
salut,


c'est de l'asm 32, et en plus, il y a peu de code linux, c'est donc toujours interessant ne serait-ce que pour les débutants.

une petite erreur qui doit je pense se corriger toute seule grace a l'alignement DWORD:
mov edx,buflen -> movzx edx,byte buflen (tu déclare un db et pas un dd)

@++
sheorogath Messages postés 2448 Date d'inscription samedi 21 février 2004 Statut Modérateur Dernière intervention 29 janvier 2010 17
16 juil. 2006 à 20:34
je suis ouvert a tout commentaire/blame/eloge/question
si vous voulez la liste des interruption linux j'ai un pdf (envoyez moi un mp avec votre mail)

je sais que le code est simple mais impossible de trouver un equivalent sur le net donc voila ^^
Rejoignez-nous