2012-11-11 2 views
5

저는 x86/x64 CPU 명령에 대한 컴파일러를 작성하고 있는데 사람들이 '변위'주소로 의미하는 바를 파악할 수 없습니다. 예를 들어, Add 명령어는 여기에 자세히 나와 있습니다. http://www.c-jump.com/CIS77/CPU/x86/X77_0150_encoding_add_edx_displacement.htmx86/x64 변위 주소 지정 추가

난 그냥 일반 메모리 주소에 레지스터가 추가되는 add 명령어를 구현하려고합니다. 문제는 주소가 '변위 주소'라는 것입니다. 즉, 주소가 명령어 위치에서 오프셋 된 부호있는 값을 의미합니까?

+3

어셈블리 코드를 생성합니까? C 코드를 생성 할 수 없습니까, 아니면 LLVM을 사용할 수 있습니까? 또는 http://code.google.com/p/asmjit/ 또는 다른 라이브러리로 기계 코드를 내 보냅니 까? x86/64 명령어 세트를 잘 이해하고 있습니까? 혹시 http://www.intel.com/content/www/us/en/processors/architectures-software-developer-manuals.html –

답변

9

는 86 간접 피연산자의 몇 가지 형태가있다 :

  1. [등록]
  2. [직접 + 변위]
  3. [변위]
  4. [직접 * 상수 +의 레지 ]
  5. [reg * constant + reg + displacement]

"displacement"는 나머지 주소에 추가되는 상수입니다. 상수가 아닌 주소의 구성 요소가없는 경우에도 여전히 "변위"라고합니다.이는 주로 다른 주소 지정 양식과 일관성을 유지하기위한 것입니다.

그것을 보는 다른 방법은 모든 주소의 형식이다이다

[직접 * 상수 +의 등록 + 변위] 0

값 있도록 각 구성 요소와 함께

[변위] 형식은 변위 이외의 모든 구성 요소가 0 인 인코딩 일뿐입니다.

컴파일러 작가로서 마지막 2 가지 형식이 특히 흥미 롭습니다. 그들은 하나의 명령으로 pArray[index]->field + 1 같은 것을 쉽게 인코딩 할 수 있습니다.

+0

[reg * constant + reg + displacement]가 어떻게 기계 명령어로 인코딩 되나요? 메모리 위치 0x00000001에 배열이 있는데 그 인덱스를 AL에 액세스하려고한다고 가정 해보십시오. 이동 명령을 사용하고 MOV AH 0x00000001 [AL]을 수행하려고합니다. 제 생각에 그것은 단지 [reg + displacement]라고 생각합니다. 이 페이지의 섹션 6은 R/M 바이트의 인코딩을 보여 주지만 실제로 혼란 스럽습니다. http://www.c-jump.com/CIS77/CPU/x86/lecture.html –

+0

인텔 설명서의 볼륨 2를보십시오. 각 명령어는 인코딩 형식을 지정합니다. r/m 피연산자를 나열하는 인코딩 양식은 mod/rm 바이트의 레지스터 또는 메모리 피연산자를 허용합니다. –

+0

인텔 설명서의 양 2에보십시오. 각 명령어는 인코딩 형식을 지정합니다. r/m 피연산자를 나열하는 인코딩 양식은 mod/rm 바이트의 레지스터 또는 메모리 피연산자를 허용합니다. 볼륨 2, 섹션 2.1의 2 장에는 mod r/m 바이트의 의미를 보여주는 표가 있습니다. [-] [-]가 나열된 양식은 SIB 바이트를 사용하는 인코딩을 나타냅니다. SIB 어드레싱은 reg * constant + reg 형식입니다. mod/rm 바이트의 일부 형식은 SIB 바이트 다음에 변위가 있음을 나타냅니다. 그것들은 reg * 상수 + reg + 상수 형태를 제공합니다. SIB를 설명하는 표도 있습니다. –

3

변위를 필요로하는 특수 추가는 없으며, 그 페이지는 불필요하게 혼란 스럽습니다. 이것은 정상적인 메모리 피연산자 인코딩의 일부일뿐입니다. , 대상으로 al 소스 (04 ib)와 같은 즉각적인를 사용하여 대상으로 ax/eax/rax를 사용하기위한 특별한 경우가 :

add 모든 ALU-작전과 같은 방법을 인코딩 상당히 표준 명령이 있습니다 즉각적인 출처 (+ 05 imm), add r/m, imm의 세 가지 버전 (8 비트 대상 1 개, 넓은 대상 및 부호 확장 된 8 비트 소스 용, 넓은 대상 및 넓은 소스 용), 물론 add r, r/madd r/m, r의 세 가지 버전이 있습니다.

이것은 이 변위의 형식을 취하는 add r, r/m의 특별한 경우입니다. 참고 # 1은 ModRM encoding입니다.

그래서 그들은 단지 add edx, [sdword]을 의미합니다. (하지만 그들은 reg 필드를 잘못 인코딩했습니다. edx010이 아니고 011이 아닙니다.

+0

을 공부하셨습니까? AL (8 비트 레지스터 0)을 메모리 위치 0x00000000에 추가하려면, CPU는 (16 진수로) 00 05 00000000? –

+0

@RyanBrown 예, 작동 할 것입니다. – harold

4

해당 페이지가 정확하지 않습니다. 말하는 "변위가 걸린다"는 말은 역 어셈블러 출력에서 ​​볼 수있는 형태 인 add r[16|32], r/m[16|32] 또는 add edx, [0xdisp]을 나타냅니다. 가정이

  • edx 레지스터의 목적지를 부호화 및 그것을 0x15의 값을 줄 것이다 ModR/M 바이트의 유효 주소는 32 비트 용량을 지정하는 연산 코드 0x03와 ADD 명령에 대해 얘기 (인텔 참조 ® 64 및 IA-32 아키텍처 소프트웨어 개발자 설명서 2 권, 41 페이지, 표 2-2).
  • 이 명령어의 효과는 메모리 주소 disp에있는 dword를 edx의 내용에 추가하는 것입니다.
  • 실제로 명령어의 인코딩은 1 바이트의 이동을 위해 \x03\x15\x00\x00\x00\x01이됩니다.