...
mov edx,len ;message length
Ce charges edx
avec une sorte de valeur numérique, comme 14 dans ce cas. len
est "EQU" symbole constant, quelque chose comme #define
en C.
mov ecx,msg ;message to write
Cette charge ecx
avec l'adresse du premier caractère (msg
est étiquette, pointant en mémoire).
mov ebx,1 ;file descriptor (stdout)
mov eax,4 ;system call number (sys_write)
int 0x80 ;call kernel
...
msg db 'Hello, world!', 0xa ;our string
Ceci définit 14 octets de mémoire, avec des valeurs 72 ('H'), 101 ('e'), .... Le premier octet est pointé par msg
étiquette (adresse mémoire de celui-ci).
len equ $ - msg ;length of our string
Ceci définit la constante len
visible pendant la compilation. Il ne définit aucun contenu de mémoire, donc vous ne pouvez pas le trouver dans l'exécutable ou pendant l'exécution (à moins d'être utilisé, comme par exemple mov edx,len
, alors il est compilé dans cette instruction particulière bien sûr).
La définition est $ - msg
, le $
dans ce contexte fonctionne comme « l'adresse actuelle », où sera compilé l'octet suivant de code machine définie, donc à cet endroit, il est égal à msg + 14
(je l'espère, je l'ai fait compter le nombre de caractères correctement :)). Et ((msg+14) - msg) = 14
= nombre d'octets définis dans la mémoire entre la définition de len
et l'étiquette msg
.
Remarquez comment j'évite les mots comme variables ou caractères, l'ASM est plus bas niveau, donc les étiquettes en mémoire et octets sont des mots plus précis et j'espère qu'il vous aidera à reconnaître les différences subtiles.
Votre len2 equ $ - len
après la len
ne donc définir la valeur len2
comme (msg+14)
(toujours là dans la mémoire, aucun nouvel octet ajouté len
définition) moins len
qui est 14
, de sorte que vous effectivement défini len2
égal à msg
.
Puis:
mov edx,len2 ;message length
mov ecx,len ;message to write
...
n'appelle sys_write
avec pointeur vers la chaîne égale à 14
(référence mémoire non valide, cette zone de mémoire est interdite au code utilisateur ordinaire) et longueur égale à traiter msg
, qui sera être sur 32b linux très probablement une valeur comme 0x80004000
, soit plus de 2G de caractères à la sortie.
Le sys_write
n'aime pas cela, échoue et renvoie le code d'erreur dans eax
.
Pour quoi que ce soit de sortie à la console avec sys_write
vous devez d'abord écrire dans la mémoire comme ASCII (je pense que UTF8 est prise en charge par défaut dans shell Ubuntu, mais trop paresseux pour vérification) chaîne codée et donner l'adresse sys_write
de cette mémoire , et la longueur en octets (avec la chaîne UTF8 la différence entre les octets et les caractères est importante, sys_write
ne connaît pas les caractères, cela fonctionne avec les fichiers binaires et les octets, donc la longueur est la quantité d'octets). Je ne vais pas écrire de code sur les numéros de sortie, car cela fait plusieurs lignes (implémentation printf
simplifiée) et SO a plusieurs Q + A, mais j'espère que mon explication vous aidera à comprendre ce qui s'est passé et comment Ça marche.
Si vous êtes en train d'apprendre ASM, envisager soit de lier l'clib
d'avoir printf
disponibles, ou mieux encore, utilisez débogueur, et vérifier les valeurs droites dans les registres Débogueur, ne vous embêtez pas avec la sortie de chaîne encore, c'est un peu sujet plus avancé que l'arithmétique initiale, et le contrôle de flux de base et la pile d'exploitation. Une fois que vous serez plus à l'aise avec le fonctionnement de l'instruction de base et la manière de déboguer le code, il sera plus facile d'essayer de sortir les numéros.
Vous pouvez vérifier [** Comment imprimer un numéro dans l'assemblage NASM? **] (https://stackoverflow.com/questions/8194141/how-to-print-a-number-in-assembly- nasm) La réponse courte est que vous écrivez * caractères * à 'stdout'. Un nombre est une valeur décimale, pas une chaîne de caractères que vous pouvez écrire immédiatement, vous devez convertir la valeur entière ou non signée en représentation de son caractère, puis l'écrire dans 'stdout'. –
Par curiosité pour quel système d'exploitation programmez-vous? Les fenêtres? Unix? MacOS? Je demande parce qu'en plus des questions comme ceci souvent les personnes demandant sur SO utilisent des tutoriels pour la plate-forme fausse. –
Merci. J'utilise ubuntu. Par curiosité, quand j'essaie d'imprimer directement le numéro en utilisant stdout, je n'ai rien. Pourquoi n'imprime-t-il rien au lieu d'imprimer des bêtises? –