Hello World en 15 lignes et plus (pt3)

Par aliu, 12 mars, 2024

Salutations à tous,

Je vous souhaite tous une très bonne journée ou soirée! Aujourd'hui, nous allons continuer de l'article précédent et couvrir les appels système et les modes d'adressage.

Apelles Système

Donc pour commencer, un appel système, c'est quoi?

Simplement dit, c'est ce qui permet à un utilisateur de faire des requêtes pour des services du système opérateur de l'ordinateur (OS).

Ou en d'autres mots, les appels système sont des APIs pour l'interface entre l'espace utilisateur et kernel (noyau).

Des exemples seraient les appelle:

sys_write(mov eax,4) et sys_exit(mov eax,1) qu'on a utilisé dans les exemples de mes articles précédents.

Il y a six registres qui peuvent stocker ces arguments d'appel système et ils sont:

  • EBX
  • ECX
  • EDX
  • ESI
  • EDI
  • EBP

Tous ces registres prennent les arguments consécutifs qui commencent après le registre EBX.

Voici des exemple qui prend une entrée utilisateur et qui l'affiche après:

  section .data                                      ;Data segment 


  ;On déclare ici les contenus texte qu'on veut afficher à l'utilisateur
  userMsg db 'Please enter a number: ' ;Ask the user to enter a number
  lenUserMsg equ $-userMsg               ;The length of the message
  dispMsg db 'You have entered: '
  lenDispMsg equ $-dispMsg                

  section .bss                                         ;Uninitialized data
  num resb 5
    
  section .text                                         ;Code Segment
  global _start
    
  _start:                                                  ;User prompt
  ;affiche le message qui demande à l'utilisateur d'entrer un nombre
  mov eax, 4                                          ;system call number (sys_write)
  mov ebx, 1                                          ;file descriptor (stdout)
  mov ecx, userMsg                               ;segment compteur qui va prendre le userMsg déjà déclaré
  mov edx, lenUserMsg                          ;taille de userMsg déclarée
  int 80h                                                ;interrupt appelé

  ;Read and store the user input (lis et mets en stockage l'entrée utilisateur)
  mov eax, 3                                          ;system call number (sys_read)
  mov ebx, 2
  mov ecx, num                                      ;segment compteur qui va prendre le num déjà déclaré
  mov edx, 5                                           ;5 bytes (numeric, 1 for sign) of that information (initialisation: on donne 5 bytes à l'information)
  int 80h                                                 ;interrupt appelé
    
  ;Output the message 'The entered number is: '
  mov eax, 4                                           ;system call number (sys_write)
  mov ebx, 1                                           ;file descriptor (stdout)
  mov ecx, dispMsg                                ;segment compteur qui va prendre le dispMsg déjà déclaré
  mov edx, lenDispMsg                          ;taille de dispMsg déclarée
  int 80h                                                ;interrupt appelé

  ;Output the number entered
  mov eax, 4                                          ;system call number (sys_write)
  mov ebx, 1                                          ;file descriptor (stdout)
  mov ecx, num                                     ;segment compteur qui va prendre le num déjà déclaré
  mov edx, 5                                         ;5 bytes (numeric, 1 for sign) of that information (initialisation: on donne 5 bytes à l'information)
  int 80h                                               ;interrupt appelé
  
  ; Exit code
  mov eax, 1                                          ;system call number (sys_exit)
  mov ebx, 0
  int 80h                                               ;interrupt appelé

Ce qui sort ressemble à cela:

Please enter a number:
1234  
You have entered:1234

Modes d'adressage

En X86, ou juste avec la plupart des langages assembleurs, les instructions nécessitent des opérandes pour être traitées.

Le processus ressemble un peu comme ça:

Adresse d'opérande fourni où est l'endroit --> Cet endroit, c'est où les données vont être traité.

Certaines instructions nécessitent les opérandes ci-mentionnés (1 à 3) et certaines autres pas du tout.

Quand une instruction nécessite deux opérandes, la première est la destination et la deuxième est la source.
Cette source contient soit les données à être envoyé immédiatement ou l'adresse de ladite donnée.

Généralement, ces données sources restent inchangées après l'opération.

Maintenant, pourquoi est-ce que je vous explique tous cela? C'est parce que les modes d'adressage, dépendamment de quel type, contiennent un opérande alors que d'autres plusieurs.
J'ai donné un petit résumé d'usage en haut juste pour vous familiariser sur ce sujet.

Donc,

Il y a trois modes d'adressage:

  • Adressage de registre

Avec celui-ci, le registre contient un opérande. Dépendant de l'instruction, le registre a la possibilité d'être le premier opérande, la deuxième, ou les deux.

Par exemple:

MOV DX, TAX_RATE   ; Register in first operand
MOV COUNT, CX       ; Register in second operand
MOV EAX, EBX       ; Both the operands are in registers

  • Adressage immédiat

Pour ce type, un opérande immédiat a une valeur constante ou une expression. 
Quand une instruction avec deux opérandes utilise cet adressage immédiat, le premier opérande peut devenir un registre ou un emplacement de mémoire, et la deuxième est une constante immédiate.

Ce premier opérande mentionné définit la taille des données.

Par exemple:

BYTE_VALUE  DB  150    ; A byte value is defined
WORD_VALUE  DW  300    ; A word value is defined
ADD  BYTE_VALUE, 65    ; An immediate operand 65 is added
MOV  AX, 45H           ; Immediate constant 45H is transferred to AX

  • Adressage de mémoire

Avec l'adressage de mémoire, il y a deux types: directe et indirecte.

Avec l'adressage direct, une chose à savoir est que quand des opérandes sont spécifiés dans le mode d'adressage mémoire, l'accès direct à la mémoire principal est requis.
Ce moyen d'adressage résulte souvent en un traitement de données plus lent.

Pour localiser l'exact emplacement des données dans la mémoire, on a besoin d'un segment d'adresse de début, et c'est normalement trouvé dans le registre DS et dans une valeur de décalage. Cette valeur de décalage est aussi appelée une adresse effective.

En mode d'adressage direct, la valeur de décalage est spécifiée directement comme faisant partie de l'instruction, et c'est souvent indiqué par le nom de la variable. 
L'assembleur calcule la valeur de décalage et maintien une table de symboles, et c'est cette table qui met en stockage toutes les valeurs de décalage de toutes les variables utilisées dans le programme.

Avec l'adressage mémoire direct, un opérande fait référence à l'emplacement mémoire et l'autre à un registre.

Par exemple:

ADD    BYTE_VALUE, DL    ; Adds the register in the memory location
MOV    BX, WORD_VALUE    ; Operand from the memory is added to register

Avec l'adressage indirect, celui-ci utilise une des habiletés de l'ordinateur qui s'appelle Segment: adressage décalé.

Généralement, les registres de base EBX, EBP (our BX, BP) et les registres d'index DI, SI, qui sont inscrits dans des crochets ([]) pour les références mémoires, sont utilisés à ce but.

L'adressage indirect est utilisé pour stocker des variables qui contiennent plusieurs éléments, par exemple: les arrêts.

Maintenant, disons par exemple qu’un array est stocké dans le registre EBX:

Voici comment un accède à différents éléments de cet array...

MY_TABLE TIMES 10 DW 0  ; Allocates 10 words (2 bytes) each initialized to 0
MOV EBX, [MY_TABLE]     ; Effective Address of MY_TABLE in EBX
MOV [EBX], 110          ; MY_TABLE[0] = 110 //alloue la valeur 110 à MY_TABLE[0]
ADD EBX, 2              ; EBX = EBX +2
MOV [EBX], 123          ; MY_TABLE[1] = 123 //alloue la valeur 123 à MY_TABLE[1]

MOV

Dans plusieurs de mes derniers exemples, vous devez avoir lu que plusieurs instructions possèdent ça:

MOV

Comme début.

Alors, qu'est-ce que c'est?

MOV est utilisé généralement pour bouger une donnée d'un endroit à l'autre.

La syntaxe est:

MOV  destination, source

Et elle a cinq formes de déplacement:

  • MOV  register, register
  • MOV  register, immediat
  • MOV  memory, immediat
  • MOV  register, memory
  • MOV  memory, register

Deux choses à noter par contre sont que un, tous les deux opérandes devraient être la même taille et que la valeur de l'opérande source doit rester la même sans exception.


Maintenant, j'espère que vous avez aimé cet article. Je vous souhaite encore une fois, une bonne journée ou fin de journée!

À plus tard!


«Assembly - Basic Syntax», TutorialsPoint,  https://www.tutorialspoint.com/assembly_programming/assembly_basic_syntax.htm (Page consultée le 9 mars 2024)

«What are system calls in assembly language?», Educative,  https://www.educative.io/answers/what-are-system-calls-in-assembly-language (Page consultée le 9 mars 2024)

«Intel x86 Assembly Language Programming», Bower Tim, CIS 450 - Computer Organization and Architecture, http://www.cs.cmu.edu/afs/cs/academic/class/15213-f02/www/R03/section_b/x86notes.pdf (Page consultée le 10 mars 2024)

Commentaires2

mkessi

il y a 11 mois 1 semaine

Vu comme ça, ça a l'air pénible..

Par contre c'est fou la liberté que tu as avec Assembler sur ta machine, vu que tu intéragis directement avec la mémoire

aouzou

il y a 11 mois 1 semaine

Bonjour, pouvez-vous expliquer la différence entre l'adressage direct et l'adressage indirect en langage assembleur, et si possible donner un exemple concret pour chaque type d'adressage ? merci