간단한 명령어 인코딩

Oct 07 2020

다음 어셈블리 지침을 살펴 보겠습니다.

add    %cl,%bl

이것은 00 cb또는 00000000 11001011바이너리 로 인코딩됩니다 . cbModR / M 비트 필드에를 넣으면 다음과 같습니다.

  1   1   0   0   1   0  1   1
+---+---+---+---+---+---+---+---+
|  mod  |    reg    |    r/m    |
+---+---+---+---+---+---+---+---+

그리고 여기 에서 레지스터 필드를 조회하면 다음과 같은 결과 를 얻을 수 있습니다.

  • mod : 11(주소 지정 모드 등록)
  • reg : 001(cl 레지스터)
  • r / m : 011(bl 레지스터)

그리고, 저는 믿습니다 000000ds은 IS add명령, 그리고 d=s=0그들은 모든 레지스터는 것 때문이다. 이 명령이 인코딩되는 방법에 대한 올바른 이해입니까? 또한 '전체 인코딩'체계의 경우 다음이 정확합니다 (비트가 아닌 바이트).

[empty]         0x0         0b11001011     [empty]        [empty]          [empty]
_ _ _ _        _ _             _              _           _ _ _ _          _ _ _ _
Prefix      Instruction    Mod-reg-r/m      Scale       displacement      immediate

명령을 '디코딩'하려는 시도에서 여기에 누락 된 것이 있습니까?

답변

2 PeterCordes Oct 08 2020 at 04:14

네, 맞아요.

인코딩 op r/m, rop r, r/m, 및 8 비트 대 16/32 비트를 위한 일반 패턴 (8086으로 거슬러 올라가는 "레거시"ALU 명령어 의 경우)은 일반 패턴에서 opcode 바이트의 하위 2 비트를 사용하지만 그럴 필요는 없습니다. 그것에 의존합니다.

인텔은 vol.2 매뉴얼에서 각 명령어의 각 인코딩에 대해 진행되는 작업을 정확히 문서화합니다. add예를 들어 Op / En 열 및 피연산자 인코딩 표를 참조하십시오 . (또한보십시오https://ref.x86asm.net/coder64.htm이는 또한 모든 opcode에 대해 어떤 피연산자를 지정합니다). 둘 다 ModRM 바이트를 사용하는 opcode와 그렇지 않은 opcode를 알려줍니다.

물론 이들은 Intel 구문 순서를 사용합니다. 피연산자 목록과 Intel 및 AMD 매뉴얼의 순서를 반대로하는 AT & T 구문을 사용하면서 매뉴얼과 튜토리얼을 따라 가면서 삶을 더 복잡하게 만들고 있습니다.

예를 들어 , 피연산자 인코딩 00 /r으로 나열 되며 MR, 테이블에서 피연산자 1 = ModRM:r/m (r, w)이므로 읽고 쓰고 r/m필드에 의해 인코딩됩니다 . 피연산자 2 = ModRM:reg (r)이므로 reg필드로 인코딩 된 읽기 전용 소스 입니다.

재미있는 사실 : 00 00is add [rax], al또는 AT & Tadd %al, (%rax)

GAS에 다음 인코딩 중 하나를 선택하도록 요청할 수 있습니다. x86 XOR opcode 차이

{load}  add    %cl,%bl        # 02 d9
{store} add    %cl,%bl        # 00 cb

MOV r / m8, r8과 MOV r8, r / m8의 차이점 도 참조하십시오.