기본 색인 주소 지정 모드

2009. 8. 9. 04:31


아래의 코드는 어느 바이너리의 특정 함수를 objdump 로 디스어셈블한 것이다.

사용자 삽입 이미지


 0x8048508에 있는 구문을 보자

     lea    (%edx, %eax, 1), %eax
   
  주소를 eax 에 넣긴 하는거 같은데 어떻게 계산이 이루어지는 지 모르겠다. 도와줘요 IDA~~
  
사용자 삽입 이미지
 

AT&T 문법에 맞춰서 디스어셈블되면  

lea   eax, [edx+eax]  로 바뀐 것을 볼 수 있다.

구글링을 해보니 리눅스 어셈블러: GAS와 NASM 비교 라는 글에서 다음과 같은 설명을 찾을 수 있었다.



NASM: mov al, byte [ebx + esi]

GAS: movb (%ebx, %esi, 1), %al

이런 방식은 기본 색인 주소 지정 모드다. 여기서 구성요소가 세 개 등장한다. 첫째는 기본 주소, 둘째는 색인 레지스터, 셋째는 승수(乘數)다. 메모리 위치에서 접근하는 바이트 숫자를 결정하기란 불가능하므로 주소를 지정한 메모리 총량을 찾아내기 위한 방법이 필요하다. NASM은 byte 연산자를 사용해 자료에서 한 바이트가 이동했음을 어셈블러에 알려준다. GAS에서는 니모닉에 b, w, l 접미사를 붙이는(예를 들어, movb) 동시에 승수를 사용해 이런 문제를 해결한다. 처음 보면 GAS 구문이 좀더 복잡해보일 수도 있다.

GAS에서 일반적인 기본 색인 주소 지정 형식은 다음과 같다.

%segment:ADDRESS (, index, multiplier)

또는

%segment:(offset, index, multiplier)

또는

%segment:ADDRESS(base, index, multiplier)

이 공식을 사용해 최종 주소를 계산한다.

ADDRESS or offset + base + index * multiplier.

따라서 바이트에 접근하려면 승수는 1이 되며, 워드에 접근하려면 승수는 2가 되며, 더블 워드에 접근하려면 승수가 4가 되어야 한다. 물론 NASM은 좀더 단순한 구문을 사용한다. 따라서 NASM으로 상기 공식을 풀어쓰면 다음과 같다.

Segment:[ADDRESS or offset + index * multiplier]

각각 메모리 1, 2, 4 바이트에 접근하도록 byte, word, dword 접두사를 메모리 주소 앞에 표시한다.



즉, movb (%ebx, %esi, 1), %al 구문으로 설명한다면  

ebx(address or offset) 의 값에 esi(index)를 더해서 al 레지스터로 옮긴다.
3번째 인자로 인덱스를 byte, word, dword 단위로 조정할 수 있으며 위의 코드에서는  
바이트(1) 단위로 접근하는 것을 알 수 있다.
 


'Code > assembly' 카테고리의 다른 글

move 명령어  (0) 2010.09.07

badcob Code/assembly