문제

누군가 다음 어셈블리 코드가 무엇을하는지 설명 할 수 있습니까?

 int 0x80  
도움이 되었습니까?

해결책

벡터 0x80을 방해하기 위해 제어를 통과합니다

보다 http://en.wikipedia.org/wiki/interrupt_vector

Linux에서는 살펴보십시오 이것: 처리에 사용되었습니다 system_call. 물론 다른 OS에서 이것은 완전히 다른 것을 의미 할 수 있습니다.

다른 팁

int 인터럽트와 숫자를 의미합니다 0x80 인터럽트 번호입니다. 인터럽트는 프로그램 흐름을 인터럽트를 처리하는 사람에게 프로그램 흐름을 전송합니다. 0x80 이 경우. Linux에서 0x80 인터럽트 핸들러는 커널이며 다른 프로그램에서 시스템 호출을 커널로 호출하는 데 사용됩니다.

커널은 등록부의 값을 검사하여 프로그램이 원하는 시스템 호출에 대해 알림을받습니다. %eax (인텔 구문의 가스 구문 및 EAX). 각 시스템 호출마다 다른 레지스터 사용에 대한 요구 사항이 다릅니다. 예를 들어, 값 1 안에 %eax 시스템 호출을 의미합니다 exit(), 및 가치 %ebx 상태 코드의 값을 보유합니다 exit().

0x80 = 80H = 128을 명심하십시오

너는 볼 수있어 여기 저것 int X86 명령 세트에 존재하는 많은 지침 (실제로 어셈블리 언어 표현 (또는 'mnemonic')을 말해야하는 많은 지침 중 하나 일뿐입니다. 인텔 자체 매뉴얼 에서이 지침에 대한 자세한 정보를 찾을 수도 있습니다. 여기.

PDF에서 요약하기 위해 :

int n/int/int 3— 방해 절차

int n 명령은 대상 피연산자로 지정된 인터럽트 또는 예외 핸들러에 대한 호출을 생성합니다. 대상 피연산자는 0에서 255 사이의 벡터를 지정하며 8 비트 서명되지 않은 중간 값으로 인코딩됩니다. Int N 명령은 인터럽트 핸들러에 소프트웨어 생성 호출을 실행하기위한 일반적인 니모닉입니다.

보시다시피 0x80 입니다 대상 피연산자 당신의 질문에. 이 시점에서 CPU는 커널에있는 일부 코드를 실행해야한다는 것을 알고 있지만 어떤 코드가 있습니까? 이는 Linux의 인터럽트 벡터에 의해 결정됩니다.

가장 유용한 DOS 소프트웨어 인터럽트 중 하나는 인터럽트 0x21입니다. 레지스터 (주로 AH 및 AL)에서 다른 매개 변수로 호출하면 다양한 IO 작업, 문자열 출력 등에 액세스 할 수 있습니다.

대부분의 UNIX 시스템 및 파생 상품은 시스템 호출을하는 데 사용되는 인터럽트 0x80을 제외하고 소프트웨어 인터럽트를 사용하지 않습니다. 이것은 입력하여 달성됩니다 프로세서의 EAX 레지스터에 커널 함수에 해당하는 32 비트 값 int 0x80을 실행합니다.

인터럽트 핸들러 테이블의 다른 사용 가능한 값이 표시되는 곳을 참조하십시오.

enter image description here

테이블에서 볼 수 있듯이 CPU는 시스템 호출을 실행합니다. Linux 시스템 호출 테이블을 찾을 수 있습니다 여기.

따라서 값 0x1을 EAX 레지스터로 이동하고 프로그램에서 int 0x80을 호출함으로써 프로세스가 현재 실행중인 프로세스 (Linux, x86 Intel CPU)를 중지 (종료)로 연결하는 커널에서 코드를 실행할 수 있습니다.

하드웨어 인터럽트는 소프트웨어 인터럽트와 혼동되어서는 안됩니다. 여기 이와 관련하여 아주 좋은 답변입니다.

이것 또한 좋은 소스입니다.

너는 볼 수있어 int 80h 행동 중 여기.

int 0x80은 x86 (예 : Intel-Compatible) 프로세서에서 Linux에서 시스템 호출을 호출하는 데 사용되는 어셈블리 언어 명령어입니다.

http://www.linfo.org/int_0x80.html

최소 실행 가능한 Linux 시스템 호출 예제

Linux는 인터럽트 핸들러를 설정합니다 0x80 IT는 시스템 호출을 구현하고 사용자 랜드 프로그램이 커널과 통신하는 방법입니다.

.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

다음과 같이 컴파일하고 실행합니다.

as -o main.o main.S
ld -o main.out main.o
./main.out

결과 : 프로그램은 STDOUT에 인쇄합니다.

hello world

그리고 깨끗하게 빠져 나옵니다.

사용자 만에서 직접 인터럽트 핸들러를 직접 설정할 수 없습니다. Ring 3과 Linux는 그렇게하지 못하게합니다.

Github 상류. 우분투 16.04에서 테스트.

더 나은 대안

int 0x80 시스템 통화를위한 더 나은 대안으로 대체되었습니다. sysenter, 그런 다음 vdso.

x86_64가 있습니다 새로운 syscall 지침.

또한보십시오: "int 0x80"또는 "syscall"더 나은 것은 무엇입니까?

최소 16 비트 예제

먼저 최소한의 부트 로더 OS를 작성하고 여기에서 설명한대로 QEMU 및 실제 하드웨어에서 실행하는 방법을 배우십시오. https://stackoverflow.com/a/32483545/895245

이제 16 비트 실제 모드로 실행할 수 있습니다.

    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

이것은 순서대로 할 것입니다.

  • Do 0.
  • Do 1.
  • hlt: 실행을 중지하십시오

프로세서가 주소에서 첫 핸들러를 찾는 방법에 유의하십시오. 0, 두 번째는 4: 그것은 The라고 불리는 핸들러의 테이블입니다 IVT, 및 각 항목에는 4 바이트가 있습니다.

일부 IO를 수행하는 최소한의 예 취급자가 보이게합니다.

최소 보호 모드 예제

최신 운영 체제는 소위 보호 모드에서 실행됩니다.

핸들링은이 모드에서 더 많은 옵션이 있으므로 더 복잡하지만 정신은 동일합니다.

핵심 단계는 LGDT 및 LIDT 지침을 사용하는 것입니다.이 지침은 핸들러를 설명하는 메모리 내 데이터 구조 (인터럽트 디스크립터 테이블)의 주소를 가리 킵니다.

최소한의 예

"int"명령은 인터럽트를 유발합니다.

인터럽트 란 무엇입니까?

간단한 답변 : 간단히 말해서 간단히 말해서 CPU를 방해하는 이벤트이며 특정 작업을 실행하도록 지시합니다.

자세한 답변:

CPU에는 메모리에 저장된 인터럽트 서비스 루틴 (또는 ISR) 테이블이 있습니다. 실제 (16 비트) 모드에서 이것은 IVT, 또는 파산 V렉터 할 수 있는. IVT는 일반적으로 위치에 있습니다 0x0000:0x0000 (물리적 주소 0x00000), ISR을 가리키는 일련의 세그먼트 오프셋 주소입니다. OS는 기존 IVT 항목을 자체 ISR로 대체 할 수 있습니다.

(참고 : IVT의 크기는 1024 (0x400) 바이트로 고정되어 있습니다.)

보호 된 (32 비트) 모드에서 CPU는 IDT를 사용합니다. IDT는 가변 길이 구조로 구성됩니다 설명자 (게이트라고도 함)는 인터럽트 핸들러에 대해 CPU에 알려줍니다. 이 설명자의 구조는 IVT의 간단한 세그먼트 오프셋 항목보다 훨씬 더 복잡합니다. 여기있어:

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

*IDT는 가변 크기 일 수 있지만 순차적이어야합니다. 즉, IDT를 0x00에서 0x50으로 선언하면 0x00에서 0x50까지의 모든 인터럽트가 있어야합니다. OS가 반드시 모든 것을 사용하지는 않으므로 현재 비트는 CPU가 인터럽트를 올바르게 처리 할 수있게합니다. OS는 OS를 처리 할 의도가 없습니다.

인터럽트가 발생하는 경우 (IRQ의 외부 트리거 (예 : 하드웨어 장치) 또는 int 프로그램에서의 지시), CPU는 EFLAGS, CS 및 EIP를 푸시합니다. (이들은 자동으로 복원됩니다 iret, 인터럽트 리턴 명령어.) OS는 일반적으로 기계 상태에 대한 추가 정보를 저장하고 인터럽트를 처리하고 기계 상태를 복원하며 계속합니다.

많은 *닉스 OS (Linux 포함)에서 시스템 호출은 인터럽트 기반입니다. 이 프로그램은 레지스터 (EAX, EBX, ECX, EDX 등)의 시스템 호출에 인수를 제시하고 인터럽트 0x80을 호출합니다. 커널은 이미 IDT를 0x80의 인터럽트 핸들러를 포함하도록 설정했으며, 이는 인터럽트 0x80을 수신 할 때 호출됩니다. 그런 다음 커널은 인수를 읽고 그에 따라 커널 함수를 호출합니다. EAX/EBX에 반품을 저장할 수 있습니다. 시스템 호출은 크게 대체되었습니다 sysenter 그리고 sysexit (또는 syscall 그리고 sysret AMD) 지침에서 링 0에 더 빠르게 들어갈 수 있습니다.

이 인터럽트는 다른 OS에서 다른 의미를 가질 수 있습니다. 문서를 확인하십시오.

언급 한 바와 같이, 제어는 벡터 0x80을 인터럽트하기 위해 점프합니다. 실제로 이것이 의미하는 바는 (적어도 Linux에서) 시스템 호출이 호출된다는 것입니다. 정확한 시스템 호출 및 인수는 레지스터의 내용에 의해 정의됩니다. 예를 들어, %eax를 1로 설정 한 다음 'int 0x80'을 설정하여 exit ()를 호출 할 수 있습니다.

CPU는 Linux OS에서 시스템 기능을 호출하는 데 사용되는 시스템 용지 인터럽트 인 인터럽트 벡터 0x80을 활성화하도록 지시합니다. open() 파일의 경우 et cetera.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top