Sur Linux, jetez un œil à ceci : il était utilisé pour gérer system_call. Bien sûr, sur un autre système d'exploitation, cela pourrait signifier quelque chose de totalement différent.
par raccourcir longue histoire, ce sont les instructions signifient DO IT for instruction était avant.
Yuda Prawira
2
@YudaPrawira: vous devriez considérer les instructions précédentes comme la configuration d'arguments dans les registres, et int 0x80comme une sorte spéciale de callfonction dans le noyau (sélectionnée par eax).
Peter Cordes
Pourquoi avez-vous dit "était utilisé?" N'est-il plus utilisé?
Liga
129
intsignifie interruption, et le nombre 0x80est le numéro d'interruption. Une interruption transfère le flux de programme à celui qui gère cette interruption, ce qui est une interruption 0x80dans ce cas. Sous Linux, le 0x80gestionnaire d'interruption est le noyau et est utilisé pour faire des appels système au noyau par d'autres programmes.
Le noyau est informé de l'appel système que le programme souhaite effectuer, en examinant la valeur dans le registre %eax(syntaxe AT&T et EAX dans la syntaxe Intel). Chaque appel système a des exigences différentes concernant l'utilisation des autres registres. Par exemple, une valeur de 1in %eaxsignifie un appel système de exit()et la valeur de %ebxcontient la valeur du code d'état pour exit().
Vous pouvez voir ici que ce INTn'est qu'une des nombreuses instructions (en fait la représentation en langage d'assemblage (ou devrais-je dire «mnémonique») de celui-ci) qui existe dans le jeu d'instructions x86. Vous pouvez également trouver plus d'informations sur cette instruction dans le manuel d'Intel disponible ici .
Pour résumer à partir du PDF:
INT n / INTO / INT 3 - Procédure d'appel pour interruption
L'instruction INT n génère un appel au gestionnaire d'interruption ou d'exception spécifié avec l'opérande de destination. L'opérande de destination spécifie un vecteur de 0 à 255, codé en tant que valeur intermédiaire non signée de 8 bits. L'instruction INT n est le mnémonique général pour exécuter un appel généré par logiciel à un gestionnaire d'interruption.
Comme vous pouvez le voir, 0x80 est l' opérande de destination dans votre question. À ce stade, le CPU sait qu'il doit exécuter du code qui réside dans le noyau, mais quel code? Cela est déterminé par le vecteur d'interruption sous Linux.
L'une des interruptions les plus utiles du logiciel DOS était l'interruption 0x21. En l'appelant avec différents paramètres dans les registres (principalement ah et al), vous pouvez accéder à diverses opérations d'E / S, à la sortie de chaîne et plus encore.
La plupart des systèmes Unix et dérivés n'utilisent pas d'interruptions logicielles, à l'exception de l'interruption 0x80, utilisée pour effectuer des appels système. Ceci est accompli en entrant une valeur de 32 bits correspondant à une fonction du noyau dans le registre EAX du processeur , puis en exécutant INT 0x80.
Jetez un œil à ceci s'il vous plaît où d'autres valeurs disponibles dans les tables de gestionnaire d'interruption sont affichées:
Comme vous pouvez le voir, le tableau indique à la CPU d'exécuter un appel système. Vous pouvez trouver le tableau des appels système Linux ici .
Ainsi, en déplaçant la valeur 0x1 vers le registre EAX et en appelant le INT 0x80 dans votre programme, vous pouvez faire en sorte que le processus exécute le code dans le noyau qui arrêtera (quittera) le processus en cours d'exécution (sous Linux, processeur Intel x86).
Une interruption matérielle ne doit pas être confondue avec une interruption logicielle. Voici une très bonne réponse à ce sujet.
Le lien de la table des appels système Linux est rompu = \
Miguel Angelo
1
La plupart des systèmes Unix et dérivés n'utilisent pas d'interruptions logicielles (sauf int 0x80) semble être une façon étrange de le dire. L' int 0x80appel système ABI i386 Linux est extrêmement similaire à l' int 0x21ABI DOS . Mettez un numéro d'appel dans un registre (AH pour DOS, EAX pour Linux) et d'autres arguments dans d'autres registres, puis exécutez une instruction d'interruption de logiciel. La principale différence réside dans ce que les appels système vous permettent de faire (accéder directement au matériel sous DOS mais pas sous Linux), pas dans la façon dont vous les appelez.
Peter Cordes
Voici un lien de table syscall non rompu. syscalls.kernelgrok.com Développez-le simplement pour afficher tous les appels en haut.
ollien le
Lors de l'utilisation de Linux 64bits, vous pouvez voir l'appel système disponible à/usr/include/x86_64-linux-gnu/asm/unistd_64.h
ton
11
Exemple d'appel système Linux exécutable minimal
Linux configure le gestionnaire d'interruption pour 0x80qu'il implémente les appels système, un moyen pour les programmes utilisateur de communiquer avec le noyau.
.data
s:
.ascii "hello world\n"
len = . - s
.text
.global _start
_start:
movl $4, %eax /* write system call number */
movl $1, %ebx /* stdout */
movl $s, %ecx /* the data to print */
movl $len, %edx /* length of the buffer */
int $0x80
movl $1, %eax /* exit system call number */
movl $0, %ebx /* exit status */
int $0x80
Compilez et exécutez avec:
as -o main.o main.S
ld -o main.out main.o
./main.out
Résultat: le programme imprime sur stdout:
hello world
et sort proprement.
Vous ne pouvez pas définir vos propres gestionnaires d'interruptions directement depuis le userland car vous n'avez que le ring 3 et Linux vous en empêche .
Apprenez d'abord à créer un système d'exploitation de chargeur de démarrage minimal et à l'exécuter sur QEMU et du matériel réel comme je l'ai expliqué ici: https://stackoverflow.com/a/32483545/895245
Vous pouvez maintenant exécuter en mode réel 16 bits:
movw $handler0, 0x00
mov %cs, 0x02
movw $handler1, 0x04
mov %cs, 0x06
int $0
int $1
hlt
handler0:
/* Do 0. */
iret
handler1:
/* Do 1. */
iret
Cela ferait dans l'ordre:
Do 0.
Do 1.
hlt: arrêter l'exécution
Notez comment le processeur recherche le premier gestionnaire à l'adresse 0et le second à 4: c'est une table de gestionnaires appelée IVT , et chaque entrée a 4 octets.
Les systèmes d'exploitation modernes fonctionnent en mode dit protégé.
La manipulation a plus d'options dans ce mode, donc c'est plus complexe, mais l'esprit est le même.
L'étape clé consiste à utiliser les instructions LGDT et LIDT, qui pointent l'adresse d'une structure de données en mémoire (le tableau des descripteurs d'interruption) qui décrit les gestionnaires.
int 0x80 est l'instruction en langage d'assemblage qui est utilisée pour appeler les appels système sous Linux sur les processeurs x86 (c'est-à-dire compatibles Intel).
Réponse simple: une interruption, en termes simples, est un événement qui interrompt le processeur et lui dit d'exécuter une tâche spécifique.
Réponse détaillée :
L'UC a une table des routines de service d'interruption (ou ISR) stockées en mémoire. En réel (16 bits) mode, cela est stocké en tant que IVT , ou je nterrupt V ecteur T mesure. L'IVT est généralement situé à 0x0000:0x0000(adresse physique 0x00000), et c'est une série d'adresses de décalage de segment qui pointent vers les ISR. Le système d'exploitation peut remplacer les entrées IVT préexistantes par ses propres ISR.
(Remarque: la taille de l'IVT est fixée à 1024 (0x400) octets.)
En mode protégé (32 bits), la CPU utilise un IDT. L'IDT est une structure de longueur variable qui se compose de descripteurs (autrement appelés portes), qui indiquent au CPU les gestionnaires d'interruption. La structure de ces descripteurs est beaucoup plus complexe que les simples entrées de décalage de segment de l'IVT; C'est ici:
bytes 0, 1: Lower 16 bits of the ISR's address.
bytes 2, 3: A code segment selector (in the GDT/LDT)
byte 4: Zero.
byte 5: A type field consisting of several bitfields.
bit 0: P (Present): 0 for unused interrupts, 1 for used interrupts.*
bits 1, 2: DPL (Descriptor Privilege Level): The privilege level the descriptor (bytes 2, 3) must have.
bit 3: S (Storage Segment): Is 0 for interrupt and trap gates. Otherwise, is one.
bits 4, 5, 6, 7: GateType:
0101: 32 bit task gate
0110: 16-bit interrupt gate
0111: 16-bit trap gate
1110: 32-bit interrupt gate
1111: 32-bit trap gate
* L'IDT peut être de taille variable, mais il doit être séquentiel, c'est-à-dire que si vous déclarez que votre IDT va de 0x00 à 0x50, vous devez avoir chaque interruption de 0x00 à 0x50. Le système d'exploitation ne les utilise pas nécessairement tous, de sorte que le bit Présent permet au processeur de gérer correctement les interruptions que le système d'exploitation n'a pas l'intention de gérer.
Lorsqu'une interruption se produit (soit par un déclencheur externe (par exemple un périphérique matériel) dans une IRQ, soit par l' intinstruction d'un programme), la CPU pousse EFLAGS, puis CS, puis EIP. (Ceux-ci sont automatiquement restaurés par iretl'instruction de retour d'interruption.) Le système d'exploitation stocke généralement plus d'informations sur l'état de la machine, gère l'interruption, restaure l'état de la machine et continue.
Dans de nombreux systèmes d'exploitation * NIX (y compris Linux), les appels système sont basés sur des interruptions. Le programme met les arguments de l'appel système dans les registres (EAX, EBX, ECX, EDX, etc.), et appelle l'interruption 0x80. Le noyau a déjà défini l'IDT pour qu'il contienne un gestionnaire d'interruption sur 0x80, qui est appelé lorsqu'il reçoit l'interruption 0x80. Le noyau lit ensuite les arguments et invoque une fonction de noyau en conséquence. Il peut stocker un retour dans EAX / EBX. Les appels système ont été largement remplacés par les instructions sysenteret sysexit(ou syscallet sysretsur AMD), qui permettent une entrée plus rapide dans l'anneau 0.
Cette interruption peut avoir une signification différente dans un autre système d'exploitation. Assurez-vous de vérifier sa documentation.
Fait amusant: l'appel système i386 de FreeBSD passe des arguments sur la pile d'espace utilisateur. Seul eaxest utilisé pour le numéro syscall. asm.sourceforge.net/intro/hello.html
Peter Cordes
2
Comme mentionné, cela fait sauter le contrôle pour interrompre le vecteur 0x80. En pratique, cela signifie (au moins sous Linux) qu'un appel système est appelé; l'appel système exact et les arguments sont définis par le contenu des registres. Par exemple, exit () peut être appelé en définissant% eax sur 1 suivi de «int 0x80».
Il indique au processeur d'activer le vecteur d'interruption 0x80, qui sur les OS Linux est l'interruption d'appel système, utilisée pour appeler des fonctions système comme open()pour les fichiers, et cetera.
Strictement parlant, il ne le dit pas au noyau ... Il en informe le CPU, qui recherche le gestionnaire dans l'IDT, qui finit par être un pointeur vers un code du noyau.
asveikau
Vrai. Je suppose que la meilleure formulation serait qu'elle indique au CPU d'activer le vecteur et que le vecteur (dans le cadre du noyau) invoque la fonction.
Ambre
qui finit par faire ceci, qui à son tour finit par faire cela, qui ensuite fait ceci, qui y va alors confus . : / Amber a une réponse compréhensible..c'est-ce que c'est ..
Afzaal Ahmad Zeeshan
1
int n'est rien d'autre qu'une interruption, c'est-à-dire que le processeur mettra son exécution en cours en attente.
0x80 n'est rien d'autre qu'un appel système ou un appel du noyau. c'est-à-dire que la fonction système sera exécutée.
Pour être précis, 0x80 représente rt_sigtimedwait / init_module / restart_sys, il varie d'une architecture à l'autre.
Réponses:
Il passe le contrôle pour interrompre le vecteur 0x80
Voir http://en.wikipedia.org/wiki/Interrupt_vector
Sur Linux, jetez un œil à ceci : il était utilisé pour gérer
system_call
. Bien sûr, sur un autre système d'exploitation, cela pourrait signifier quelque chose de totalement différent.la source
int 0x80
comme une sorte spéciale decall
fonction dans le noyau (sélectionnée pareax
).int
signifie interruption, et le nombre0x80
est le numéro d'interruption. Une interruption transfère le flux de programme à celui qui gère cette interruption, ce qui est une interruption0x80
dans ce cas. Sous Linux, le0x80
gestionnaire d'interruption est le noyau et est utilisé pour faire des appels système au noyau par d'autres programmes.Le noyau est informé de l'appel système que le programme souhaite effectuer, en examinant la valeur dans le registre
%eax
(syntaxe AT&T et EAX dans la syntaxe Intel). Chaque appel système a des exigences différentes concernant l'utilisation des autres registres. Par exemple, une valeur de1
in%eax
signifie un appel système deexit()
et la valeur de%ebx
contient la valeur du code d'état pourexit()
.la source
Gardez à l'esprit que
0x80
=80h
=128
Vous pouvez voir ici que ce
INT
n'est qu'une des nombreuses instructions (en fait la représentation en langage d'assemblage (ou devrais-je dire «mnémonique») de celui-ci) qui existe dans le jeu d'instructions x86. Vous pouvez également trouver plus d'informations sur cette instruction dans le manuel d'Intel disponible ici .Pour résumer à partir du PDF:
Comme vous pouvez le voir, 0x80 est l' opérande de destination dans votre question. À ce stade, le CPU sait qu'il doit exécuter du code qui réside dans le noyau, mais quel code? Cela est déterminé par le vecteur d'interruption sous Linux.
L'une des interruptions les plus utiles du logiciel DOS était l'interruption 0x21. En l'appelant avec différents paramètres dans les registres (principalement ah et al), vous pouvez accéder à diverses opérations d'E / S, à la sortie de chaîne et plus encore.
La plupart des systèmes Unix et dérivés n'utilisent pas d'interruptions logicielles, à l'exception de l'interruption 0x80, utilisée pour effectuer des appels système. Ceci est accompli en entrant une valeur de 32 bits correspondant à une fonction du noyau dans le registre EAX du processeur , puis en exécutant INT 0x80.
Jetez un œil à ceci s'il vous plaît où d'autres valeurs disponibles dans les tables de gestionnaire d'interruption sont affichées:
Comme vous pouvez le voir, le tableau indique à la CPU d'exécuter un appel système. Vous pouvez trouver le tableau des appels système Linux ici .
Ainsi, en déplaçant la valeur 0x1 vers le registre EAX et en appelant le INT 0x80 dans votre programme, vous pouvez faire en sorte que le processus exécute le code dans le noyau qui arrêtera (quittera) le processus en cours d'exécution (sous Linux, processeur Intel x86).
Une interruption matérielle ne doit pas être confondue avec une interruption logicielle. Voici une très bonne réponse à ce sujet.
C'est aussi une bonne source.
la source
int 0x80
appel système ABI i386 Linux est extrêmement similaire à l'int 0x21
ABI DOS . Mettez un numéro d'appel dans un registre (AH pour DOS, EAX pour Linux) et d'autres arguments dans d'autres registres, puis exécutez une instruction d'interruption de logiciel. La principale différence réside dans ce que les appels système vous permettent de faire (accéder directement au matériel sous DOS mais pas sous Linux), pas dans la façon dont vous les appelez./usr/include/x86_64-linux-gnu/asm/unistd_64.h
Exemple d'appel système Linux exécutable minimal
Linux configure le gestionnaire d'interruption pour
0x80
qu'il implémente les appels système, un moyen pour les programmes utilisateur de communiquer avec le noyau.Compilez et exécutez avec:
Résultat: le programme imprime sur stdout:
et sort proprement.
Vous ne pouvez pas définir vos propres gestionnaires d'interruptions directement depuis le userland car vous n'avez que le ring 3 et Linux vous en empêche .
GitHub en amont . Testé sur Ubuntu 16.04.
Meilleures alternatives
int 0x80
a été remplacé par de meilleures alternatives pour faire des appels système: d'abordsysenter
, puis VDSO.x86_64 a une nouvelle
syscall
instruction .Voir aussi: Qu'est-ce qui est mieux "int 0x80" ou "syscall"?
Exemple 16 bits minimal
Apprenez d'abord à créer un système d'exploitation de chargeur de démarrage minimal et à l'exécuter sur QEMU et du matériel réel comme je l'ai expliqué ici: https://stackoverflow.com/a/32483545/895245
Vous pouvez maintenant exécuter en mode réel 16 bits:
Cela ferait dans l'ordre:
Do 0.
Do 1.
hlt
: arrêter l'exécutionNotez comment le processeur recherche le premier gestionnaire à l'adresse
0
et le second à4
: c'est une table de gestionnaires appelée IVT , et chaque entrée a 4 octets.Exemple minimal qui effectue des E / S pour rendre les gestionnaires visibles.
Exemple de mode protégé minimal
Les systèmes d'exploitation modernes fonctionnent en mode dit protégé.
La manipulation a plus d'options dans ce mode, donc c'est plus complexe, mais l'esprit est le même.
L'étape clé consiste à utiliser les instructions LGDT et LIDT, qui pointent l'adresse d'une structure de données en mémoire (le tableau des descripteurs d'interruption) qui décrit les gestionnaires.
Exemple minimal
la source
http://www.linfo.org/int_0x80.html
la source
L'instruction "int" provoque une interruption.
Qu'est-ce qu'une interruption?
Réponse simple: une interruption, en termes simples, est un événement qui interrompt le processeur et lui dit d'exécuter une tâche spécifique.
Réponse détaillée :
L'UC a une table des routines de service d'interruption (ou ISR) stockées en mémoire. En réel (16 bits) mode, cela est stocké en tant que IVT , ou je nterrupt V ecteur T mesure. L'IVT est généralement situé à
0x0000:0x0000
(adresse physique0x00000
), et c'est une série d'adresses de décalage de segment qui pointent vers les ISR. Le système d'exploitation peut remplacer les entrées IVT préexistantes par ses propres ISR.(Remarque: la taille de l'IVT est fixée à 1024 (0x400) octets.)
En mode protégé (32 bits), la CPU utilise un IDT. L'IDT est une structure de longueur variable qui se compose de descripteurs (autrement appelés portes), qui indiquent au CPU les gestionnaires d'interruption. La structure de ces descripteurs est beaucoup plus complexe que les simples entrées de décalage de segment de l'IVT; C'est ici:
* L'IDT peut être de taille variable, mais il doit être séquentiel, c'est-à-dire que si vous déclarez que votre IDT va de 0x00 à 0x50, vous devez avoir chaque interruption de 0x00 à 0x50. Le système d'exploitation ne les utilise pas nécessairement tous, de sorte que le bit Présent permet au processeur de gérer correctement les interruptions que le système d'exploitation n'a pas l'intention de gérer.
Lorsqu'une interruption se produit (soit par un déclencheur externe (par exemple un périphérique matériel) dans une IRQ, soit par l'
int
instruction d'un programme), la CPU pousse EFLAGS, puis CS, puis EIP. (Ceux-ci sont automatiquement restaurés pariret
l'instruction de retour d'interruption.) Le système d'exploitation stocke généralement plus d'informations sur l'état de la machine, gère l'interruption, restaure l'état de la machine et continue.Dans de nombreux systèmes d'exploitation * NIX (y compris Linux), les appels système sont basés sur des interruptions. Le programme met les arguments de l'appel système dans les registres (EAX, EBX, ECX, EDX, etc.), et appelle l'interruption 0x80. Le noyau a déjà défini l'IDT pour qu'il contienne un gestionnaire d'interruption sur 0x80, qui est appelé lorsqu'il reçoit l'interruption 0x80. Le noyau lit ensuite les arguments et invoque une fonction de noyau en conséquence. Il peut stocker un retour dans EAX / EBX. Les appels système ont été largement remplacés par les instructions
sysenter
etsysexit
(ousyscall
etsysret
sur AMD), qui permettent une entrée plus rapide dans l'anneau 0.Cette interruption peut avoir une signification différente dans un autre système d'exploitation. Assurez-vous de vérifier sa documentation.
la source
eax
est utilisé pour le numéro syscall. asm.sourceforge.net/intro/hello.htmlComme mentionné, cela fait sauter le contrôle pour interrompre le vecteur 0x80. En pratique, cela signifie (au moins sous Linux) qu'un appel système est appelé; l'appel système exact et les arguments sont définis par le contenu des registres. Par exemple, exit () peut être appelé en définissant% eax sur 1 suivi de «int 0x80».
la source
Il indique au processeur d'activer le vecteur d'interruption 0x80, qui sur les OS Linux est l'interruption d'appel système, utilisée pour appeler des fonctions système comme
open()
pour les fichiers, et cetera.la source
int n'est rien d'autre qu'une interruption, c'est-à-dire que le processeur mettra son exécution en cours en attente.
0x80 n'est rien d'autre qu'un appel système ou un appel du noyau. c'est-à-dire que la fonction système sera exécutée.
Pour être précis, 0x80 représente rt_sigtimedwait / init_module / restart_sys, il varie d'une architecture à l'autre.
Pour plus de détails, consultez https://chromium.googlesource.com/chromiumos/docs/+/master/constants/syscalls.md
la source