Comment ouvrir un fichier dans l'assembleur et le modifier?
Je commence à apprendre l'Assembleur et je travaille dans Unix. Je veux ouvrir un fichier et écrire "Hello world".
section.data
textoutput db 'Hello world!', 10
lentext equ $ - textoutput
filetoopen db 'hi.txt'
section .text
global _start
_start:
mov eax, 5 ;open
mov ebx, filetoopen
mov ecx, 2 ;read and write mode
int 80h
mov eax, 4
mov ebx, filetoopen ;I'm not sure what do i have to put here, what is the "file descriptor"?
mov ecx, textoutput
mov edx, lentext
mov eax, 1
mov ebx, 0
int 80h ; finish without errors
Mais quand je compile, il ne fait rien. Ce que je fais mal?
Lorsque j'ouvre un dossier où le fichier descripteur de valeur de retour?
OriginalL'auteur Rama | 2011-11-29
Vous devez vous connecter pour publier un commentaire.
C'est x86 Linux (x86 n'est pas le seul langage d'assemblage, et Linux n'est pas le seul Unix!)...
Le nom de fichier de la chaîne nécessite un 0 octet terminator:
filetoopen db 'hi.txt', 0
2
est leO_RDWR
drapeau de laopen
syscall. Si vous voulez que le fichier est créé si il n'existe pas déjà, vous aurez besoin de laO_CREAT
drapeau; et si vous spécifiezO_CREAT
, vous avez besoin d'un troisième argument qui est le mode d'autorisations pour le fichier. Si vous fouiner dans les C-têtes, vous trouverez queO_CREAT
est défini comme0100
- méfiez-vous du zéro: c'est une octal constante! Vous pouvez écrire les constantes octales dansnasm
à l'aide de lao
suffixe.De sorte que vous besoin de quelque chose comme
mov ecx, 0102o
pour obtenir le droit de drapeaux et demov edx, 0666o
pour définir la permssions.Le code de retour d'un syscall est passé dans
eax
. Ici, ce sera le descripteur de fichier (si l'ouverture a réussi) ou d'un petit nombre négatif, ce qui est un négatiferrno
code (par exemple -1 pourEPERM
). A noter que la convention pour le retour des codes d'erreur à partir d'un raw syscall est pas tout à fait le même que le C syscall wrappers (qui est généralement de retour-1
et définirerrno
dans le cas d'une erreur)......donc, ici, vous devez
mov ebx, eax
première (pour enregistrer leopen
résultat avanteax
est écrasé) puismov eax, 4
. (Vous voudrez peut-être penser à vérifier que le résultat a été positif de la première, et la manipulation de l'absence d'ouverture d'une certaine façon, si elle ne l'est pas.)Manquant
int 80h
ici./usr/include/bits/fcntl.h
sur debian/ubuntu, voici un résumé des constantesOriginalL'auteur Matthew Slattery
Cela dépend de ce que l'assembleur que vous utilisez et si vous vous attendez à l'aide de la C runtime ou pas. Dans ce cas, ce qui semble être le Bonjour tout le Monde, exemple de texte à partir de rosettacode ils sont à l'aide de msna. Étant donné que vous avez un _start champ vous n'êtes pas avoir besoin du runtime C de sorte que vous assemblez à un elfe de fichier de l'objet et de le lier dans un programme:
Vous pouvez maintenant exécuter le
hello
programme.Un peu plus portable de l'exemple qui utilise le runtime C pour faire le travail plutôt que linux syscalls pourrait ressembler à l'exemple ci-dessous. Si vous liez ce que décrit pouvez utiliser
printf
pour l'impression.Pour plus d'informations sur les descripteurs de fichier - lire la
open(2)
page de manuel ou de regarder wikipédia. Il est de savoir comment posix se réfère à ouvrir un flux d'e/s. Dans votre cas, stdout.fopen
/fprintf
pour écrire dans un fichier. (Ou, plus simplement,fputs
si vous n'avez pas besoin de mise en forme.) Ou vous avez besoin de faireopen
etdup2
appels système pour rediriger votrestdout
dans le fichier avant d'utiliser stdioprintf
. L'écriture de l'asm qui utilise plus portable Api semble inutile lorsque la convention d'appel est une plate-forme spécifique (comme pour x86-64). 32-bit Windows et Linux conventions d'appel sont suffisamment proches pour la plupart des choses, à l'exception de Windows utilise_printf
dans le code 32 bits, n'est-ce pas? Mais vous avez oublié de s'assurer de 16 octets de la pile l'alignement avant de lacall
; Système i386 V exige que. (sub esp,8
)OriginalL'auteur patthoyts
Avez-vous lu le Linux Assemblée HOWTO? Il couvre votre question.
Vous pouvez aussi compiler du code C avec
gcc -S -fverbose-asm -O1
et de regarder l'assembly généré.Enfin, je ne pense pas que ça vaut la peine de se beaucoup sur l'assembleur. Le compilateur va sûrement générer un code de meilleure qualité que ce que vous pouvez écrire.
OriginalL'auteur Basile Starynkevitch
C'est un x64 Linux échantillon
.data
comme qword entiers? Vous pouvez utiliserequ
de la même façon que vous êtes pourmsglen
à définir mais il y assembler en mov-immédiate. Aussi, normalement, vous devriez utiliser le mode =0666o
et permettre à l'utilisateur deumask
prendre soin d'autorisations, de sorte qu'ils ont le choix de644
ou 664, or of
600` si ils veulent.Il n'y a également aucune raison de stocker le fichier descripteur de mémoire à tous. Vous pouvez copier à un appel préservé registre (par exemple
ebx
) donc il survit appels de la fonction de tabasser RAX. Ou àedi
si votreprint
fonction utilise un custom convention d'appel comme Irvine32 qui préserve à la RDI. (BTW,int open(const char *pathname, int flags, mode_t mode);
retourne un int, ce qui n'est que de 32 bits x86-64 V ABI. Il est inutile de copier autour de l'ensemble de la 64 bits de registre lorsque vous avez seulement besoineax
. Aussi, cette réponse apparemment, dépend de certainesbasicFunctions.asm
dont vous n'avez même pas liés.OriginalL'auteur Rommel Samanez