Tuuna Computer Science

ModR/M 바이트에서 Mod+R/M과 Reg와의 목적지(순서) 구분 & SIB 바이트 작성법 본문

Debugger

ModR/M 바이트에서 Mod+R/M과 Reg와의 목적지(순서) 구분 & SIB 바이트 작성법

GuTTe 2018. 12. 15. 01:58
 
개꿀팁인데 Opcode에서 오퍼랜드와 오퍼랜드 사이의 목적지를 구별 짓는 것이 상당히 어려웠다. 
 
어떤 블로그에선 Mod 비트부분에서 11이면 목적지가 레지스터라는데 테스트 결과 조금 개소리였다. (아닐수도) 
구글링 결과 Mod부분이 11이면 R/M이 Register임을 알린다.
추가 적으로 Mod부분이 00이라면 뒤엔 Displacement가 따른다. 
 
그래서 고민하다가 구글링 해보았는데 Opcode안에 d라는 비트와 s라는 비트가 숨겨져 있었다! 
 
d비트는 전체 1번째 비트에 
s비트는 전체 0번째 비트에...
 
┌──────────────────────────┐
│     │      │       │       │        │        │   d    │                s                │
├──────────────────────────┤
 
d비트는 이 Opcode에 의한 오퍼랜드가 어떤 방향으로 가야하는지 Direction을 결정 짓는다. 
 
  • d비트가 1이라면 Memory에서 Register로 
 
  • d비트가 0이라면 Register에서 Memory로 
 
만약 오퍼랜드 2개다 레지스터면 어떡하냐 그럴땐 기본형은 ModR/M + Reg의 형태를 따르는 것 같다. (이건 내 피셜) 
 
그리고 오퍼랜드의 크기도 조금 헷갈릴  수 있는데 그럴 땐 0번째 비트에 위치한 s비트를 비교하면 된다.
 
  • s비트가 0이라면 8-bit 
 
  • s비트가 1이라면 16-bit or 32-bit 
 
하지만 위의 내용중 NOT명령과 NEG명령은 먹히지 않는다! (오퍼랜드가 한개라서 그런가) 
 
   0:    8b 46 14                 mov    eax,DWORD PTR [esi+0x14]
   3:    89 46 14                 mov    DWORD PTR [esi+0x14],eax
 
여기서 볼 수 있는 거처럼 Mov의 Opcode인 0x8b와 0x89를 보자 
 
0x8b의 경우 (10001011)2로 표현된다. 
 
반면, 
 
0x89의 경우 (10001001)2로 표현된다. 딱 봐도 d비트의 차이가 보이는가
 

 
Q. 다음 목표는 SIB의 경우 어떤 식으로 배치 해야 할지 음... 
 
=> 만약 ModR/M값이 2C라면 2C에 대응하는 Reg값은 그대로 써주고 SIB표에서 2C를 찾는다. 그리고 찾은 값을 [Base + Scale Index]의 형태로 작성하면 된다! 
 
간단한 예시를 들어보자. 예를 들어 
 
add ebp, [eax*2]는 => add ebp, DWORD PTR [eax + eax  * 1] 이렇게 표현된다. 
 
이를 기계어로 나타내면 "03 2c 00"이다. 하나 하나 분석해보자. 
 
03 :  add라는 Opcode의 Hex코드 
2C : Reg field는 EBP를 의미하고 ModR/M Field를 보면 [--][--]이므로 SIB를 살펴보자. 00이니까 그럼 Base가 000인 eax와 SS Index 00인 [eax]다. 
이를 열씨미 조합해보면 [eax + eax * 1]임을 알 수 있다. 
 
자세한 내용은 이 사이트에서 보길 바람. (설명이 쩐다.) 
 
 
 
 

 

 
 
 
Comments