맨위로가기

JMP (x86 명령어)

"오늘의AI위키"는 AI 기술로 일관성 있고 체계적인 최신 지식을 제공하는 혁신 플랫폼입니다.
"오늘의AI위키"의 AI를 통해 더욱 풍부하고 폭넓은 지식 경험을 누리세요.

1. 개요

JMP 명령어는 x86 아키텍처에서 사용되는 분기 명령어의 일종으로, 프로그램의 실행 흐름을 변경하는 데 사용된다. JMP 명령어는 점프 대상의 위치와 방식에 따라 단거리 점프, 근거리 점프, 원거리 점프, 태스크 전환 등으로 나뉜다. 단거리 점프는 현재 명령어 포인터를 기준으로 -128바이트에서 +127바이트 범위 내에서 점프하며, 근거리 점프는 현재 코드 세그먼트 내에서 점프한다. 원거리 점프는 다른 코드 세그먼트로 점프하며, 태스크 전환은 보호 모드에서 다른 태스크로 점프하는 데 사용된다. JMP 명령어를 사용하여 태스크 전환을 수행할 경우, CALL 명령어와는 달리 중첩 태스크 플래그가 설정되지 않고 이전 태스크 링크가 갱신되지 않아 IRET 명령어를 사용하여 이전 태스크로 돌아갈 수 없다.

2. JMP 명령어의 종류

JMP 명령어는 프로그램의 실행 흐름을 변경하는 방식으로, 점프하는 대상의 위치와 점프 방식에 따라 다음과 같은 네 가지 주요 유형으로 나눌 수 있다.


  • '''단거리 점프''': 현재 명령어 포인터(EIP)를 기준으로 비교적 짧은 거리(-128바이트에서 +127바이트) 내에서 점프한다.
  • '''근거리 점프''': 현재 코드 세그먼트(CS 레지스터가 가리키는 영역) 내에서 점프한다. 점프할 위치는 세그먼트 내의 절대 주소 또는 현재 위치로부터의 상대적인 거리로 지정될 수 있다.
  • '''원거리 점프''': 현재 코드 세그먼트가 아닌 다른 코드 세그먼트로 점프한다. 일반적으로 서로 다른 코드 세그먼트 간 이동에 사용되며, 점프하는 세그먼트는 동일한 권한 수준을 가져야 한다.
  • '''태스크 전환''': 보호 모드에서 사용되며, 현재 실행 중인 태스크가 아닌 다른 태스크로 실행 흐름을 전환한다. 이때 JMP 명령어는 태스크 게이트를 참조하거나 직접 태스크 상태 세그먼트(TSS)를 지정하여 전환할 태스크를 가리킬 수 있다.

2. 1. 단거리 점프 (Short Jump)

단거리 점프는 현재 명령어 포인터 (EIP)를 기준으로 -128바이트에서 +127바이트 범위 내에서 프로그램 실행 흐름을 변경하는 명령어이다. 이동할 거리를 나타내는 상대 오프셋은 8비트 부호 있는 값(rel8)으로 표현되며, 현재 EIP로부터의 상대적인 거리를 나타낸다. 단거리 점프 시 코드 세그먼트 레지스터 (CS)의 값은 변경되지 않는다.

2. 2. 근거리 점프 (Near Jump)

근거리 점프는 현재 실행 중인 코드 세그먼트 내에서 프로그램의 실행 흐름을 바꾸는 명령어이다. 이 과정에서 CS 레지스터의 값은 변경되지 않는다.[1] 점프할 대상 주소는 다음 두 가지 방식으로 지정될 수 있다.

  • 절대 오프셋: 점프할 주소를 직접 지정하여 해당 주소 값을 EIP 레지스터에 바로 로드한다.
  • 상대 오프셋: 현재 EIP 레지스터 값에 상대적인 거리(rel16 또는 rel32)를 더하여 점프할 주소를 계산한다.


점프의 동작 방식은 피연산자 크기에 따라 달라진다.

  • 절대 오프셋을 사용하는 경우:
  • 16비트 모드에서는 지정된 오프셋 값이 EIP 레지스터의 하위 16비트에 로드되고, 상위 16비트는 0으로 채워진다.
  • 32비트 모드에서는 32비트 전체 오프셋 범위를 사용하여 EIP 레지스터에 값을 로드할 수 있다.
  • 상대 오프셋을 사용하는 경우:
  • 오프셋의 크기(8비트, 16비트 또는 32비트)는 명령어의 opcode와 피연산자 크기 속성에 따라 결정된다. 이는 점프할 수 있는 거리의 범위를 제한한다.

  • ---

2. 3. 원거리 점프 (Far Jump)

원거리 점프(Far Jump)는 현재 실행 중인 코드 세그먼트와 다른 코드 세그먼트로 프로그램의 실행 흐름을 옮기는 명령어이다. 이 점프 방식은 일반적으로 서로 다른 세그먼트 사이를 이동할 때 사용된다. 원거리 점프를 수행할 때는 목표 지점을 지정하기 위해 두 가지 정보가 필요하다. 하나는 이동할 코드 세그먼트를 가리키는 세그먼트 선택자이며, 이 값은 `CS` 레지스터에 로드된다. 다른 하나는 해당 세그먼트 내의 특정 위치를 나타내는 오프셋으로, 이 값은 `EIP` 레지스터에 로드된다.

원거리 점프는 프로세서의 작동 모드(리얼 모드, 가상 8086 모드, 보호 모드)에 따라 동작 방식에 차이가 있으며, 각 모드에서의 구체적인 작동 방식은 하위 섹션에서 설명한다.

2. 3. 1. 리얼 모드 또는 가상 8086 모드

대상 주소는 다음 두 가지 요소로 구성된다:

  • '''세그먼트 선택자''': CS 레지스터에 로드된다.
  • '''오프셋''': EIP 레지스터에 로드된다.


대상 주소는 다음 두 가지 방식으로 지정될 수 있다:

# '''직접''' 지정: 명령어 자체에 포인터(ptr16:16 또는 ptr16:32) 형태로 인코딩된다.

# '''간접''' 지정: 메모리(m16:16 또는 m16:32)에 저장된 주소를 명령어가 가져와 사용한다.

2. 3. 2. 보호 모드

보호 모드에서 먼(far) 점프는 다음 용도로 사용할 수 있다.

# '''코드 세그먼트 전환'''

#* '''순응''' 또는 '''비순응 코드 세그먼트'''로의 점프.

#* CS 레지스터는 대상 세그먼트 선택자로 업데이트되고 EIP는 오프셋으로 업데이트된다.

# '''호출 게이트 사용'''

#* 대상 피연산자는 점프할 세그먼트와 오프셋을 정의하는 '''호출 게이트 디스크립터'''를 지정한다.

#* 이 방법은 간접 점프를 허용하며 '''16비트'''와 '''32비트''' 세그먼트 간의 전환에 선호된다.

# '''작업 전환 수행'''

#* 대상은 '''작업 게이트'''를 지정하거나 직접 '''TSS''' (Task State Segment)를 참조한다.

#* 작업의 세그먼트 선택자(코드 및 스택)와 EIP는 TSS에서 로드된다.

3. 태스크 전환 시 특별 참고 사항

JMP 명령어를 사용하여 태스크 전환을 수행하는 경우, 다음과 같은 특징이 있다.


  • EFLAGS 레지스터의 중첩 태스크(Nested Task, NT) 플래그가 설정되지 않는다.
  • 새로운 TSS의 이전 태스크 링크 필드가 갱신되지 않는다.
  • 따라서 IRET 명령어를 사용해도 이전 태스크로 돌아갈 수 없다.


이는 CALL 명령어를 이용한 태스크 전환과 다른 점이다. CALL 명령어는 NT 플래그를 설정하고 이전 태스크 링크 정보를 저장하여 IRET 명령어를 통한 태스크 반환을 가능하게 한다.

참조

[1] 웹사이트 Intel Architecture Software Developer's Manual, Volume 2: Instruction Set Reference Manual (6.5MB) https://web.archive.[...] 2009-11-03
[2] 웹인용 Intel Architecture Software Developer's Manual, Volume 2: Instruction Set Reference Manual (6.5MB) http://download.inte[...] 2009-11-03



본 사이트는 AI가 위키백과와 뉴스 기사,정부 간행물,학술 논문등을 바탕으로 정보를 가공하여 제공하는 백과사전형 서비스입니다.
모든 문서는 AI에 의해 자동 생성되며, CC BY-SA 4.0 라이선스에 따라 이용할 수 있습니다.
하지만, 위키백과나 뉴스 기사 자체에 오류, 부정확한 정보, 또는 가짜 뉴스가 포함될 수 있으며, AI는 이러한 내용을 완벽하게 걸러내지 못할 수 있습니다.
따라서 제공되는 정보에 일부 오류나 편향이 있을 수 있으므로, 중요한 정보는 반드시 다른 출처를 통해 교차 검증하시기 바랍니다.

문의하기 : help@durumis.com