Votre question

Problèmes Batch. - Page 6

Tags :
  • Echo
  • Programmation
Dernière réponse : dans Programmation
15 Mars 2009 11:34:37

Re,

Oki, donc le cycle d'horloge est bien variable, j'étais parti en délire :p 

Donc je fais un autre petit truc :

"On s'aperçoit qu'il y a plusieurs BUS reliés entre eux et qui ont en général des fréquences différentes d'un bus à l'autre ? Un problème se pose ...
Les accès aux bus doivent être synchronisés.
Imaginez un bus1 de 200 Mhz, et un autre bus2 de 3354 Mhz sans aucun intermédiaire entre eux.
Plusieurs cycles d'horloges du bus2 se retrouveraient en plein milieu d'un cycle d'horloge du bus1 (et inversement), comment réguler ensuite les accès aux bus ..? Impossible... Ce serait donc n'importe quoi (l'anarchie matérielle si on peut dire)

Il faut donc synchroniser les bus, c'est le rôle des "contrôleurs" (NorthBridge, SouthBridge, Contrôleur RAM). Pour faire ceci au mieux, il faut bien choisir le moment précis de lecture/écriture de tel Bus.

Deux contraintes sont présentes :

- S'adapter au Bus (périphérique) le plus lent en ralentissant une des fréquences pour ne pas générer d'erreurs (mais ce qui fait perdre en performance forcément);
- Utiliser des Buffer ( = zone de mémoire vive ou de disque utilisée pour stocker temporairement des données) pour mettre les données en file d'attente.
Ne pas confondre Mémoire Cache et Buffer /!\

~> La mémoire cache est une SRAM (non dynamique) qui stocke les instructions les plus utilisées, le Buffer stocke plus ou moins aléatoirement des données temporairement.

En utilisant bien ces deux systèmes, le contrôleur amortit le plus possible les pertes de temps (perte de performance).

Pour faciliter le processus, la fréquence de la plupart (pas tous !) des composants (CPU, RAM) est basée (partiellement ou non) sur la fréquence du FSB par un coefficient multiplicateur (2x/4x/6x/11x/12x...) pour avoir des cycles d'horloges plus cohérents, ce qui permet des synchronisations plus simples.

Exemple : Si on a un FSB de 200Mhz, et un proco qui tourne à 2200MhZ, alors le coeff multiplicateur est à 11.

Rappel : Un cycle d'horloge n'a pas une durée universelle (au contraire).
--> Fréquence = 1 / Temps d'un cycle d'horloge.
Si on réduit la durée d'un cycle d'horloge, on augmente la fréquence et vice-versa.

Conclusion : L'intermédiaire entre bus, bus et composants est l'une des choses les plus importantes, puisque c'est elle qui permet la synchronisation de vos composants/bus.

N.B : C'est pas pour rien que le Chipset (NorthBridge) supporte seulement quelques vitesses FSB, et quelques types de mémoire seulement.

----------------

Better ?

Juste deux questions subsidiaires :

- J'ai cru comprendre qu'il y avait plusieurs buffer, ou alors un seul mais gros.
Celui qui est utilisé pour faire les C/C, a-t-il une taille limitée ? (je n'ai jamais eu de "buffer overflow"

- Sais-tu concrètement ce que signifie horloge effective par rapport à horloge originelle ?
Sur Everest, pour mon FSB, je vois originelle : 197MHz, et effective 700 quelque chose :D 

Merci..!
a b L Programmation
15 Mars 2009 12:21:40

Citation :
- Utiliser des Buffer ( = zone de mémoire vive ou de disque utilisée pour stocker temporairement des données) pour mettre les données en file d'attente.

Je n'avais pas regardé la définition du wikipedia, et celle-ci me parait fausse, plutôt incomplète. La définition qui est donnée est dans le cadre logiciel. En programmation quand on utilise un buffer, c'est une mémoire pour faire une file d'attente logicielle (en utilisant la RAM).
Au niveau électronique, c'est une puce (ou partie d'une puce) dédiée à ça. Par exemple, les buffers du northbridge sont intégrés dans le chip du northbridge (comme pour les registre avec le CPU).
Sur le wikipedia anglais, le buffer est bien défini de façon générale (et donc pour la partie hardware qui t'intéresse).
http://en.wikipedia.org/wiki/Data_buffer

Citation :
~> La mémoire cache est une SRAM (non dynamique) qui stocke les instructions les plus utilisées, le Buffer stocke plus ou moins aléatoirement des données temporairement.

Moi, j'aurais plutôt dit l'inverse. :) 
Dans la mémoire tampon, côté hardware, les données sont mises en FIFO (donc clairement ordonnées), alors qu'en cache c'est ce qui est souvent réutilisé (ce qui est plus ou moins aléatoire :p  ).

Citation :
- J'ai cru comprendre qu'il y avait plusieurs buffer, ou alors un seul mais gros.
Celui qui est utilisé pour faire les C/C, a-t-il une taille limitée ? (je n'ai jamais eu de "buffer overflow"

Je pense avoir répondu, chaque chip a son ou ses buffers qu'il gère comme il veut. ;) 
Pour le buffer overflow, le tout est de dimensionner les chose et prévoir si ça va saturer. Pour la théorie, voir les chaînes de Markov. :) 

Citation :
- Sais-tu concrètement ce que signifie horloge effective par rapport à horloge originelle ?
Sur Everest, pour mon FSB, je vois originelle : 197MHz, et effective 700 quelque chose :D 

En fait, si tu as les DDR, comme l'a dit dafen, il y a un bit émis sur front montant, et un sur front descendant, donc la fréquence effective est 2 fois supérieure à la fréquence physique de l'oscillateur.
J'ai regardé ton screenshot et je vois que ce n'est pas de la DDR (Double Data Rate), mais de la QDR (Quad Data Rate), donc 4 bits sont émis pour un cycle d'horloge (en utilisant un autre oscillateur déphasé, mais les 2 sont de la même fréquence). Donc, la fréquence effective (au sens fréquence d'envoi de bits par seconde) vaut 4x la fréquence physique de l'horloge.
198 * 4 = 792
15 Mars 2009 13:33:57

Re,

Merci pour le Buffer, je ne savais pas, je vais éditer :) 

Citation :
Dans la mémoire tampon, côté hardware, les données sont mises en FIFO (donc clairement ordonnées), alors qu'en cache c'est ce qui est souvent réutilisé (ce qui est plus ou moins aléatoire :p  ).

Ouais, c'est vrai ! L'exemple "bête" si je confonds pas avec le buffer logiciel est le C/C qui dit clairement les données à "encaisser". Alors que le cache est rempli aléatoirement (puisque on ne peut pas forcément savoir à l'avance ce qui va être le plus utilisé)

Citation :
voir les chaînes de Markov. :) 

Ça a l'air assez mathématique :D 

Ah, je crois avoir compris pour l'horloge originelle et l'horloge effective.
En fait, mon FSB est de type QDR, donc il exploite "4 phases" du cyle d'horloge (4 bits par cycle d'horloge sans prendre en compte la largeur du bus) grâce à des oscillateurs déphasés, ce qui permet un débit 4x supérieur au débit de l'horloge physique (1 bit par cycle d'horloge).
Pour mon bus mémoire, il est de type DDR, donc exploite la phase montante et descendante, ok !

Au final, cela permet de mieux exploiter la capacité du CPU pour le FSB, idem pour le Bus mémoire et la RAM, mais paradoxalement (j'ai peut-être faux), cela contribue au déphasage temporel que l'on veut éviter en mettant une "limite" à la fréquence.

Merci ! :) 
J'éditerai ça dans mon post



Contenus similaires
a b L Programmation
15 Mars 2009 19:13:29

Citation :
Au final, cela permet de mieux exploiter la capacité du CPU pour le FSB, idem pour le Bus mémoire et la RAM, mais paradoxalement (j'ai peut-être faux), cela contribue au déphasage temporel que l'on veut éviter en mettant une "limite" à la fréquence.

Je comprends pas ce que tu veux dire.
15 Mars 2009 20:10:14

Bah, en fait, vu que la fréquence des BUS est relativement plus faible que celle des composants (ram, processeur ici), exploiter le plus possible le cycle d'horloge reviendrait à avoir une fréquence plus haute (horloge effective), donc on peut mieux exploiter les capacités du processeur (qui a une fréquence beaucoup plus élevée), non ?

Pour le déphasage temporel, ça m'étonne un peu oui ..
Citation :
Deux moyens sont possibles pour augmenter le débit de données sur un bus :

- Réduire le temps de cycle (plus de transferts/sec);
- Augmenter la largeur du Bus (plus de bits/transfert).

Hélas plus on joue sur ces facteurs, plus le problème du déphasage temporel se pose (= signaux des différentes lignes se déplacent à des vitesses légèrement différentes). La vitesse n'est donc pas extensible à l'infini !

Ce qui revient au même (en exploitant les fronts du cycle ou avec des signaux déphasés), non ?

Merci
a b L Programmation
15 Mars 2009 20:56:17

oui le problème reste le même, mais quand ça passe, avec le DDR, on envoie plus de données.
16 Mars 2009 17:18:24

Yep, oki, vais éditer ça, encore merci ;) 
29 Mars 2009 21:02:55

Hello CRicky,

J'ai lu cet article un peu en diagonale : http://zone.ni.com/devzone/cda/tut/p/id/5851

Un processeur 64 bits, c'est bien un processeur qui a des registres large de 64bits , non ?

Citation :
Le nombre total d'adresses disponibles dans la mémoire virtuelle – i.e. la quantité totale de données que l'ordinateur peut conserver dans sa zone de travail pour les applications – est déterminé par la largeur des registres du processeur de l'ordinateur.


Processeur 64 bits peut adresser théoriquement 2^64 adresses, et le processeur 32 bits peut adresser théoriqeument 2^31 bits théoriquement.

Normal que je vois pas un rapport direct entre la largeur des registres et l'adressage via un bus par ex ..?

Ceci dit, c'est peut-être parce que j'ai pas encore vu assez en détail l'implémentation. Pour le moment, j'ai vu vaguement "le processeur positionne l'adresse du mot sur les lignes d'adresses, blbla", il serait donc probable que ce soit lié aux Registre, ce qui expliquerait alors tout ça ? (Vais continuer à lire pendant les vacances dans un semaine :p  )

Thanks a lot
a b L Programmation
30 Mars 2009 19:22:14

C'est trop simplifié. Quand tu programmes, tu manipules des adresses mémoires en utilisant les registres. par exemple avec un MOV [EDI], 3, dans le registre EDI, il n'y a pas de valeur, mais une adresse mémoire, et cette instruction (avec les []), va en fait mettre la valeur 03h en mémoire à l'adresse indiquée dans le registre EDI.
C'est simplifié, parce que par dessus, il y a l'OS, la pagination, etc.
30 Mars 2009 19:27:43

Yop,

Yes, je me doute que cela ne se limite pas à des principes liés à l'architecture, j'ai bien lu ce que tu as écrit.
Malgré cela, cela coïncide quand même avec ce que j'avais écrit ? (bien que ce soit effectivement très simplifié)

Du moins, processeur 32 bits = largeur registre 32 b, et proco 64b : registre de 64b ?

Merci beaucoup .. ;) 
a b L Programmation
30 Mars 2009 19:45:24

Oui ce sont bien les registres (un jour ça changera peut-être :D )
30 Mars 2009 20:28:51

Oki, au final (désolé pour la double question, j'aurais du la poser avec !!), donc l'histoire d'adressage des 2^64 et 2^32 adresse sont liées, mais il faut en prendre beaucoup d'autres facteurs (mémoire physique disponible, OS, mémoir epaginée etc.)

Chiant l'école, pas le temps de lire.

Tu m'avais dit que tu avais fait une école d'ingénieur.
As-tu fait SUPINFO, EPITA ou EPITECH à tout hasard ?

Merci
a b L Programmation
31 Mars 2009 20:53:54

Non, ces écoles ne délivraient pas le diplôme d'ingénieur. J'ai fait l'ISIMA.
1 Avril 2009 16:45:18

Yop,

Désolé pour le Recome :

Je crois juste avoir repéré une erreur en relisant un cours :

Citation :
En little endian, on inverse les octets dans un paquet, et en big, on le laisse dans le bon ordre

--> OKK

Citation :
Pour les DWord, on utilise le Big Endian. Par exemple, on met "valeur"=dword:00000001, et bien en vrai (vous le verrez dans modifier données binaires), ce sera 01 00 00 00

--> OK

Citation :
Par contre, quand on entre une donnée en REG_EXPAND_SZ, ou en REG_MULTI_SZ, on entre directement la donnée en Little Endian (c'est pour ça qu'on retrouve le même ordre dans modifier données binaires).

J'ai envie de dire OK, mais ..

Bon, maintenant, prneons n'importe quel exemple.

valeur=blabla(en hexa)

donne en UCS-2 :

62,00,6C,00,61,00,62,00,6C,00,61,00,00,00

Dans mon cours, je dis que c'est du Little-Endian, mais c'est faux non ?

Si c'était du vrai little endiant, les 00 serait dans l'ordre normal non ?
Les paquets de deux bytes sont inversés, mais pas les bytes non ? (vu qu'ici, 2 bytes codent pour un caractère)

Donc du little endiant serait ça je suppose :
00,00,00,61,00,6C,00,62,00,61,00,6C,00,62

Inversé à l'échelle totale (donc par groupe de deux bytes) mais pas à l'intérieur des bytes.

Tu en penses quoi ?
je me suis gourré sur ce coup-là je crois, et finalement, je sais pas expliquer pourquoi dans l'inscription dans la bdr, en UCS-2, les octets sont inversés pour chaque groupe de deux bytes.

Merci !!

a b L Programmation
1 Avril 2009 20:27:30

Citation :
62,00,6C,00,61,00,62,00,6C,00,61,00,00,00

Dans mon cours, je dis que c'est du Little-Endian, mais c'est faux non ?

Si c'était du vrai little endiant, les 00 serait dans l'ordre normal non ?

little endian: l'octet de poids faible est mis en premier.
Pour le premier caractère, tu as 62h = 0x0062.
En big endian (pas d'inversion), ça donne 00 62
En little endian (on inverse), ça donne 62 000
Donc tu as bien du little endian dans le codage des caractères.

En fait quand on parle de little endian ou big endian, ça dépend du contexte. Toi, tu vois maintenant l'endianess sur la chaine de caractère. Donc pour résumer je dirais:
- la chaîne de caractère est en big endian
- le codage du caractère est en little endian
En fait parler d'endianness sur une chaine ne sert à rien, puisque ça n'a pas d'intérêt. Sur le caractère lui-même, l'intérêt se situe dans la conversion d'un codage des caractères à un autre codage.

1 Avril 2009 21:05:35

Yop,

Merci, je vais le préciser.
Codification des caractères -> Contexte à l'échelle du codage d'un caractère
Chaîne de caractères -> Contexte à l'échelle d'une chaîne inversée donc.

En revanche, lorsque tu dis, que l'intérêt se situe dans la conversion d'un codage à un autre, je ne vois pas l'influence qu'a l'ordre des octets sur le codage (utf8, ucs-2 , etc.)

Encore Merci.
a b L Programmation
2 Avril 2009 19:30:12

C'est surtout pour une conversion du genre ascii <-> UCS-2.
ça dépend de l'algo et du choix d'implémentation de regedit.
si tu prends un caractère ASCII 0x30, que tu convertit en ajoutant 00 devant 0x0030. Du coup la valeur est identique. Sur les architectures intel, comme on est en little endian, 0x0030 s'écrit en mémoire 30 00.
Donc en fait la chaine de caractère, si on la lit comme un tableau de valeurs sur 2 octects, on lit 0x0062, 0x006C, 0x0061...

Microsoft aurait pu aussi implémenter ça en big endian, et la conversion en valeur binaire se ferait en en (62 << 8) & 00, (6C << 8) & 00,...
le << 8 est le décalage vers la gauche de 8 bits, et le & le AND.
2 Avril 2009 21:12:05

Yop,

Oki, merci ;) 

Commence à m'attaquer à nouveau au livre (MicroInstruction définie à partir de l'OpCode blabla qui via le microprogramme va dire à l'ual quoi fair eetc .. :p )

PS : J'ai installé Linux hier, la calculette est vraiment bien (avec les portes logiques .. :)  )
4 Avril 2009 22:44:15

Hello,

Avant de poser 2-3 questions, dans le livre, on prend comme exemple la IJVM. La structure générale est la même partout je suppose ?

J'ai vu un peu plus en précision comment ça se passait au niveau de l'UAL.
Différents registres qui envoient leur contenu vers l'UAL via un BUS x.
Le microprogramme se trouvant en ROM contient des microinstructions avec un pointeur de microinstructions [...], et en fonction de l'OPCode définie par le décodage, va choisir la bonne MicroInstruction pour "dire" à l'UAL quoi faire.

Transmis ensuite au décaleur, le résultat va être écrit dans tel(s) registre(s) via le bus y qui part de l'UAL.

Donc, un cycle de l'UAL : - Écriture des données du bus z vers des registres
- Copie des registres sur le bus x pour alimenter l'UAL
- Fonctions de l'UAL et du décodeur (donc finalement le décodage se fait au passage à l'ual ?)
- MicroInstruction désignée exécute son opération.
(Opérations de lecture/écriture si nécessaire (MAR/MDR, IP/MBR)

Tu es d'accord ?

Des trucs que j'ai moyennement compris :

Registre MAR (Memory Adress Table) contient des adresses de mots (et non d'octets).
Exemple : S'il contient la valeur 1, l'adresse 4 est placée sur le bus (pas de mappage direct), donc ici, il part du mot 0 c'est ça ? (0-1-2-3 puisque DWORD : 4 octets) Sinon je comprends pas, en tout cas, c'est cool, ça m'éclaire sur l'expression de la mémoire en bits, octets, mots .. :)  Donc, en fait, il suffit de multiplier par 4 pour obtenir l'adresse à mettre sur le bus.

Par contre, je vois pas trop ce qu'il veut dire quand il dit :
"Lorsque le contenu de MAR est transféré sur le bus d'adresses, ses 32 bits ne sont pas mappés directement sur les 32 lignes du bus (lignes 0 à 31), mais le bit 0 est relié à la ligne 0, le it 1 à la ligne 3, et ainsi de suite".
Y a une logique d'attribution ?.? Que deviennent les autres bits du bus ..

Sinon le principe de pile est bien exposé avec un exemple très concret. Puis exemple d'une compilation d'un bout de code avec correspondance en assembleur java.

Merci

a b L Programmation
5 Avril 2009 11:30:55

En fait, plus tu rentres dans les détails d'implémentations (comme on l'a un peu fait avec les processeurs intel), plus tu vas détailler un processeur spécifique. Justement le décodage des instructions (avec utilisation des divers pipelines caches et autres) dépendent du choix d'implémentation du fondeur.
Registre MAR, idem, jamais entendu parlé pour les intel. Après, si tu prends quelque chose comme la JVM (qui n'est qu'une couche software, même si elle peut être hardware), tu peux avoir un système de registres (comme le MAR) et plus généralement de la mémoire virtuelle indépendante de l'architecture, mais il faut que la JVM traduise cette mémoire virtuelle en mémoire physique.
Bref, t'es pas en train de lire un bouquin pour programmer une JVM ? :D 
5 Avril 2009 13:29:28

Hi,

Ouïe, aïe, ouïe !

J'ai bien fait de demander ! Mon but est justement de retenir et pouvoir me faire des fichiers .txt sur des choses que l'on peut appliquer à tous les processeurs (surtout les intel & amd).
Ici, il prend bien un exemple IJVM, avec de l'assembleur IJVM.
Très bon exemple ici (mais quand j'essaie sur un exe à moi, y a beaucoup plus d'assembleur :p  )

La partie où je suis illustre en effet la IJVM.
En admettant que les registres ne soient pas les mêmes d'un proc à l'autre, le principe est-il le même ? (sinon raaa)

Voici une partie intéressante :

D'abord il parle des piles, là par contre c'est bien général me semble-t-il !
Pool de constantes, bloc de variables, pointeur de pile, c'est bien général ?

Voici deux images que je t'ai uploadé (je trouve ça intéressant ) :





Merci de me dire ce que t'en penses.

Comme d'hab, je note tout ce que je trouve intéressant, donc là j'ai noté pas mal de choses (registres, fonctionnement de la pile et pile d'opérandes).
a b L Programmation
5 Avril 2009 19:42:46

Dans l'exemple du i + j. Quand tu as un exe, tu n'as pas ces 4 instructions, et aucune pile n'est utilisé car les valeurs sont transférés de la mémoire vers des registres différents, le calcul se fait et le résulat se met dans un registre.

Dans une exécutable, il y a:
- les registres, à utiliser le plus souvent pour optimisation
- les données statique dont la zone est définie dans l'exe (chargé en mémoire, donc c'est une zone mémoire "allouée" au chargement de l'exécutable)
- la pile (stack) pour les appels de fonctions et variables temporaires
- le tas (heap) pour tout ce qui est allocation dynamique

En fait, la JVM pourra traduire un ILOAD par un chargement sur la pile ou un chargement dans un registre, c'est un niveau d'abstraction (qui est l'intérêt de la JVM).

Si tu veux voir la théorie sur le fonctionnement des ordinateurs, il faut rester au niveau des machines de Turing, sinon tu rentres dans une implémentation, donc spécifique à un fondeur, même si des concepts sont repris.
5 Avril 2009 20:58:04

Hello,

Okay, CRIcky, c'est compris.

Pour ce qui est des variables temporaires, par exemple %mavariable% en est une ou ça n'a aucun rapport avec ce qu'on fait ? Car à ce que j'ai lu une variable serait donc censé être un mot (dword) ce qui peut très bien être dépassé par n'importe quelle variable.

Sinon, j'ai compris ce que tu voulais dire (d'ailleurs là je commence à lire en diagonale, trop de détails, et pas facile à comprendre..)

Est-ce que tu sais pour ça sinon ? :D 

Citation :
Registre MAR (Memory Adress Table) contient des adresses de mots (et non d'octets).
Exemple : S'il contient la valeur 1, l'adresse 4 est placée sur le bus (pas de mappage direct), donc ici, il part du mot 0 c'est ça ? (0-1-2-3 puisque DWORD : 4 octets) Sinon je comprends pas, en tout cas, c'est cool, ça m'éclaire sur l'expression de la mémoire en bits, octets, mots .. :)  Donc, en fait, il suffit de multiplier par 4 pour obtenir l'adresse à mettre sur le bus.


Par contre, je vois pas trop ce qu'il veut dire quand il dit :
"Lorsque le contenu de MAR est transféré sur le bus d'adresses, ses 32 bits ne sont pas mappés directement sur les 32 lignes du bus (lignes 0 à 31), mais le bit 0 est relié à la ligne 0, le it 1 à la ligne 3, et ainsi de suite".
Y a une logique d'attribution ?.? Que deviennent les autres bits du bus ..

Je suppose que ce problème de registre exprimant la mémoire en mots n'est pas que sur l'IJVM ?

Thanks
a b L Programmation
6 Avril 2009 20:26:56

Comparer avec le batch n'a pas vraiment de sens puisque c'est aussi une sur-couche (l'interpréteur de commande DOS).

Pour le problème du registre, c'est un faux problème. En C, on utilise des adresses d'octets, pas de mots.
8 Avril 2009 18:06:58

Hello,

Avancé un petit peu dans la lecture (pas beaucoup) et prépare un mini-résumé sur les circuits logiques :) 

Est-ce que ça te parle une unité fonctionnelle de recherche ? (IFU = Instruction Fetch Unity) pour éviter à l'UAL d'incrémenter IP.

L'histoire de pipelines qui ""crée"" les dépendances RAW (Read After Write) lorsqu'une "microétape" attend le résultat d'une microétape précédente., ce qui entraîne une temporisation par voie de codage (stalling) : attendre que la dépendance soit résolue pour commencer une nouvelle microinstruction. (étapes divisées en "cycles virtuels").

Avec ce que j'ai noté , on aurait donc :

- Une ROM interne indexée par OPCode.
Chaque entrée de cette mémoire comprend :

- la longueur de l'instruction
- index de positionnement dans une autre ROM, celle des microopérations.
Le décodeur analyse le flux d'octets pour produire les instructions et distinguer les différents octets. Il transmet l'index (destiné à la rom des microopérations) qu'il trouve dans sa table à l'unité de mise en fille d'attente.
Composé de deux tables internes, un en ROM l'autre en RAM.
ROM renferme le micro-programme, avec chaque instruction composée de microopérations.

[Ensuite il illustre un exemple]

====> tout ça, c'est du général, ou c'est spécifique encore une fois ? Parce que sinon, je distingue pas ce qui est MicroProgramme, micro-instruction etc.

-> Le problème du GoTo (microbranchement) : Au branchement conditionnel, le fonctionnement du pipeline s'arrête. L'unité de mise en attente n'evoie pas le signal d'acquittement au décodeur ce qui entraîne une temporisation jusqu'à résolution.

=> C'est pour cette raison que vous aimez pas le GoTo, ou aucun rapport ?

---------

En fait, je comprends moyennement la couche microarchitecturale.

Pour les micro-instructions, à ce que je vois dans le livre, apparemment, ça consiste à faire des opérations très simple, mais précises.
Par exemple donner une valeur à un registre, faire une soustraction-addition... tu es d'acccord ?
-> Origine des "jeux d'instructions".

En regardant sur le Net à microarchitecture, je tombe plus sur les caches, prédictions d ebranchements etc .. (j'y arrive avec mon livre).

J'ai jeté un oeil ici : http://fr.wikipedia.org/wiki/Microcode , mais ils font comme si il n'y avait que certains PCs ...

Tu penses que je devrais lire ça ?
http://www.lsv.ens-cachan.fr/~goubault/CoursProgrammati...

Merci encore ..!
a b L Programmation
8 Avril 2009 21:19:54

Citation :
Est-ce que ça te parle une unité fonctionnelle de recherche ? (IFU = Instruction Fetch Unity) pour éviter à l'UAL d'incrémenter IP.

Non, c'est pas juste la première étape du pipeline? peut-être que cette unité s'occupe de la gestion du cache (je n'en sais rien).

Pour tout ce qui est microcode, c'est juste que toutes les instructions ne sont plus directement cablées électriquement comme lorsqu'on fait un processeur basique. Par exemple, il existe l'instruction REP MOVSB qui permet le transfert de tout un bloc mémoire (adresses indiquées dans ESI et EDI pour une taille mise dans ECX). Dans ton programme exécutable, tu as juste l'instruction REP MOV SB (F3 A4), et le micro-processeur doit exécuter du microcode pour effectuer l'opération.
C'est forcément spécifique mais aussi général pour les micro-processeurs. :) 

Le but des micro-instructions est d'avoir un ensemble d'instructions cablées de base et d'avoir des instructions plus complexes faisant appel en interne aux instructions plus simple, et de réunir plusieurs types d'instructions.
8 Avril 2009 21:37:05

Hmm, pas très facile.
J'ai repéré deux liens que je vais lire quand j'aurai du temps.

Au moins, la mémoire cache c'est compréhensible, quoi que .. :D  (je commence à lire, y a tout à noter .. :p  )

Je te posterai le mini-tuto que je fais sur les circuits logiques : Je sais pas si j'ai le droit de mettre des images qui sont pas de moi dans le tuto (même en précisant) ?
9 Avril 2009 12:39:05

Hey CRicky,

Dis-moi, tu sais toi sur quelles bascules sont basées les mémoires actuelles ?

Apparemment, Flip-Flop, c'est dépassé.
On m'a suggéré FLik FLak, mais je n'ai rien trouvé à part des jouets pour enfants ..

Merci ..!
9 Avril 2009 16:36:34

Hello,

+-------+

Couche Circuits Logiques


Après avoir étudié le fonctionnement global d'un PC en étudiant son architecture matérielle générale, voyons progressivement et brièvement les diverses couches présentes dans un PC. Il faut voir les couches comme une sorte de concept :

Les instructions compliquées/sophistiquées des langages de haut niveau, sont traduites par le passage de diverses couches pour "finalement" obtenir des instructions simples compréhensibles par le processeur, représentées par la couches des circuits logiques, à la limite du matériel/logiciel car les instructions sont logiques, mais les actions sont physiques. Encore plus bas, nous aurions la couche Physique au sens pur, c'est à dire le fonctionnement physique des éléments d'un PC, ce qui nous n'aborderons pas.
Pour un article plus exhaustif et précis sur les circuits logiques : http://www.lsv.ens-cachan.fr/~goubault/CoursProgrammati...
Pour plus d'informations sur les renseignements physiques, vous pouvez consulter ce site : http://comelec.enst.fr/tpsp/eni/poly/enich8.html#x13-16...

Nous n'aborderons que très brièvement cette couche, car je ne suis que débutant en la matière et que mine de rien, ça devient vite compliqué.

Les PORTES :

La porte logique est l'élément le plus élémentaire d'un circuit ben.. logique. Une porte est constituée d'un assemblage de transistors (ce qui peut expliquer le nombre impressionnant [de dizaines à centaines de millions] de transistors dans une puce). Les transistors servent d'interrupteurs binaires du fait qu'ils "possèdent" une tension d'entrée et une tension de sortie notamment. En effet, un circuit logique admet deux valeurs : Un signal entre 0 et 1 Volt pour le 0 binaire (comme quoi le binaire, ce n'est qu'une manière logicielle d'interpréter des signaux électriques) et un signal entre 2 et 5V pour le 1 binaire.
Les portes logiques sont donc de minuscules circuits électriques. Le temps de traversée d'une porte est de 1 à 10 nanosecondes.

Comme vous pouvez vous en douter, les portes logiques on un rôle selon justement leur aspect logique. Elles permettent, selon leur nature, de transformer une ou plusieurs tension d'entrée en une tension de sortie (différente ou non). Introduit comme cela, les portes logiques peuvent paraître tout à fait anodines, mais ce n'est pas du tout le cas !

Il y a plusieurs types de portes logiques, on en distinguera 4 principales.
Mais l'opérateur NOT pouvant s'appliquer à chaque porte, on obtient au final 7 portes logiques (en considérant que ce ne sont pas des combinaisons de portes logiques).
Pour chaque porte, nous verrons la schématisation, et l'équivalent sous forme d'opération booléenne.

  • NOT (NON)
  • AND (ET)
    - NAND (NON-ET)
  • OR (OU)
    - NOR (NON-OU)
  • XOR (eXclusive OR = OU EXCLUSIF)
    - XNOR (eXclusive NOT OR = NON-OU EXCLUSIF)

    NOT : Probablement la porte logique la plus simple, son rôle est d'inverser la tension d'entrée (on peut l'appeler inverseur).
    Autrement dit, si la tension d'entrée est équivalente à un 0 binaire, la tension de sortie sera équivalente au 1 binaire.

    La porte NOT est schématisée de cette manière :



    L'opération booléenne est la suivante : (soit A la tension d'entrée en considérant bien-sûr que la tension n'a que deux états possibles puisque booléen) .

    AND : Cette porte logique (selon les tensions de transistors en série qu'elle reçoit, de 1 à x..) retourne un 1 binaire uniquement si tous les transistors sont à 1.

    La porte AND est schématisée de cette manière :



    L'opération booléenne est la suivante : A . B (. est assimilé à la multiplication, dans une multiplication, le 0 remporte toujours quels que soient les autres facteurs et leur nombre).

    NAND : Cette porte logique retourne les résultats inversés de la porte AND. (à cause du NOT)

    La porte NAND est schématisée de cette manière :



    L'opération booléenne est la suivante : ("produit" qui subit une inversion)

    OR: Cette porte logique (selon les tensions de transistors en série qu'elle reçoit, de 1 à x..) retourne un 0 binaire uniquement si tous les transistors sont à 0.

    La porte OR est schématisée de cette manière :



    L'opération booléenne est la suivante : A + B (comparable à une addition puisque le 1 remporte sur le 0)
    Attention ! J'ai bien dit comparable et non c'est une addition. On ne peut dire que c'est une addition du fait que la tension ne peut prendre que deux états.
    De plus en addition binaire, deux 1 additionnés donnent un 0


    NOR : Cette porte logique renvoie le résultat inversé de la porte OR.

    Elle est schématisée de cette manière :



    L'opération booléenne est la suivante :

    XOR : Cette porte logique est très importante et très utilisée en programmation (Assembleur) pour réaliser des opérations très simples.
    Elle retourne le 0 binaire quand les tensions d'entrées sont équivalente, et le 1 binaire quand elle sont différentes.

    Cette porte est schématisée de la manière suivante :



    L'opération booléenne est la suivante : (là, en fait, c'est une véritable addition binaire).

    XNOR : Cette porte retourne le résultat inversé de la porte XOR.

    Schématisée de la manière suivante :



    Opération booléenne est la suivante :

    Comme vous pouvez le remarquer, chaque porte a une forme bien spécifique. On remarque par exemple que le NOT est représenté par un . à la sortie de la porte. (inverse le résultat)

    L'algèbre booléen étudié est très connu et s'appelle officiellement l'Algèbre de Boole.

    Pour chaque porte logique, l'algèbre de Boole est schématisée sous la forme de tableaux que voici. Ces tableaux sont appelés tables de vérité.
    Je ne mets que les tables des 4 portes, les autres ne sont pas trop dures à trouver, non ? o_O



    Voilou. Maintenant, vous vous imaginez qu'en combinant ces portes, et en faisant des circuits, on arrive à des circuits "intelligents", puisqu'il y a beaucoup de possibilités de combinaisons. On peut également facilement faire des calculs de ce type : A . (A + B) ou autres ;) 

    Voici une courte démonstration intéressante en assembleur que j'ai trouvé sur Wikipedia (rappelons que EAX est le registre accumulateur) :


    Le but est ici d'assigner la valeur 0 au registre EAX. Le premier code est plus rapide, car il fait directement un XOR entre EAX et EAX. Puisque EAX=EAX, le résultat est 0.

    1. xor eax, eax


    Dans le deuxième cas, le code assembleur effectue un déplacement de la valeur 0 vers le registre EAX, ce qui fait perdre du temps (le déplacement).

    1. mov eax, 0


    Un autre exemple simple.
    Comme vous avez pu le voir ici, on peut facilement calculer la distance de Hamming en regardant quels bits diffèrent, respectivement selon les positions des bits bien-sûr.

    Prenons par exemple le mot A : 00111100 et le mot B : 01011010.
    Possible de calculer la distance de Hamming de ces deux mots avec des portes ? Et ben oui :red:
    En calculant visuellement, on voit que la distance est de 4.
    Et si je vous dis que la distance est égale à la somme des XOR des différents bits ?

    Partant de la position 0 (c'est à dire, le bit le plus à droite).
    (0 XOR 0 = )0 +( 0 XOR 1 = )1 + (1 XOR 0 = )1 + (XOR 1 XOR 1 = )0 + (1 XOR 1 = )0 + (1 XOR 0 =)1 + (0 XOR 1 = )1 + (0 XOR 0 = )0 = 4 !

    Vous allez me dire : "oui mais l'addition ? o_O", nous allons voir plus loin que ce n'est qu'un assemblage très simple de portes logiques.

    Voyons maintenant des exemples d'applications.

    Les bascules :

    Juste pour commencer, il faut savoir qu'un circuit intégré est une plaquette de silicium sur laquelle sont intégrées les portes du circuit. La plaquette est encapsulée dans un boîtier avec sur les côtés des broches permettant les connexions électriques. Le meilleur rendement étant obtenu lorsqu'il y a le plus de portes possible pour le moins de broches possible, ce qui minimise d'une part le coût du produit. Le circuit bénéficie donc de plus en plus d'interconnexions entre les portes.

    Les bascules sont à l'origine des mémoires, le but d'une mémoire étant de mémoriser un bit, variable d'entrée précédemment transmise.
    La mémoire sert à stocker les instructions à exécuter ainsi que les données. On construit alors des mémoires d'un bit à partir de circuits à bascules.

    Il existe deux types de bascules de base, les bascules latch, et les bascules flip-flop, bien que maintenant, l'informatique ait encore évolué et les mémoires sont plus perfectionnées et utilisent autre chose.
    Les bascules latch réagissent aux niveaux (bas, haut) de l'horloge alors que les bascules flip-flop réagissent aux transitions/fronts de l'horloge.
    Rappelons la schématisation des ondes d'une horloge : /'\_/'\_/ : Ici les niveaux sont respectivement l'underscore (niveau bas) et l'apostrophe (niveau haut) [ces niveaux sont de même durée pour une horloge symétrique], les transitions, sont les slash et backslash.

    Il ya plusieurs sous-types de bascules : RS, D, JK ... Ces bascules diffèrent par leur "architecture", c'est à dire le type de portes qu'elles utilisent et par leurs interconnexions. Mais le principe est généralement le même, le produit étant finalement le résultat de signaux et d'états.

    Ensuite, pour faire des mémoires un peu plus grandes, on connecte entre elles ces différentes bascules, en imposant une hiérarchie : par exemple, des signaux qui activent telle ou telle ligne, dans le cas de mémoire x * y bits. (3 mots de 4 bits par exemple)

    Note : Les Buffers sont des interrupteurs pouvant s'ouvrir ou se fermer en quelques nanosecondes. C'est un circuit à trois états : Il peut générer un 1, 0 ou rien : un état flottant. Ces buffers sont des amplificateurs de puissance, dans la mesure où ils peuvent commander simultanément plusieurs entrées de portes.

    Je ne mettrai pas de schéma de bascules ici, car c'est assez compliqué, et il faut faire entrer en jeux les signaux de l'horloge etc. Une introduction théorique suffira je pense.
    Juste pour vous montrer la structure globale d'une mémoire, voici une image provenant de http://www.lsv.ens-cachan.fr.



    Ici, les signaux sont représentés par des traits pointant sur le circuit.

    Quelques circuits :

    Maintenant, nous allons tout de même voir quelques circuits "intelligents", produits d'assemblage de portes logiques, pour au final vous faire un cadeau : vous montrer le schéma très simplifié d'un UAL 1 bit, vous savez l'unité qui fait les calculs très simples pour le Processeur. :) 
    Note : Les images sont extraites du livre "Architecture des Ordinateurs" d'Andrew Tannenbaum. Je me voyais mal redessiner avec Paint les circuits suivants.

    Voyons un premier circuit très intéressant : le décodeur.
    Le but de ce circuit, est d'accepter un nombre à n bits en entrée, qu'il utilise pour sélectionner une seule des 2^n lignes de sortie.
    En résumé, selon le "mot" reçu, telle ligne de sortie sera activée (mise à 1), qui appellera par exemple une fonction x.



    Ici, on a un donc un décodeur qui accepte un mot de 3 bits, et qui propose 2^3=8 lignes de sortie. Telle ligne de sortie est activée (mise à 1) si et seulement si une combinaison précise des entrées est respectée. C'est donc du filtrage. Très intéressant pour l'UAL par exemple.

    Voilà maintenant un autre circuit vraiment très simple et qui pourtant donne un résultat précis, c'est un comparateur, ici, on prend l'exemple d'un comparateur 4 bits, c'est à dire un comparateur qui reçoit deux mots de 4 bits. Il compare chaque bit avec des portes XOR qui renvoient donc 0 si les deux bits comparés sont égaux. Les 4 résultats de XOR sont routés vers une porte NOR qui renvoie 1 si tous les bits d'entrées sont à 0, ce qui est le cas uniquement si les deux mots sont identiques.



    Voyons maintenant enfin un autre circuit simple dont nous commencé à parler au début : L'additionneur.
    Si vous connaissez un peu la logique binaire, alors il est très facile de remarquer qu'une porte XOR permet de faire des sommes puisqu'elle renvoie 1 quand les deux bits sont différents et 0 quand les deux bits sont égaux. Sauf que dans l'histoire = 01b + 01b n'est pas égal à 00b, mais à 10b. Il y a une retenue !
    Et bien, il suffit simplement d'ajouter un autre porte .. Une porte qui renverrait 1 seulement si les deux bits d'entrées font 1, bon et bien on a trouvé la porte manquante : AND ! On peut donc faire une ébauche d'additionneur (demi additionneur) avec une porte XOR et une porte AND.



    Mais un additionneur de ce type ne gèrerait pas des chiffres plus grand (les bits des positions intermédiaires), car ils ne possèdent aucune entrée représentant la retenue qui provient du bit de droite précédent. Il faut donc recourir à un additionneur complet. Un additionneur complet ne prend donc plus deux bits d'entrée, mais 3 (2 bits à additionner plus la retenue précédente !), et en sortie le résultat et la retenue (comme le demi-additionneur).
    Donc, pour faire un additionneur 8 bits, il te faut 1 demi-additionneur 1 bit et 7 additionneurs 1 bit pour faire circuler les retenues d'un additionneur à un autre. Pour le premier bit à ajouter, il n'y a pas de retenue en entrée, donc un demi-additionneur suffit. Dans ce cas, on appelle ce circuit un addionneur à propagation de retenue.



    Voilà un additionneur complet.

    Enfin, nous allons voir à quoi pourrait ressembler un UAL très simple d'un bit, que j'espère, vous allez comprendre.



    Le décodeur ici sert à définir l'opération qui va être entreprise par l'UAL. Une addition, un NOT, ET, NOR .. On peut donc commencer à construire une unité intelligente à partir de portes logiques banales. Les circuits actuels sont bien entendu bien plus complexes, sophistiqués, mais le principe de base n'en est pas moins le même !

    [hr/]

    Les schémas des portes ont été prise sur WikiPedia.
    Merci à CRicky )

    ++++-------++++

    Yop,

    Merci de faire des commentaires.

    J'ai peur de dire des bêtises pour l'additionneur. Mais j'ai lu que l'additionneur complet est deux demi-additionneurs , or , je ne vois pas en quoi il est plus complet que le demi-additionneur ?
    Pour les mémoires actuelles, toujours basées sur du flip-flop ? J'ai lu que non .

    Merci pour les commentaires et suggestions !
    a b L Programmation
    9 Avril 2009 20:21:38

    Pour les images, elles sont libres (du coup ton document devrait être libre, à voir selon les droits des images).

    Pour les bascules, je ne sais pas.

    Pour les demi-additionneurs, je t'ai déjà expliqué. :p 
    En fait un demi-additionneur 1 bit prend en entrée les deux bits à ajouter, et en sortie le résultat et la retenue
    Un additionneur 1 bit prend en entrée les deux bits à ajouter et la retenue précédente (donc 3 bits à ajouter), et en sortie le résultat et la retenue.
    Donc, pour faire un additionneur 8 bits, il te faut 1 demi-additionneur 1 bit et 7 additionneurs 1 bit pour faire circuler les retenues d'un additionneur à un autre. Pour le premier bit à ajouter, il n'y a pas de retenue en entrée, donc un demi-additionneur suffit.

    pour la mémoire, ça dépend de quelle mémoire tu parles. ;) 

    Je lirai ta doc plus tard.
    9 Avril 2009 21:29:43

    Hello,

    J'ai compris pour l'addionneur merci.
    Donc si on a un nombre de 423135135131 bits, il faudra un nombre impressionnant d'additionneurs :o 

    Dommage pour le schéma, on ne voit pas les trois bits d'entrées (par exemple les deux autres bits), ça embrouille plus qu'autre chose, je trouve, non ?

    Où veux-tu en venir pour la mémoire ? (par rapport à ma doc ou une question que je t'ai posée?)

    Merci, à la prochaine pour les commentaires.
    J'arrive sur la fin du chapitre MicroArchitecture, pas aisé à comprendre, je vais avoir du mal à faire mon résumé ..
    a b L Programmation
    10 Avril 2009 20:05:24

    Citation :
    Donc si on a un nombre de 423135135131 bits, il faudra un nombre impressionnant d'additionneurs :o 

    Pas forcément ;) 
    Avec 7 additionneurs 1 bit et 1 demi-additionneur 1 bit, en fait, tu fais un demi-additionneur 8 bits. Si tu fais un additionneur complet 8 bits, tu peux lui donner en entrée un bit de retenu. Du coup, tu peux enchainer autant d'additions pour effectuer un très grand additionneur. Le seul problème est qu'il y a un cycle par calcul de paquets de 8 bits.
    Par exemple, si l'on veut additionner 32 bits, tu découpe en 4 paquets de 8bits.
    Pour l'addition: 0xEFFFFFFF + 0x01000001
    Cycle 1: A=FFh, B=01h, Re=0 => Somme4 = 00h, Rs=1
    Cycle 2: A=FFh, B=00h, Re=1 => Somme3 = 00h, Rs=1
    Cycle 3: A=FFh, B=00h, Re=1 => Somme2 = 00h, Rs=1
    Cycle 4: A=EFh, B=01h, Re=1 => Somme1 = F1h, Rs=0
    Resultat: Somme=0xF1000000, Rs=0
    Evidemment, plus ton additionneur est physiquement grand, plus tu limites le nombre de cycles pour faire des gros calculs.
    Tu peux créer du microcode pour faire les calcul de grand nombres. ;) 

    Citation :
    Dommage pour le schéma, on ne voit pas les trois bits d'entrées (par exemple les deux autres bits), ça embrouille plus qu'autre chose, je trouve, non ?

    si, sur le schéma, tu as bien A, B et Re en entrée, et Somme et Rs en sortie.
    On voit bien que comme je l'avais démontré:
    Somme = A XOR B XOR Re
    Rs = ((A XOR B) AND Re) OR (A AND B)

    Citation :
    Où veux-tu en venir pour la mémoire ? (par rapport à ma doc ou une question que je t'ai posée?)

    Je veux dire que si c'est du dual channel, il faut voir les fronts montants et descendants.
    10 Avril 2009 21:47:39

    Hello CRicky,

    Wouh, t'as l'air plutôt à l'aise en maths/logique :p 

    Vu que je veux comprendre pour pouvoir le faire partager (sinon c'est idiot d'écrire si on comprend pas ...), pour ceci :

    Somme = A XOR B XOR Re
    Rs = ((A XOR B) AND Re) OR (A AND B)

    Je comprends tout à fait la somme, ben, logique quoi.
    En revanche, RS, c'est la retenue des trois entrées, ou de tout l'additionneur ?
    SI c'est juste la retenue des trois entrées, j'aurais dit :
    (A XOR B) AND Re ou (A XOR AND)
    et pour une méga retenue finale des deux demi-additionneurs :
    ((A XOR B) AND RE) et là je pige pas trop le OR.
    Parce qu'en fait, si il y avait deux retenues, donc deux 1. il faudrait pas plutôt faire à nouveau un XOR et un AND (au cas où il y a bien deux retenues positives ?)
    Je m'embrouille .. snif :( 

    Citation :
    Du coup, tu peux enchainer autant d'additions pour effectuer un très grand additionneur.

    Je me disais bien qu'il doit bien y avoir une limite. J'ai également lu un truc sur les calcules à virgules flottantes (mantisse et exposant) pour raccourci le nombre avec intervalle et bornes, mais c'est un peu compliqué je trouve.

    Par contre, tu as sûrement très bien expliqué :

    Citation :
    Du coup, tu peux enchainer autant d'additions pour effectuer un très grand additionneur. Le seul problème est qu'il y a un cycle par calcul de paquets de 8 bits.

    Mais d'un coup, je ne parviens pas à comprendre ceci directement.
    Par ex, je me dis : "Et qu'est-ce qui additionne les résultats intermédiaires entre eux" ?

    J'avais également lu ça dans le livre "retenue anticipée" ou quelque chose du genre.

    Encore merci !
    Je voulais poser deux-trois autres questions sur autre chose, mais, je te demanderai plus tard (pas envie de te surbooker avec mes questions ;)  )

    Bonne soirée
    a b L Programmation
    11 Avril 2009 12:38:40

    Pour l'additionneur 1 bit, alors je vais détailles tous les calculs .:) 

    D'abord, on prend un simple demi-additionneur: A, B entrée qui donne SommeTemp, RsTemp en sortie.
    On a SommeTemp = A XOR B (0+0 = 0, 0+1 = 1, 1+0 = 1, et 1 + 1 = 0 avec une retenue)
    et RsTemp = A AND B (la retenu pour le cas 1+1, sinon pas de retenue)

    Maintenant, je veux ajouter la retenue de l'additionneur 1 bit (Re). Donc on additionne SommeTemp, RsTemp et Re. Pour ça je décompose tous les cas possibles (ce qui est le début de ton raisonnement).
    1 er cas: RsTemp = 0
    Si notre calcul précédent donne RsTemp = 0 (c'est-à-dire que A et B ne sont pas tous les deux à 1), alors SommeTemp + RsTemp + Re = SommeTemp + 0 + Re = SommeTemp + Re.
    Donc, c'est un simple ajout de 2 entrées: un demi-additionneur suffit en prenant A'=SommeTemp et B'=Re.
    Comme on sait calculer le résultat d'un demi-additionneur, on a:
    Somme' = A' XOR B'
    Rs' = A' AND B'
    Donc, en remplaçant A'=SommeTemp et B'=Re:
    Somme' = SommeTemp XOR Re
    Rs' = SommeTemp AND Re
    Donc, en remplaçant SommeTemp = A XOR B, on obtient:
    Somme' = A XOR B XOR Re
    Rs' = (A XOR B) AND Re


    2 ème cas: RsTemp = 1
    C'est le cas où l'on a la retenue dans l'addition A + B, donc c'est le cas A=1 et B=1 qui donne SommeTemp = 0 et RsTemp = 1
    Dans ce cas, le résultat du demi-additionneur est 01b + 01b = 10b = (RsTemp, SommeTemp)b
    On veut toujours additionner Re, mais cette fois-ci c'est SommeTemp qui est égal à 0, car en additionnant 2 bits, on ne peut jamais avoir une somme et une retenue à 1.
    Donc, en fait notre addition (sur 2 bits maintenant) est (RsTemp, SommeTemp)b + (0,Re)b = 10b + (0,Re)b
    Donc, notre addition est maintenant:
    (Rs", Somme")b = 10b + (0,Re)b = (1,Re)b car 1+0=1 et 0+Re = Re
    Donc, pour notre deuxième cas:
    Somme" = Re
    Rs" = 1


    Factorisation des 2 cas
    - Pour la somme:
    cas 1) Somme' = (A XOR B) XOR Re
    cas 2) Somme" = Re
    Dans le cas 2, c'est le cas où A = 1 et B = 1, donc si on calculait (A XOR B) XOR Re, on obtiendrait (1 XOR 1) XOR Re = 0 XOR Re = Re, ça tombe bien, c'est justement Somme"
    Dans dans le cas 2, Re est aussi égal à (A XOR B) XOR Re.
    Donc:
    cas 1) Somme' = (A XOR B) XOR Re
    cas 2) Somme" = (A XOR B) XOR Re
    Donc, on le même calcul dans les cas, alors on généralise pour tous les cas:
    Somme = (A XOR B) XOR Re

    - Pour la retenue:
    cas 1) Rs' = (A XOR B) AND Re
    cas 2) Rs" = 1
    Dans le cas 2, c'est le cas où A = 1 et B = 1, donc si on calculait (A XOR B) XOR Re, on obtiendrait (1 XOR 1) XOR Re = 0 XOR Re = Re. Et là et bien, notre calcul sert à rien, puisque ça donne pas Rs" :) 
    Le cas 2 c'est lorsque A = 1 et B = 1, et le cas 1 c'est le reste donc non(A = 1 et B = 1)
    Donc, en fait, le cas 2 c'est lorsque A AND B = 1, et le cas 1 c'est lorsque NOT(A AND B) = 1
    cas1 <=> c1 = NOT(A AND B) = 1
    cas2 <=> c2 = A AND B = 1
    Evidemment, on a c2 = NOT(c1) (les cas sont bien distincts)
    on utilise ce masque binaire pour regrouper les cas:
    Rs = (c1 AND Rs') OR (c2 AND Rs")
    Pour le cas1, c1 = 1 et c2 = 0, donc on a bien Rs = Rs'
    Pour le cas2, c1 = 0 et c2 = 1, donc on a bien Rs = Rs"

    En remplaçant c1 = NOT(A AND B) et c2 = A AND B, on obtient:
    Rs = (NOT(A AND B) AND Rs') OR (A AND B AND Rs")
    En remplaçant Rs" = 1, on obtient:
    Rs = (NOT(A AND B) AND Rs') OR (A AND B AND 1) = (NOT(A AND B) AND Rs') OR (A AND B)
    En remplaçant Rs' = (A XOR B) AND Re, on obtient:
    Rs = (NOT(A AND B) AND (A XOR B) AND Re) OR (A AND B)

    On va simplifier la partie de gauche. Je pose Z = NOT(A AND B) AND (A XOR B), et on a donc:
    Rs = (Z AND Re) OR (A AND B)

    Pour simplifier Z = NOT(A AND B) AND (A XOR B), c'est simple, je fais une table de vérité:
    A B Z
    0 0 0 (car A XOR B = 0, donc le AND va forcément faire 0)
    0 1 1 (car A XOR B et A AND B = 0)
    1 0 1 (car A XOR B et A AND B = 0)
    1 1 0 (car A XOR B = 0, donc le AND va forcément faire 0)
    Donc, on remarque que Z est en fait A XOR B

    Qu'est-ce qui m'a fait pensé à poser Z = NOT(A AND B) AND (A XOR B) ?
    C'est simple, on a résultat complexe avec seulement 2 entrées, et comme il n'y a que 2 entrées, il ne peut y avoir que 4 (2^2) possibilités (la table de vérité), donc une formule plus simple était fortement probable.

    Donc, on reprend Rs et on remplace Z = A XOR B, et on obtient:
    Rs = ((A XOR B) AND Re) OR (A AND B)

    Conclusion:
    Pour un additionneur complet 1 bit prenant en entrée A, B et la retenue précédente Re, le résultat avec retenue est:
    Somme = (A XOR B) XOR Re
    Rs = ((A XOR B) AND Re) OR (A AND B)

    a b L Programmation
    11 Avril 2009 12:56:44

    Citation :
    Je me disais bien qu'il doit bien y avoir une limite. J'ai également lu un truc sur les calcules à virgules flottantes (mantisse et exposant) pour raccourci le nombre avec intervalle et bornes, mais c'est un peu compliqué je trouve.

    En informatique, l'infini (que ce soit dans l'infiniment grand ou l'infiniment petit) n'existe pas.

    Pour les virgules flottantes, il y a un encodage particulier puisqu'on est limité là aussi (généralement sur 4 octets, 32bits).
    C'est lorsqu'on sait comment est codé un flottant (float) et qu'on sait programmer en C, que l'on peut pleinement apprécier le calcul de l'inverse de la racine carrée d'un flottant (1 / rac(x)) dans le moteur de Quake3 (avec le nombre magique 0x5f3759df):
    1. float InvSqrt (float x){
    2. float xhalf = 0.5f*x;
    3. int i = *(int*)&x;
    4. i = 0x5f3759df - (i>>1);
    5. x = *(float*)&i;
    6. x = x*(1.5f - xhalf*x*x);
    7. return x;
    8. }


    Citation :
    Mais d'un coup, je ne parviens pas à comprendre ceci directement.
    Par ex, je me dis : "Et qu'est-ce qui additionne les résultats intermédiaires entre eux" ?

    Quand tu découpes en morceaux, tu n'as qu'un bit de retenue à faire passer entre les morceaux.

    11 Avril 2009 18:04:30

    Hi CRicky,

    Waou ! o_O

    Merci pour le calcul détaillé, pfouuu (j'ai passé du temps dessus ^^) !

    Sinon tu as vu quelque chose de faux dans le reste du mini-tutoriel ?
    Pas/plus inexact ?

    ---++----+++------+++++-----------

    J'aurais 2-3 question sur mes lectures d'hier et d'aujourd'hui si ça ne te dérange pas.
    Ne t'inquiète pas pour la longueur, c'est juste des extraits de texte ;) 

    1) Il parle à un moment des données non numériques en disant qu'elles sont distinguées par des instructions ISA spécifiques (dois-je comprendre que l'ASCII est interprété en temps réel par une instruction différente pour interpréter l'Unicode, en admettant qu'il n'y ait pas d'intervention de la part de l'OS).

    Et puis tout d'un coup, sans prévenir, il dit "les valeurs booléennes sont également d'une grande importance". Et puis là il part sur les deux valeurs d'un booléen et après il dit : "[...] Mais dans la pratique, on utilise à cet effet des octets ou des mots parce que les bits individuels ne disposent pas de leur propre adresse et sont par conséquent difficiles à manipuler. Convention blalba. [...] Ainsi, on emploiera les 32 bits d'un même mot pour stocker 32 valeurs. Connue sous le nom de table de bits, cette structure de données est relativement fréquente. On s'en sert pour assurer le suivi des blocs d'espace libre sur un disque. Si ce dernier est constitué de n blocs, la table de bits contiendra n bits."
    C'est normal que je vois strictement aucun rapport avec le début pour différencier les types de données ?

    2) ça parle d'adressage :
    "À l'instar de la méthode précédente (adressage immédiat), celle-ci (adressage direct) est limitée à certaines utilisations : étant donné que l'instruction contient toujours la même adresse, la valeur de l'opérande peut changer, mais pas son emplacement en mémoire. Ainsi, cette approche ne peut être utilisée qu'avec les variables globales, dont les adresses sont connues au moment de la compilation. [...]"
    Je capte pas la logique qu'il veut faire passer là :p .
    par ex, l'adressage immédiat qui comprend directement l'opérande (forcément une constante) dans son champ d'adresses, ça me paraît tout à fait logique. Mais là : 1) pourquoi toujours la même adresse, 2) l'histoire des variables globales ?

    3) Plus tard, il prend un exemple de format d'instruction qu'il dit avec deux adresses (je dois comprendre je suppose deux champs d'adresse en tant qu'opérande), or il met dans une adresse un "mode" (à la rigueur celui-là on s'en fout), un registre et un offset. Donc je dois conclure que dans un opérande (champ d'adresse), il peut y avoir un registre ET un offset ?
    Exemple , on pourrait avoir un truc du style :
    MOV AX+0xF2, 65
    En gros, un champ d'adresse peut être un composé ? (adresse mémoire ou registre + constante ou + offset etc ?)
    C'est juste une hésitation là sinon je comprendrai dans les deux cas ;) 

    Au final, en ayant lu tout l'adressage. Le jeu d'instruction est défini par un ensemble d'opcode avec une certaine orthogonalité OpCode/mode d'adressage, c'est bien ça ?

    4) J'ai rédigé une dizaine de lignes sur les Ring (il en a parlé pendant un paragraphe), je peux te montrer ?

    Merci Beaucoup ...!
    a b L Programmation
    11 Avril 2009 19:38:44

    Citation :
    Sinon tu as vu quelque chose de faux dans le reste du mini-tutoriel ?

    Non.

    1) tu es sur un trop haut niveau, l'unicode ce n'est que côté OS: le processeur ne lit pas l'unicode.
    Il te parle de la façon de manipuler les données. Lorsque tu as des infos booléenne à manipuler, comme en mémoire tu manipule des octets, tu regroupes tous ces flags dans le même octets.

    2) C'est l'explication des pointeurs en C (une fois compilé), ça dit juste qu'à l'exécution de ton programme, une variable globale, sera stockée à une adresse mémoire, et tu manipules le contenu de cette adresse mémoire.
    exemple: tu programmes un jeu vidéo en assembleur, et tu as une variable "score" pour avoir le score du jeu. En langage machine, il n'y a plus de notions de variable nommée, c'est tout en adresse mémoire. Après compilation, la variable score devient une adresse relative au segment de données (par exemple 0x00000010). Pour lire ou écrire ton score (il peut changer), tu va utiliser le contenu de la mémoire à l'adresse relative 0x00000010. Pour faire +5 au score, tu dois faire:
    ADD [0x00000010], 5
    (en asm x86, [] signifie le contenu de l'adresse indiquée).
    5 est constant, on ne passe pas par un adressage mémoire
    [0x00000010] est variable, on passe par la mémoire dans le segment de données (DS).

    Après le 5 est dans l'instruction, donc aussi en mémoire finalement, mais dans le segment de code (CS), alors on peut le modifier, mais s'il l'on modifie, on modifie l'instruction du programme (méta-programmation) lorsque le registre IP repassera sur l'instruction, alors on ne fait généralement pas. :) 

    2) oui, on peut y mettre des offsets
    MOV AX, 1000h => met 1000h dans le registre AX (c'est on adresse de la variable)
    MOV [AX], 65 => met 65 en mémoire à l'adresse indiquée dans AX soit à l'adresse 1000h
    MOV [AX+2], 72 => met 72 en mémoire à l'adresse 1002h
    Au final, en mémoire, il y aura à partir de l'adresse 1000h:
    65 00 72 00
    C'est là qu'on voit l'intérêt du little endian:
    Si tu veux lire le mot à l'adresse 1002, tu prends 2 octets à partir de 1002h (soit 72 00), ce qui te donne 0x0072.
    Si tu veux lire l'octet de ta variable tu reste sur l'adresse 1002h et tu ne prends qu'un octet (72), ce qui donne 0x72. En big endian, il aurait fallu lire à l'adresse 1003h.

    Je te renvoie sur la doc de nasm:
    http://www.posix.nl/linuxassembly/nasmdochtml/nasmdoca.html#section-A.102
    On voit pour le MOV la liste des instructions selon les tailees et l'accès (registre, mémoire ou immédiat).
    En plus, tu as la correspondance en langage machine.
    12 Avril 2009 14:39:31

    Salut,

    1) D'accord. Mais concrètement, que dois-je retenir de cette manipulation des données non numériques ?

    Par exemple, dans le paragraphe juste avant, il parlait des données numériques, en disant qu'on pouvait utiliser tant de bits (32,64 par exemple) selon que l'entier soit signé ou non, que ce soit un nombre à virgule flottante. Simple précision, ou double précision.

    2) D'accord, j'ai compris. En gros, il parle de variables globales pour dire variable qu'on trouve dans un programme en C par exemple (voire en batch).
    Donc l'adresse de la variable ne change pas. Oki, merci, c'est bien ça ?
    Juste un truc qui me questionne , exemple :
    Si je créais une variable long (32 bits il me semble, désolé, ça fait longtemps que j'ai pas fait du C, sinon je peux prendre l'exemple en batch).
    Long var=mavariablefaitplusde32bits, où est le sens du long dans la mesure où il est censé indiquer une limite de place pour la variable ?
    Si je fais par ex : var = 65123, admettons qu'elle prenne x cases mémoire, si je retire la moitié, donc nombre beaucoup plus petit, y aura-t-il de l'espace mémoire libéré ?
    Je me posais également la question de savoir si la mémoire était partagée entre instructions et données, mais il en parlera peut-^etre dans la couche OS.

    3) D'accord, en fait, je suis bête, c'était logique, puisque dans la logique, l'opérande avant la virgule est une destination, et celle d'après l'origine, enfin dans un certain cadre. ça pourrait aussi être des choses à comparer bien-sûr;

    Le lien est peut-être un peu compliqué pour moi, mais je le regarderai c'est sûr.
    Tu entends bien instructions ISA par langage machine ?
    Pour le moment, je ne vois pas de différence avec l'assembleur, même dans les exemples qu'il donne (livre);
    Enfin, le truc c'est qu'il parle d'adressages comme si c'était pour la couche ISA, masi quand il montre un exemple, c'est en ASM, normal/logique ?

    Thank you so much
    C'est reparti pour la lecture!..
    a b L Programmation
    12 Avril 2009 15:45:51

    1) il définit juste les différents types de variables qu'on utilise (char, unsigned char, short, unsigned short, int, long, float, double...).

    2) oui les variable dans les programmes compilé (le batch est particulier puisque c'est de l'interprété).
    Les adresses des variables globales sont bien fixes, ce sont les adresses des variables dynamiques qui ne le sont pas (dans ce cas, le programmeur manipule les adresses avec les pointeurs).

    Un unsigned long fait toujours 32 bits et est limité à des nombres de 0 à 2^32 (environ 4 milliards)
    Un long (signé) fait toujours 32 bits et est limité à des nombres de -2^31 à 2^31 - 1

    le "var = 65123" n'existe pas, car toute donnée a une taille prédéfinie. Le typage dynamique que l'on peut voir dans certains langages (généralement interprétés) associe aussi un type (avec taille) à une variable, mais il le fait implicitement (on ne le voit pas, mais il y a bien une limite que l'interpréteur peut changer si besoin).

    Pour la mémoire, code, données, pile... sont mis en mémoire leur segment sont indiqués dans des registres.

    3) En fait l'assembleur se traduit directement en langage machine: à une instruction assembleur correspond une instruction ISA. L'assembleur est le langage le plus proche de la machine, il permet d'avoir un truc plus lisible pour notre cerveau. :) 
    12 Avril 2009 17:25:55

    Hi,

    1) D'accord;
    2) Ok, la variable dynamique, c'est quoi concrètement ?
    Là dans ma tête, variable globale = variable qu'on crée dans les programmes = variables à adresse fixe.
    Sinon oki, il va parler de la segmentation dans une cinquantaine de pages je crois.
    Donc pour le moment, je vais retenir. variable globale = fixe.
    3) Oki. Tu as un exemple ? (pas trouvé sur le net) Il montre le jeu d'instruction du Pentium 4 et tout dans le livre, mais ça me semble bien être de l'assembleur puisqu'on retrouve MOV, ADD, INC etc.

    --

    - À un moment, il parle des instructions de contrôle de boucle. Pas grand chose de nouveau en parlant des tests en début ou fin de boucle.
    Et il dit : "Les premières versions du FORTRAN spécifiaient que toutes les boucles devaient être exécutées au moins une fois pour permettre l'utilisation systématique de ce code. Mais en 1977, même la communauté fortran a reconnu que l'économie d'une instruction de branchement par boucle ne justifiait pas le risque d'obtenir des réponses erronées à certaines boucles"
    Dans la première phrase, il sous-entend par une utilisation systématique, les prédictions de branchement ? (couche microarchitecture)

    -- Il parle des instructions E/S (intéressant) avec les E/S programmées avec un contrôleur DMA qui génère des interruptions une fois un ensemble de petites opérations terminée, par exemple, l'écriture de X mots à l'écran via le clavier.
    C'est l'exemple qu'il prend.
    Deux mini-questions que je me suis posé :
    ~ Il parle de registre de données et de registres d'état de périphérique d'E/S, par ex, le clavier ou l'écran, mais il ne dit pas où ils se trouvent.
    Extension du périphérique relié à un contrôleur DMA par un bus ? Ou alors (ce qui semblerait plus logique), ces registres font parti du contrôleur du périphérique E/S ? Le contrôleur DMA n'étant pas spécifique à un E/S à ce que j'ai cru comprendre.
    ~ Il dit que malgré que ce soit une très bonne méthode, il y avait l'histoire des vols de cycle (UC qui doit se mettre en pause pour laisser un accès "total" aux E/S qui ne tolèrent pas de délais [pour pertes de données si je me souviens bien du début du livre]). Or, justement, au début du livre, on a vu vers la fin, que vu le nombre de BUS, ce n'était plus un problème (donc logiquement pas de vols de cycles). Qu'en penses-tu ?

    +++++++++++

    Pas très pressé, mais je mets quand même au cas où tu as du temps pour y répondre aussi.

    J'ai commencé à rédiger un petit truc sur les Ring (inspiré de notre discussion bien-sûr) :

    Citation :
    Les Rings, qu'est-ce ?


    Le Ring, terme anglais "très" utilisé pour désigner un "Anneau de Protection" est en fait un niveau de privilèges accordé par le Processeur.
    Il existe quatre niveaux de privilèges : 0, 1, 2 & 3, mais seules les deux limites sont réellement utilisées, donc le 0 et le 3.
    On peut dériver la formule en parlant de "Mode".

    Le Ring0, ou encore Mode Système ou Mode Kernel (Noyau), représente le niveau le plus privilégié, celui qui donne un accès total aux fonctions du processeur.
    Pour être un peu plus clair, n'importe quelle instruction peut être exécutée, et n'importe quel registre peut être utilisé (pas totalement vrai, car tous les registres ne sont pas visibles et tangibles par le développeur à défaut de l'être de la couche micro-architecturale [voir architecture d'un PC]).
    Ce niveau de privilèges est uniquement accordé au Système d'exploitation, ou plus exactement à son noyau/kernel.
    Quand un objet se trouve dans ce mode, on peut dire qu'il se trouve en Kernel-land.

    Note : Un Registre est une petite mémoire de 32bits ou 64bits (selon votre type de processeur) interne au processeur qui sert à stocker des instructions, des états, des résultats de calculs, des adresses (pointeurs) etc.

    Le Ring3, ou encore Mode Utilisateur représente l'opposé, c'est-à-dire, le niveau le moins privilégié. Ce Mode/niveau bloque l'accès à certaines instructions et certains registres de contrôle critiques afin d'éviter qu'un programme malicieux puisse corrompre le système tout entier.
    Ce niveau de privilèges est le vôtre, celui de Windows en tant qu'interface avec l'utilisateur, celui des sessions (System comprise). Rappelons que les sessions représentent une hiérarchie de niveau de privilège codée dans l'OS, indépendamment du Processeur. Désolé de vous décevoir en vous annonçant que votre compte Administrateur ou même System n'est pas dieu tout puissant :red:
    En effet, comme dit plus haut, le Ring ne dépend pas de l'OS, il est attribué par le Processeur. Pour être plus précis, ces niveaux sont contrôlés par les bits contenus dans un Registre communément appelé PSW (Program Status Word), disponible dans un mode hybride mi-système mi-utilisateur qui contient notamment des bits utilisés par l'UC, appelés bits de condition, et également des indicateurs de niveau de priorité [...] et des champs qui décrivent le Mode machine. Compliqué hein :III
    Quand on se trouve dans ce ring3, on parle également d'user-land.

    Pour faire un petit résumé :

    - Les sessions (et tout ce qu'elles démarrent), les logiciels manipulant l'OS, les programmes applicatifs que vous utilisez (ou non) etc. se trouvent en user-land (ring3).
    - Le noyau du système d'exploitation, lui se trouve en ring0 (Kernel-land). On peut également, par extension, y associer les drivers qui démarrent au boot, et les services qui y accèdent.


    Vois-tu des erreurs ?

    Un ami m'a dit : "alors le registre du ring 0 c'est le cpl, current process level ou un truc dans le style tu regardera sur le net
    et c'est un registre de deux bites qui se situe dans le registre CS si j'ai bonne memoire, c'est les deux bites de poids faible du registre CS"
    J'ai regardé sur le net, et n'ai rien trouvé. Je pensais que le registre PSW était "universel". Ce n'est pas lui ?
    Peut-être une différence d'architecture (j'ai partiellement pris ça du livre)
    Un autre contact m'a également dit que le Ring0 n'était pas/plus le plus haut privilège. Il m'a parlé de je ne sais plus quoi, avant que le DD tourne. ça te dit quelque chose ?


    Merci..
    a b L Programmation
    12 Avril 2009 19:03:33

    Citation :
    la variable dynamique, c'est quoi concrètement ?

    c'est lorsque la mémoire est allouée dynamiquement par le programme.
    Par exemple, si dans un programme, tu as une structure arborescente, et que l'utilisateur veux créer un nouvel élément, tu va allouer de la mémoire pour créer ce nouvel élément (malloc en C, new en C++).

    Pour la correspondance, le lien de nasm te donne tout. ;) 
    Par exemple, si je prends la ligne:
    Citation :
    MOV reg16,imm16 ; o16 B8+r iw [8086]

    Et que je prends pour exemple MOV AX, 0123h
    on aura donc pour l'instruction B8+numéro du registre (en A.2.1, on nous indique que AX c'est le registre 0, donc B8+0=B8)
    et la valeur en little endian: 23 01
    Donc l'instruction sera B8 23 01
    Le passage du MOV AX, 0123h vers B8 23 01 est simple, et pour l'inverse, lorsque l'instruction est de B8 à BF, on voit dans les docs que c'est un MOV reg 16, immediat 16.

    Avec cette doc, tu dois pouvoir décompiler ma signature à la main. :p 

    Citation :
    Et il dit : "Les premières versions du FORTRAN spécifiaient que toutes les boucles devaient être exécutées au moins une fois pour permettre l'utilisation systématique de ce code. Mais en 1977, même la communauté fortran a reconnu que l'économie d'une instruction de branchement par boucle ne justifiait pas le risque d'obtenir des réponses erronées à certaines boucles"

    Qu'est-ce qu'il vient parler du fortran :D 
    Je connais pas les version plus anciennes que le F77, peut-être fallait-il faire un test avant de faire la boucle, bref, c'est un problème de compilateur fortran.

    Pour les E/S, je ne sais pas, j'imagine, que oui, il y a un contrôleur et que les ports sont mappés sur les contrôleurs. Pour les vols de cycles, je pense que c'est juste dû au blocage matériel s'il y en a.

    "deux bites" <= On est toujours dans l'informatique là ? :D 

    Bon je rouvre un vieux bouquin pour pas dire de betises :) 
    CPL=Current Privilege Level
    Le CPL est le niveau de privilège en cours (dans le ring), et est effectivement stocké dans les 2 bits de poids faible de CS. On a 4 niveaux, donc c'est codé sur 2 bits (de 0 à 3).
    Dans les tables de descripteurs (GDT et LDT), les niveaux des segments y sont décrits par le DPL (Descriptor Privilege Level) qui est aussi 2 bits indiquant le niveau (de 0 à 3).
    Un code (référencé par CS qui contient le niveau du code, par exemple ring 1) ne peut accéder qu'aux segment de données dont le niveau est moins restrictif (ring > ou = 1).
    Pour accéder aux données en changeant de segment, on modifie le registre DS. Donc, lorsque le registre DS est modifié, le processeur lit dans sa table le DPL à quel niveau correspond le nouveau segment, et le compare avec le CPL (issu de CS).
    Si DPL < CPL, c'est à dire que l'on veut permettre au code d'accéder à des données dont le niveau de privilège est plus restrictif, alors le processeur arrête l'exécution et déclenche une exception.

    Après il y a les Call Gate, pour permettre quand même aux application d'accèder aux fonctions systèmes, la gestion des interruption...
    un petit lien intéressant (la version française ne l'est pas):
    http://en.wikipedia.org/wiki/Segment_selector
    12 Avril 2009 20:06:44

    Hey,

    Ouh, ça devient complexe pour mon petit cerveau, mais ne nous décourageons pas ! :-P

    Ok pour les var dynamiques, je me souviens un peu de Malloc en C.
    Après pour la correspondance Assembleur-ISA, je dois t'avouer que je n'ai rien compris :D  Faut que je bosse plus le sujet je pense (avoir fini le livre au moins). Pas encore assez à l'aise, et je n'ai encore rien lu sur la Segmentation, ce qui ne devrait pas tarder remarque. Mais merci quand même, et cela me resservira par la suite !

    Citation :
    Avec cette doc, tu dois pouvoir décompiler ma signature à la main. :p 

    En prenant un verre, un paquet d'aspirines, et un pistolet à côté de moi, peut-être :D 

    Oki pour le Fortran, quand j'essaierai de rédiger un truc sur la MicroArchitecture, je te ressortirai le passage dont je te parlais pour que tu vois ce que je voulais dire ;) 

    Citation :
    y a un contrôleur et que les ports sont mappés sur les contrôleurs

    Qu'entends-tu par ports ? Données, registres ..?

    Citation :
    "deux bites" <= On est toujours dans l'informatique là ? :D 

    J'aurais du corrigé avant de poster :D 

    Hmm pour le CPL. Merci ..! J'ai mis les liens en favoris que je re-regarderai une fois la segmentation vue ;) 

    Donc le registre PSW, il existe pas ?
    Ou c'est juste un registre qui stocke les états d'un résultat (retenue, signe, overflow etc.)

    Et aussi, juste un truc que j'ai remarqué dans le tuto que j'avais fait :

    "- En deuxième lieu, on définit les opérandes. Ici, par exemple, on a un Registre (AX) et une adresse mémoire (0013h). En effet, une opérande peut faire partie d’une instruction, car ici, MOV AX est une instruction. Ce qui fait qu’en fait, une fois traduit, l’instruction n’a qu’un seul paramètre (opérande) puisque l’instruction a une opérande par défaut."
    C'est pas faux non ? C'est MOV l'instruction et AX et 0013h sont les opérandes, c'est bien ça ?

    THX.



    a b L Programmation
    12 Avril 2009 21:09:11

    PSW (Program Status Word), c'est effectivement le registre des flag pour les intel.

    MOV AX, 0013h
    B8 13 00
    B8, c'est l'instruction + la première opérande
    13 00, c'est la seconde.

    MOV AX, 0013h => B8 13 00
    MOV CX, 0013h => B9 13 00
    MOV DX, 0013h => BA 13 00
    MOV BX, 0013h => BB 13 00
    MOV SP, 0013h => BC 13 00
    MOV BP, 0013h => BD 13 00
    MOV SI, 0013h => BE 13 00
    MOV DI, 0013h => BF 13 00

    En fait, si tu veux, B8 13 00 en binaire c'est 10111xxx 00010011 00000000
    avec xxx le numéro de registre. Donc, on peut dire que l'instruction c'est les 5 premiers bits du premier octet, la première opérande, les 3 bits de poids faible du premier octet.
    Mais bon, comme on découpe par octets, on voit plutôt dans le sens: premier octet B8 + numéro de registre, puis l'opérande.
    C'est qu'une question de point de vue. :) 
    12 Avril 2009 21:16:05

    Ah d'accord ! Merci !
    Je vais dire que ça dépend du point de vue ;) 

    Au fait, "ouf", j'ai vu que plus loin dans le livre il parlait de la pagination, segmentation et de ces descripteurs de table, donc je ne vais pas être perdu finalement (enfin j'espère).

    Et si on relaxait deux minutes, je peux te poser deux-trois questions sur un service par rapport à son fichier ? Des questions pas compliquées :) 
    13 Avril 2009 21:44:31

    Yop,

    Je commence à gratter sur la couche ISA. Quelques questions :

    1) Dans le livre (sans expliciter), andrew disait en prenant l'exemple du pentium qu'il y avait 16000 (et des brouettes) segments d'adresse de 0 à 2^32-1 disponibles et que l'OS n'en utilisait qu'un, qu'est-ce que cela signifie ? De plus, en ayant avancé dans la couche OS, j'ai vu qu'apparemment il y avait plein de segments (ceux d'un programme particulier) et les généraux décrits par les descripteurs de table.

    2) Une autre chose me tamponne, on parle de registre 32 bits, par exemple EAX. Mais aujourd'hui, les processeurs sont majoritairement physiquement des 64 bits, pourquoi parle-t-on alors de registre 32 bits ?
    Taille variable ?

    3) Je voulais parler du little endian comme tu l'avais expliqué plus haut:

    "Sur l'architecture INTEL, les octets disposent de leur propre adresse et les mots, généralement de 32 bits (DWORD) sont stockés au format Little Endian (l'octet de poids faible se trouve à l'adresse de poids faible, en fait l'offset (qui traduit un déplacement) ira dans le sens inverse qu'en Big Endian.)" en m'appuyant sur ce que tu m'avais donné en exemple plus haut, j'ai commencé à faire cette image :



    Mais je ne sais pas la compléter, car je ne sais pas si c'est l'adresse qui change de place, la disposition des octets, ou l'offset qui va dans un certain sens

    4) J'ai aussi parlé du mode d'adressage, mais une chose me questionne :

    Quelle est la différence par exemple entre :

    MOV [0xFF], 5
    et
    MOV 0xFF, 5

    Pour moi, comme tu l'avais dit, [...] est le contenu de l'adresse mémoire. En même temps, puisque l'adresse mémoire n'est pas un pointeur, je ne vois alors pas de différence entre les deux.

    5) J'aimerais parler de la pile aussi. Mais la pile, qu'est-ce concrètement ? J'ai regardé sur le net, ils ne le disent pas (Wiki), ni son utilisation spécifique. Pour le moment, je pars sur le point de vue qu'elle stocke des variables locales, et qu'elle est pratique pour faire de petites opérations.

    6) Adressage indexé basé : Mode d'adressage qui consiste à ajouter un ou deux registre et facultativement un offset pour obtenir une adresse mémoire. Un des registre forme la base, et l'autre l'index.
    )> Tu as déjà entendu parler de ça ?

    Merci ..
    14 Avril 2009 20:43:57

    Salut,

    J'ai enlevé les questions sur la Pagination, je vais retravailler dessus plus tard.
    Donc le post est bien réduit, j'ai laissé quelques questions pour la couche ISA, que j'essaie de rédiger .. avec un peu de mal.
    a b L Programmation
    14 Avril 2009 22:10:09

    1) tu parles du système d'adressage en mode protégé ? et tu parles de quel OS ?

    2) Le registre RAX contient EAX qui contient AX qui contient AH et AL
    Voici le registre RAX ans lequel j'ai numéroté les octets avec un total de 8*8 = 64 bits
    +---+---+---+---+---+---+---+---+
    | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
    +---+---+---+---+---+---+---+---+

    RAX (64 bits) = 76543210
    EAX (32 bits) = 3210
    AX (16 bits) = 10
    AH (8 bits) = 1
    AL (8 bits) = 0
    On peut toujours utiliser AH et AL dans nos gros registres. ;) 

    Il y a aussi les registre du MMX.
    http://msdn.microsoft.com/en-gb/library/ms794547.aspx

    3)
    Citation :
    Little Endian (l'octet de poids faible se trouve à l'adresse de poids faible

    il serait plus clair de dire que le premier octet est l'octet de poids faible, parce que adresse de poids faible, je vois pas ce que ça veut dire :p 

    Pour ton image, c'est dans le DWORD qu'il faut inverser: 00 72 00 23. Les adresses ne bougent pas.

    4)
    Citation :
    MOV 0xFF, 5

    Tu sais mettre une valeur dans une valeur ? moi pas et ça n'a pas d'intérêt si ça va pas en mémoire quelque part.
    Bref, le "MOV imm,qqchose" ça veut rien dire et ça n'existe pas.

    5) instructions assembleurs:
    "PUSH valeur" pour mettre une valeur sur la pile
    "POP memoire" pour dépiler la pile et mettre la valeur dépilée dans une mémoire
    si je veux appeler une fonction addition qui a 10 paramètres (0, 1, 2, 3, 4, 5, 6, 7, 8, 9) et qui fait une addition, j'empile les paramètres avant d'appeler la fonction. Celle-ci dépile les parametres, fait l'addition et retourne le résultat dans AX
    1. PUSH 00h
    2. PUSH 01h
    3. PUSH 02h
    4. PUSH 03h
    5. PUSH 04h
    6. PUSH 05h
    7. PUSH 06h
    8. PUSH 07h
    9. PUSH 08h
    10. PUSH 09h
    11. CALL MonAddition

    1. ; Additionnes 10 valeurs de longueurs 1 octet
    2. ; Paramètres sur la pile:
    3. ; - 1ère valeur
    4. ; - 2ème valeur
    5. ; - 3ème valeur
    6. ; - 4ème valeur
    7. ; - 5ème valeur
    8. ; - 6ème valeur
    9. ; - 7ème valeur
    10. ; - 8ème valeur
    11. ; - 9ème valeur
    12. ; - 10ème valeur
    13. ; Retourne le résultat dans AX
    14. ; Modifie les registres AX et BX
    15. MonAddition:
    16. XOR AX, AX
    17. XOR BX, BX
    18. POP AL
    19. POP BL
    20. ADD AX, BL
    21. POP BL
    22. ADD AX, BL
    23. POP BL
    24. ADD AX, BL
    25. POP BL
    26. ADD AX, BL
    27. POP BL
    28. ADD AX, BL
    29. POP BL
    30. ADD AX, BL
    31. POP BL
    32. ADD AX, BL
    33. POP BL
    34. ADD AX, BL
    35. POP BL
    36. ADD AX, BL
    37. RET

    Ma fonction modifie BX, alors si j'avais une valeur dans BX que je voulais garder, que dois-je faire ?
    Et bien il suffit d'empiler BX avant l'empilement des paramètres et de le dépiler après l'appel.

    6) J'imagine que c'est l'adressage par segment : offset.
    par exemple MOV ES:[DI], 10h va écrire 10h à l'adresse de segment ES et d'offset AX. Utile pour écrire en mémoire vidéo.
    14 Avril 2009 23:10:19

    Hello CRicky,

    1) Yop, je t'écris ce qu'il a marqué, mais je ne sais guère si cela va t'aider plus :

    "[...] Correspondant aux programmes utilisateur, le niveau 3 bloque l'accès à certaines instructions et certains registres de contrôle critiques afin d'éviter qu'un programme malicieux puisse corrompre le système tout entier. Les niveaux 1 et 2 sont, quant à eux, rarement utilisés.

    Sa mémoire étant divisée en 16 384 segments allant chacun des adresses 0 à 2^32-1, le Pentium 4 dispose d'un adressage gigantesque. Toutefois, la plupart des systèmes d'exploitation (y compris Uniw et toutes les versions de Windows) ne prenant en charge qu'un seul segment, les applications ne "voient" qu'un seul espace d'adressage de 2^32 octets, souvent partiellement occupé par l'OS"

    2) Ok ;)  Merci.
    3) Bien, j'ai une idée un peu plus claire, j'espère que c'est bon !!

    "Sur l'architecture INTEL, les octets disposent de leur propre adresse et les mots, généralement de 32 bits (DWORD), et sont stockés au format Little Endian (le premier octet est donc l'octet de poids faible [contrairement au big endian]). Dans notre exemple, nous avons stocké le mot 0x00720023 à l'adresse 1000h (ou 0x1000).



    Comme nous l'avions déjà vu, le Little Endian inverse l'ordre des octets dans le groupe d'octets. Par conséquent, pour une lecture en mémoire, si un offset est indiqué, cet offset partira de l'octet de poids faible vers celui de poids fort (contrairement au Big Endian)."

    4, 5) D'accord. En fait, j'illustre les modes d'adressage (enfin j'essaie serait plus exact!). La chose qui m'avait mené à cette hypothèse, et qu'avec un registre, cette opération : MOV AX, 513 ne paraît pas invraisemblable (ou MOV AX, 151Fh).
    Donc pour un registre, je suppose que le [] est réservé pour l'adressage indirect par registre (registre en tant que pointeur) alors que les [] sont obligatoire pour la mémoire, si on veut y inscrire quelque chose. Right ?

    J'avais/ai écrit ça (+ PILE):

    Citation :
    Mode d'adressage :

    Passons aux choses sérieuses :)  Nous avons vu que dans une instruction, les champs d'adresses étaient réservés aux opérandes. La méthode de localisation d'une opérande se fait par adressage. Voyons les différents types d'adressage que l'on peut y trouver.
    Le mode d'adressage est la manière d'interpréter les bits d'un champ d'adresse en vue de la localisation de l'opérande. Notez qu'une instruction peut posséder plusieurs modes d'adressages différents.

    Mode d'adressage relatif aux données :

    Adressage immédiat : Avec ce mode, le contenu de l'opérande est directement placé dans le champ d'adresse, au lieu d'indiquer comment la trouver. L'avantage de ce mode est que l'instruction peut être directement exécutée (pas besoin de faire une lecture/écriture en mémoire par exemple). Ce type d'adressage se limite donc aux constantes.

    Par exemple :
    1. XOR 18, 19

    est un exemple d'adressage immédiat. ici, on lance un XOR sur 18 et 19, ce qui devrait retourner 1.

    Adressage direct : Ce mode spécifie une adresse entière de l'opérande à trouver en RAM ou en ROM par exemple.
    Ce mode est utilisé pour les variables globales dont l'adresse est connue au moment de la compilation. [DIFF var local et var globale ]

    Par exemple :
    1. ADD [0x00FF25DE], 13


    Ici, on a une instruction qui contient à la fois un mode d'adressage immédiat (à droite) et un mode d'adressage direct (à gauche). Ici, comme bien souvent en ASM, l'opérande à droite (opérandes séparées par une virgule) sert d'opérande d'origine, et l'opérande de gauche sert d'opérande de destination.
    0x00FF25DE représente une adresse mémoire, nous voulons additionner son contenu (exprimé avec les crochets : assembleur x86) avec la constante 13, le contenu de l'adresse mémoire sera donc incrémenté de 13.

    Adressage par registre : Cette fois, on spécifie un registre à la place d'une adresse Mémoire. C'est le modèle le plus courant.
    On appelle également ça le Mode registre, ce mode étant bien évidemment, bien plus rapide qu'une adresse mémoire qui requiert un accès en Mémoire.

    Par exemple :
    1. CMP AH, AL

    Cette instruction contient deux opérandes adressées par registre. Ici, on compare la valeur du sous-registre AH et du sous-registre AL.

    Adressage indirect par registre : Cette fois-ci, on va se servir du registre comme un pointeur, sur une adresse mémoire en général.
    Ainsi, cette fois, il faut bien différencier la valeur du registre, et le contenu du registre. Voici un exemple :

    1. MOV AX, 0xFF
    2. MOV [AX], 12


    Dans le premier exemple, nous pouvons dire que nous avons un simple adressage par registre. On copie l'adresse mémoire (seulement l'adresse, pas son contenu, sinon j'aurais mis [0xFF] ;)  ) dans le registre AX. Dans la deuxième instruction, on va mettre 12, non pas dans le registre AX, mais dans l'adresse sur laquelle pointe le registre AX ! C'est là toute la subtilité, le registre devient un pointeur. Si on avait pas mis les crochets autour de AX pour montrer qu'on parlait du contenu, le 12 aurait été inséré dans le registre AX en tant que valeur.
    On a donc une référence à la mémoire, sans que l'instruction n'en contienne, d'où la notion d'indirect.

    Adressage indexé : Il est souvent utile de pouvoir localiser des mots mémoires placés à un distance donnée (Offset) par rapport à un certain registre, ou bien à une certaine adresse mémoire. Avec ce type d'adressage, il devient possible de spécifier en opérande, un registre ou adresse mémoire avec un offset qui indique donc un décalage. En reprenant l'exemple précédent, nous pourrions faire :

    1. MOV [AX+2], 26

    Cette fois-ci, on déplace la constante 26 non pas dans le registre AX plus un offset de 2 (vu que le registre sert de pointeur), mais à une distance de 2 de l'adresse 0xFF, soit 0xFF+2 = 0x101. Donc on aurait pu aussi bien faire :

    1. MOV [0xFF+2], 26


    On pourrait aussi faire une instruction de ce type :

    1. SUB AX, [0xFF]+65


    Ce code, soustrairait le contenu de l'adresse 0xFF + 65 à la valeur contenu dans le sous-registre AX.

    Adressage indexé basé : Mode d'adressage qui exprime une adresse via cette structure : Segment : Offset (nous verrons les segments dans le prochain épisode)

    1. MOV DS:0x0D, 0x60


    Cette instruction va écrite 0x60 à l'adresse du segment DS (Data Segment) d'offset 0x0D.

    Adressage implicite : Cet adressage est dit implicite, car il fait appel à des endroits spécifiques du Processeur, comme la Pile par exemple. Il n'y a alors pas besoin d'exprimer d'adresses mémoire.

    Pour expliquer cet adressage, nous allons exprimer le fonctionnement de la pile.

    Les variables locales sont stockées dans la pile (Stack), elles n'ont donc pas d'adresse absolue. Sur une pile, on trouve ce qu'on appelle des variables locales (mots de 16 bits = WORD), c'est-à-dire, des variables momentanément utilisées, mais on trouve aussi des blocs d'opérandes.. En fait, la pile constitue une structure de données (de bloc de variables locales, bloc d'opérandes) qui suit la loi du LIFO (Last In, First Out) : dernier arrivé, premier sorti. Les derniers éléments ajouté sont les premiers à être enlevés. La pile est très utilisée notamment lors des appels de procédure que nous verrons un peu plus loin. Lors de l'appel de procédure, un ou plusieurs blocs de variables locales est ajouté sur la pile (PUSH), lorsque l'appel est terminé, le bloc est retiré de la pile (POP). Sur certains PCs, un registre référence la base du bloc de variables le plus récent, mais on trouve surtout le célèbre registre (E)SP (Stack Pointer), autrement dit, qui référence le sommet de la pile (mot supérieur des variables locales).

    Pour comprendre le fonctionnement de la pile, on peut l'assimiler à ce qu'on appelle la notation postfixée ou polonaise inverse.
    Lorsqu'on fait une opération, par exemple : (3 x 7) + (4 / 2). <- Notation infixée
    Sur la pile, cela reviendrait, à mettre un 3 (PUSH 3), à ajouter un 7 (PUSH 7, à les multiplier (instruc que je connais pas), à ajouter 4, à ajouter 2, à les diviser, et enfin à additionner les deux résultats obtenus.

    Allez un schéma pour illustrer ça :



    En notation postfixée, l'opération s'écrirait : 37x42/+ <- Comme on peut le remarquer, c'est exactement l'ordre suivi par la Pile.
    En fait, le fonctionnement n'est pas compliqué, comme vous voyez, les instructions sont optimisées pour faire des opérations sur les deux opérandes que l'on a ajouté sur la Pile, on retrouve donc très facilement la notation postfixée, qui indique l'ordre suivi par la pile. Ou l'inverse (selon ce que vous comprenez le mieux ;)  )

    Pourquoi il y a des sauts entre les étapes ? J'aimerais vous dire cycle machine, mais certaines étapes prennent plus de cycles que d'autres ;)  Donc la longueur de mes étapes est variable.
    Et bien en fait, à chaque opération sur les deux opérandes du sommet de la pile, le résultat n'apparaît pas en une étape.


    Je sais qu'il y a des choses encore fausses dans les modes d'adressage donc je préfère avoir ton opinion avant de foncer tête baissée en disant des âneries.
    En ce qui concerne la pile, je ne connais que les instructions IJVM pour les opérations (additions et pop, mul et pop ..) :-S
    Je ne sais pas si ma division en étapes est bonne, je pense qu'il a voulu simplifier dans le livre, donc je ne suis plus sûr de quoi dire précisément sur les étapes intermédiaires.

    Thank you so much ..!
    a b L Programmation
    15 Avril 2009 21:03:21

    1) C'est pas très clair.
    Du temps de l'EMS, on étendait du segment D000 à E000 (en mode réel).
    Bon comme il parle de windows/unix, je pense qu'il parle en mode protégé où l'on a un espace de 0x00000000 à 0xFFFFFFFF avec un découpage en pages. Je ne vois pas ce qu'un "segment" viendrait faire ici. En même temps, je ne connais pas bien les spécificités du P4.

    4) Oui, MOV AX, 513 met 513 dans le registre AX, et effectivement avec [], c'est l'accès mémoire RAM à l'adresse indiquée dans le [] directement ou indirectement par le contenu d'un registre.

    Citation :
    XOR 18, 19

    Non, tu stockes le résultat nulle part en faisant ça, et c'est pour ça que cette instruction n'existe pas.
    XOR Param1, Param2
    fait le caulcul:
    Param1 := Param1 XOR Param2
    Donc le premier paramètre ne peut pas être une valeur immédiate.

    Sur le processeur, la pile est plus simple, il n'y a que des POP et des PUSH. Si tu veux faire une addition sur les 2 éléments sur la pile, il faut faire 2 POP pour récupérer les valeurs, faire le calcul, et faire un push pour remettre le résultat.
    15 Avril 2009 21:57:39

    Saloute,

    1) En effet, il parle de segment sans en avoir fait référence avant.
    3) Le schéma que j'ai fait sur le big/little endian est correct cette fois ? :-P
    4) D'accord. J'ai pas mal bossé dessus et lu et j'ai compris plusieurs autres choses :) 

    Merci :)  Vais corriger ce que je peux déjà. Ensuite je ferai la micro-architecture en conséquence.

    Edit du 16 : 1) J'ai vu que l'équivalent actuel du PSW est le registre des FLAGS.
    Je suis allé ici : http://en.wikipedia.org/w/index.php?title=FLAGS_registe...(computing)
    Et je me demande, FLAGS est-il un gros registre qui contient des sous-registre EFLAGS, RFLAGS ..?

    2) Juste une petite chose.
    Il est possible de spécifier une adresse autrement qu'en hex.
    Par exemple, MOV AX, [140]
    Le 140 est-il cette fois considéré comme en décimal ? (donc traduction en binaire par le PC ou le microprogramme, je ne sais pas vraiment). Ou bien est-ce de l'octal ? Merci.
    Je me rends bien compte que si on avait fait MOV AX, 140, le 140 n'aurait pas été pris comme une adresse mais comme une constante, donc le registre n'aurait pas été un pointeur.

    3) Vais essayer de représenter les étapes intermédiaires de la pile. Juste pour savoir, les instructions multiplier et diviser sont MUL et DIV. Sur le net, j'ai trouvé des OPCode pour faire par 2^n mais ce n'est pas tellement ce qui m'intéresse.
    D'ailleurs, je cherchais justement les OPCode pour faire un décalage et une rotation, il semblerait que pour le décalage, ce soit (ah retrouve plus .. :p )

    4) Alors, voilà une question qui me semble importante.
    Dans mon doc, je voulais montrer un exemple d'utilisation de la pile pour un appel de proc théorique :

    "Bien, comme je l'avais promis, je vais donner un exemple très court et très simple de l'utilité de la pile dans ces appels. Comme nous l'avons constaté, les appels de procédure peuvent tout à fait modifier le contenu de plusieurs registre etc. Comment faire pou réinitialiser ensuite ? Stocker dans la pile ! (comme expliqué juste au-dessus).
    Voici un exemple tiré de CCM concis et parlant, AX et BX étant deux registre, on considère ici que l'appel de procédure va modifier ces deux registres (trois lignes du milieu).

    1. PUSH AX
    2. PUSH BX
    3. MOV AX, [0x0140]
    4. ADD BX, AX
    5. MOV [0140h], BX
    6. POP BX
    7. POP AX


    Avec les deux premières lignes, on stocke AX puis BX sur la pile. Au final, SP = adresse pile de BX. Là viennent les modifications des registres par la procédure : stockage du contenu de l'adresse 0x140 dans AX. Puis, on ajoute AX à BX, et enfin on écrit le contenu de BX à l'adresse 0140h (ou 0x0140). Maintenant, il est l'heure de restaurer les registres à l'état auxquels ils étaient avant l'appel. Pour, ce on dépile ce qu'on avait mis sur la pile. En suivant la loi du LIFO, BX ayant été mis le dernier, on l'enlève le premier et naturellement on le met dans BX (qui avait été modifié par l'appel). Comme vous pouvez le remarquer, on ne spécifie pas ce qui est sur la pile, cela pointe automatiquement sur le sommet de la pile : SP (un peu comme si on faisait MOV BX, [SP] au détail près que l'instruction originale décrémente SP également, ce qui est tout à fait logique/légitime.) Note : SP est bien-sûr un pointeur, puisqu'il contient l'adresse du sommet de la pile.
    Note additive importante : Lorsqu'on fait un POP registre, il y a dépilement d'un mot de taille égale au registre dans lequel on le stocke. Par exemple, POP AX, va dépiler 2 octets = 16 bits de la pile, car AX est un sous-registre de 16 bits. Si on faisait POP EAX, 32 bits = 4 octets seraient dépilés pour être stockés dans EAX.

    Ainsi, dans notre exemple, POP AX est équivalent à :

    1. MOV AX, [SP]
    2. SUB SP, 0x10


    On déplace le contenu du pointeur dans AX (16 bits), et on soustrait au contenu de SP, c'est-à-dire, l'adresse de SP, la taille du mot, 16 bits soit 0x10 en hexadécimal.
    Si vous ne comprenez, référez-vous au schéma de la mémoire en haut du chapitre pour comprendre."
    La logique semble correcte, en revanche, du point de vue mémoire, si je prends ce schéma qui illustre une mémoire 32 bits (même si aujourd'hui, il me semble qu'elles soient toutes 64 bits)



    Pour moi un problème se pose. Si je retire de la pile un mot de 32 bits, ou multiple de 32 (64, 128 ..), aucun problème.
    En revanche, si je retire 16 bits par exemple. On m'a dit qu'il fallait décrémenter SP de 16 bits (même si ça se ferait automatiquement avec pop). Or, comment puis-je décrémenter une moitié d'adresse.
    En admettant que j'ai par exemple adresse 1000h et 1004h comme dans mon exemple. Si je retire 16 bits, je suis à 1002 h. Or, cela ne traduit plus une adresse mais un offset, là est mon soucis.. Vois-tu ce que je veux dire ? Merci


    Merci !

    Au fait, serait-ce possible que je t'envoie un cadeau pour te remercier ?
    Tu m'as tellement apporté, je te dois la quasi-totalité de mes compréhensions. À l'heure qu'il est, je serais peut-être encore en train de me poser des questions sur l'Hexadécimal. J'aimerais beaucoup te remercier. Tu as du passer vraiment beaucoup de temps à m'expliquer certaines choses, et ce sont des choses que je n'oublierai pas. (Au passage, je te remercie dans chacun de mes articles, ce qui est tout à fait normal !).
      • Premier
      • Précédent
      • 6 / 8
      • 7
      • 8
      • Plus de pages
      • Suivant
      • Dernier
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6 / 8
        • 7
        • 8
    Tom's guide dans le monde
    • Allemagne
    • Italie
    • Irlande
    • Royaume Uni
    • Etats Unis
    Suivre Tom's Guide
    Inscrivez-vous à la Newsletter
    • ajouter à twitter
    • ajouter à facebook
    • ajouter un flux RSS