J'essaie d'apprendre l'assemblage - X86 dans un environnement Linux. Le tutoriel le plus utile que je puisse trouver est écrire un programme utile avec NASM . La tâche que je me cadre est simple: lisez un fichier et écrivez-le à stdout.
C'est ce que j'ai: p> un problème crucial ici est que le Le tutoriel ne mentionne jamais comment créer un tampon, le Comment puis-je faire cela? P> (A de côté: Après au moins une heure de recherche, je suis vaguement consterné à la mauvaise qualité des ressources pour l'assemblage d'apprentissage. Comment sur Terre utilise-t-il un ordinateur lorsque la seule documentation est le dossier négocié sur le 'net?) p> p> p> bufsize code> variable ou en effet des variables du tout. p>
3 Réponses :
Ohh, ça va être amusant. p>
Le langage de montage n'a pas de variables. Ce sont une construction de langues de niveau supérieur. En langage de montage, si vous voulez des variables, vous les faites vous-même. Montée. Dans les deux sens. Dans la neige. P>
Si vous voulez un tampon, vous devez utiliser une région de votre pile comme tampon (après avoir appelé les instructions de configuration de la pile appropriées) ou utilisez une région sur le tas. Si votre tas est trop petit, vous devrez faire une instruction SYSCALL (un autre INT 80H) pour prier le système d'exploitation pour plus (via SBRK). P>
Une autre alternative consiste à en apprendre davantage sur le format ELF et à créer une variable globale dans la section appropriée (je pense que c'est .Data). P>
Le résultat final de l'une de ces méthodes est un emplacement de mémoire que vous pouvez utiliser. Mais vos seules «variables» telles que vous êtes habituée à partir du monde désigné-merveilleux de C sont vos registres. Et il n'y en a pas beaucoup d'entre eux. P>
L'assembleur pourrait vous aider avec des macros utiles. Lire la documentation de l'assembleur; Je ne me souviens pas d'eux en haut de ma tête. P>
La vie est difficile là-bas au niveau de l'ASM. P>
Je comprends que buf code> est juste un pointeur à la mémoire que j'ai besoin de créer et que je dois demander
bufsize code> de la mémoire du système d'exploitation. Cependant, je ne fais pas comment faire de ces choses et je ne peux pas savoir.
EEGG: MALLOC code> n'est pas réellement un appel système. Vous devez mettre en place un tas. Ceci est fait, comme je l'ai mentionné, avec le
BRK code> et
sbrk code> appels système. Voir
Man 2 BRK CODE>. Vous devez rechercher le numéro d'appel système correspondant à
BRK code> (voir
/usr/include/sys/syscall.h code>), puis faire un
MOV EAX, # code> et
int 80h code> pour l'appeler selon votre modèle SYSCall ci-dessus. Une fois que vous avez fait cela, vous avez un tas à l'adresse que vous spécifiez! Neato!
Ok, apparemment brk code> est un appel système, mais
sbrk code> n'est pas.
sbrk code> semble décidément plus utile. Utiliser Just
BRK CODE> serait possible, si je savais où se trouve dans la mémoire la pause actuelle du programme. Malgré la recherche, je ne sais pas comment le trouver. À la recherche de la source de
SBRK code> (qui enveloppe vraisemblablement
brk code>), je ne peux trouver que Ce , que je ne peux faire ni tête ni queue de.
@eegg Que sbrk code> est l'appel
brk (0) code> et enregistre sa valeur de retour (qui est la pause actuelle du programme). Est ce que ça aide?
Pourquoi gâcher avec brk code> lorsque vous pouvez simplement
MMAP (map_anonymous) code> pour obtenir de nombreuses pages que vous voulez? Ou honnêtement pour un programme de jouet ayant besoin d'un grand tampon, un tampon statique dans le BSS est certainement le choix le plus facile.
Section .BSS CODE> /
MYBUF: RESB 1024 * 1024 * 1024 CODE> Réserves 1GIB. (Et non, vous ne le voulez pas dans
.data code>, qui mettrait des zéros dans le fichier exécutable.) J'adorerais +1 cette réponse pour la bonne partie expliquant les étiquettes vs. Variables de langage de niveau, cependant. Mais les variables statiques font une sorte de carte pour étiqueter + stockage; C'est un stockage automatique qui mesure à REG.
Vous devez déclarer votre tampon dans la section BSS et le bufsize dans les données
section .data bufsize dw 1024 section .bss buf resb 1024
Et si vous ne connaissez pas la taille du fichier, comment faites-vous cela?
La taille est une constante de temps d'assemblage, vous n'avez pas besoin de le stocker en mémoire. (Et dans un mot code> a peu de sens en code 32 bits). Utilisez
buf: resb 1024 code> /
bufsize EQA € -BUF code> Pour que l'assembleur calculera une taille pour vous que vous pouvez utiliser comme immédiat au lieu de devoir charger de la mémoire.
Après l'ouverture de l'appel, la poignée du fichier est dans EAX. Vous déplacez légitimement EAX à EBX, où l'appel à lire le cherchera. Malheureusement, à ce stade, vous avez déjà écrasé avec 3, le syscall pour la lecture. P>
J'ai lu pour résoudre ce problème en recherchant l'équivalent en C, mais tout le tout utilise le package
stdio.h code> au lieu de simplement
Ouvrir code>,
lisez code> et
écrire code>. J'ai même regardé
stdio.h code>, mais les organes de fonction ne sont définis nulle part.
Ouvrir, lire et écrire des appels système. Les corps sont dans le noyau Linux.
Je voulais dire que je cherchais que je cherchais les corps de
fopen code>,
fread code> et
fwrite code>, pour voir comment
Ouvrir code>,
lire code> et
écriture code> sont utilisés.
Les corps des fonctions Wrapper sont à la source de GLIBC.
RE: Ressources d'apprentissage: Stackoverflow.com/tags/x86/info a un tas de liens. Les tutoriels de bonne qualité sont rares, mais réelle la documentation i> est généralement très bonne, notamment les manuels d'Intel et d'AMD, ainsi que la documentation NASM ( nasm.us ). Pour les interfaces OS / Conventions d'appel des appels, Linux dispose d'une page
syscall (2) CODE> Man, et voir le système X86-64 System V ABI Doc en PDF.