2011-01-15 2 views
7

다음에 대해 궁금합니다. 필자는 어셈블리 언어 작성시 IA32가 상대 점프의 사용을 촉진하는 방법, 즉 바이트의 변위량을 점프하는 것과 절대 점프를 사용하는 것, 즉 메모리의 특정 주소로 eip를 변경하는 방법으로 설계된 것을 알아 챘다. 이 논리 뒤에있는 논리는 무엇입니까?조립품의 상대 js 절대 jmp

+0

대부분의 경우 현재 사용할 수있는 주소를 사용하며 사용자가 선택한 주소는 사용하지 않습니다. – ruslik

답변

14

대부분의 점프는 점프 명령에서 멀리 떨어져 있지 않은 대상에 대한 것입니다. 부호있는 16 비트 값을 사용하는 점프 명령이 제공되므로 절대 점프 (일반적으로 4 바이트 + 명령 자체)에 필요한 것보다 적은 바이트가 될 수 있습니다.

상대적 분기의 또 다른 장점은 링커에서 수정하거나 PIC (position independent code)에 필요한 여분의 간접 참조를 수행 할 필요가 없다는 것입니다.

8

상대 점프는 컴파일러가 변동 가능 코드 코드를 생성 할 수있게합니다. 즉, 코드가 메모리의 어느 곳에서나 실행됩니다. 고정 된 위치에 묶여 있지 않습니다. 이것은 라이브러리 뒤에있는 중요한 개념입니다. 코드를 한 번 작성하고 임의의 프로그램에 그대로 링크 할 수있는 재배치 가능한 오브젝트 파일로 컴파일 할 수 있습니다. 링커는 외부에서 액세스 할 수있는 함수에 대해서만 절대 주소를 할당해야합니다 (그래서 자신의 코드에서 찾을 수 있습니다). 모든 "내부"점프는 상대적이며 하나의 실행 파일에서 다음 실행 파일로 변경할 필요가 없습니다.

C와 같은 고급 언어로 코드를 작성하고 컴파일러에서 어셈블리 코드를 생성 한 다음 (-S gcc 옵션 확인) 어셈블리 출력을 읽는 것이 좋습니다. if, forwhile과 같은 조건부 및 루프에 특히주의하십시오. 그러면 모두 상대 점프가 생성됩니다.

여기 가상 어셈블리 명령어를 이용하여 인위적인 예이다 : 여기

// Sample C code   Address Assembly Code  Comments 

if (x < 10) {   0000  CMP x,#10   ; Compare x to 10 
    do_true_stuff();  0003  JGE +7    ; Skip 7 bytes to 000A if x>=10 
} else {     0005  SUB do_true_stuff ; x<10 
    do_false_stuff();  0008  JMP +5    ; Skip 5 bytes to 000D 
}      000A  SUB do_false_stuff ; else-branch (x>=10) 
do_more_stuff();   000D  SUB do_more_stuff ; Finished if/else 

컴파일러는 if-else 블록의 미 실행 된 분기 스킵 상대 점프 (JGEJMP)를 생성한다. 이러한 점프는 링커가 코드를 저장하는 메모리의 어디에 상관없이 작동합니다. 절대 점프 인 경우 링커는 코드를 연결할 때마다 주소를 다시 계산해야합니다.

특히 함수가 단일 파일 내에서 범위가 지정되는 경우 많은 함수 호출이 상대 점프를 생성합니다. 이 작업은 연결 프로세스의 속도를 향상시킬뿐만 아니라 실행 코드를 작고 효율적으로 만듭니다. 상대 주소는 일반적으로 절대 주소보다 훨씬 작은 범위로 제한되기 때문에 더 적은 바이트로 나타낼 수 있습니다.

희망 하시겠습니까?

관련 문제