누군가 다음 어셈블리 코드의 기능을 설명 할 수 있습니까?
int 0x80
답변
제어를 인터럽트 벡터 0x80으로 전달합니다.
http://en.wikipedia.org/wiki/Interrupt_vector 참조
Linux에서 이것을 보세요 : system_call. 물론 다른 OS에서는 완전히 다른 의미 일 수 있습니다.
답변
int인터럽트를 의미하고 번호 0x80는 인터럽트 번호입니다. 인터럽트는 인터럽트를 처리하는 사람에게 프로그램 흐름을 전송합니다 0x80.이 경우에는 인터럽트 입니다. Linux에서 0x80인터럽트 처리기는 커널이며 다른 프로그램에서 커널에 대한 시스템 호출을 수행하는 데 사용됩니다.
커널은 레지스터의 값 %eax(AT & T 구문 및 Intel 구문의 EAX)을 검사하여 프로그램이 만들고자하는 시스템 호출에 대한 알림을받습니다 . 각 시스템 호출에는 다른 레지스터 사용에 대한 요구 사항이 다릅니다. 예를 들어 1in 값은 %eax의 시스템 호출을 의미하고 exit()in %ebx값은에 대한 상태 코드 값을 보유합니다 exit().
답변
명심 0x80= 80h=128
당신은 볼 수 있습니다 여기에 그 INTx86 명령어 세트에 존재하는 바로 많은 지시 사항 중 하나입니다 (실제로 어셈블리 언어 표현 (또는 나는 그것을 ‘연상’)라고한다). 이 지침에 대한 자세한 내용은 여기 에서 찾을 수있는 인텔의 자체 설명서에서도 찾을 수 있습니다 .
PDF에서 요약하면 :
INT n / INTO / INT 3— 인터럽트 프로 시저 호출
INT n 명령어는 대상 피연산자로 지정된 인터럽트 또는 예외 처리기에 대한 호출을 생성합니다. 대상 피연산자는 8 비트 부호없는 중간 값으로 인코딩 된 0에서 255 사이의 벡터를 지정합니다. INT n 명령어는 인터럽트 핸들러에 대한 소프트웨어 생성 호출을 실행하기위한 일반적인 니모닉입니다.
보시다시피 0x80 은 질문 의 대상 피연산자 입니다. 이 시점에서 CPU는 커널에있는 일부 코드를 실행해야한다는 것을 알고 있지만 어떤 코드입니까? 이는 Linux의 인터럽트 벡터에 의해 결정됩니다.
가장 유용한 DOS 소프트웨어 인터럽트 중 하나는 인터럽트 0x21입니다. 레지스터의 다른 매개 변수 (대부분 ah 및 al)로 호출하면 다양한 IO 작업, 문자열 출력 등에 액세스 할 수 있습니다.
대부분의 Unix 시스템 및 파생 제품은 시스템 호출에 사용되는 인터럽트 0x80을 제외하고 소프트웨어 인터럽트를 사용하지 않습니다. 이는 커널 함수에 해당 하는 32 비트 값을 프로세서의 EAX 레지스터에 입력 한 다음 INT 0x80을 실행하여 수행됩니다.
인터럽트 처리기 테이블에서 사용 가능한 다른 값이 표시되는 곳을 살펴보십시오.

표에서 볼 수 있듯이 CPU는 시스템 호출을 실행합니다. 여기 에서 Linux 시스템 호출 테이블을 찾을 수 있습니다 .
따라서 값 0x1을 EAX 레지스터로 이동하고 프로그램에서 INT 0x80을 호출하여 현재 실행중인 프로세스 (Linux, x86 Intel CPU)를 중지 (종료)하는 커널의 코드를 프로세스가 실행하도록 할 수 있습니다.
하드웨어 인터럽트를 소프트웨어 인터럽트와 혼동해서는 안됩니다. 다음은 이 점에 아주 좋은 대답이다.
이것은 또한 좋은 소스입니다.
답변
최소 실행 가능한 Linux 시스템 호출 예제
Linux는 0x80사용자 영역 프로그램이 커널과 통신하는 방법 인 시스템 호출을 구현 하도록 인터럽트 처리기를 설정합니다 .
.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
깨끗하게 종료됩니다.
사용자 영역에서 직접 인터럽트 처리기를 설정할 수는 없습니다. 링 3 만 있고 Linux에서는이를 방지하기 때문 입니다.
GitHub 업스트림 . Ubuntu 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: 실행 중지
프로세서가 address에서 첫 번째 핸들러를 찾는 방법 0과 두 번째 핸들러를 찾는 방법에 유의하십시오 4. 이는 IVT 라는 핸들러 테이블 이며 각 항목에는 4 바이트가 있습니다.
핸들러를 표시하기 위해 일부 IO 를 수행하는 최소 예제입니다 .
최소 보호 모드 예
최신 운영 체제는 소위 보호 모드에서 실행됩니다.
이 모드에서는 핸들링에 더 많은 옵션이 있으므로 더 복잡하지만 정신은 동일합니다.
핵심 단계는 처리기를 설명하는 메모리 내 데이터 구조 (인터럽트 설명자 테이블)의 주소를 가리키는 LGDT 및 LIDT 명령어를 사용하는 것입니다.
답변
int 0x80은 x86 (즉, Intel 호환) 프로세서의 Linux에서 시스템 호출을 호출하는 데 사용되는 어셈블리 언어 명령어입니다.
답변
“int”명령은 인터럽트를 발생시킵니다.
인터럽트 란 무엇입니까?
간단한 답변 : 간단히 말해 인터럽트는 CPU를 중단하고 특정 작업을 실행하도록 지시하는 이벤트입니다.
자세한 답변 :
CPU에는 메모리에 저장된 인터럽트 서비스 루틴 (또는 ISR) 테이블이 있습니다. 리얼 (16 비트) 모드에서, 이것은로 저장됩니다 IVT , 또는 I nterrupt V의 엑터 T 수. 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가 이들 모두를 반드시 사용하는 것은 아니므로 Present 비트를 사용하면 CPU가 OS가 처리하지 않을 인터럽트를 적절하게 처리 할 수 있습니다.
인터럽트가 발생하면 (IRQ의 외부 트리거 (예 : 하드웨어 장치) 또는 int프로그램 의 명령에 의해 ) CPU는 EFLAGS, CS, EIP 순으로 푸시합니다. (이는 iret인터럽트 반환 명령 인에 의해 자동으로 복원됩니다 .) OS는 일반적으로 시스템 상태에 대한 추가 정보를 저장하고, 인터럽트를 처리하고, 시스템 상태를 복원하고, 계속합니다.
많은 * NIX OS (Linux 포함)에서 시스템 호출은 인터럽트 기반입니다. 프로그램은 레지스터 (EAX, EBX, ECX, EDX 등)의 시스템 호출에 인수를 넣고 인터럽트 0x80을 호출합니다. 커널은 이미 인터럽트 0x80을 수신 할 때 호출되는 0x80의 인터럽트 핸들러를 포함하도록 IDT를 설정했습니다. 그런 다음 커널은 인수를 읽고 그에 따라 커널 함수를 호출합니다. EAX / EBX에 반품을 저장할 수 있습니다. 시스템 호출은 크게 의해 대체되었습니다 sysenter및 sysexit(또는 syscall과 sysret링 0으로 빠른 진입을 허용 지침, AMD에).
이 인터럽트는 다른 OS에서 다른 의미를 가질 수 있습니다. 설명서를 확인하십시오.
답변
언급했듯이 제어가 인터럽트 벡터 0x80으로 점프하도록합니다. 실제로 이것이 의미하는 것은 (적어도 Linux에서는) 시스템 호출이 호출된다는 것입니다. 정확한 시스템 호출과 인수는 레지스터의 내용에 의해 정의됩니다. 예를 들어, % eax를 1로 설정 한 다음 ‘int 0x80’을 설정하여 exit ()를 호출 할 수 있습니다.
