간단 지식/System Programming

05. movq와 leaq의 address 계산 방식

납작한돌맹이 2020. 11. 6. 05:26
반응형

movq의 주소 지정 방식의 가장 일반적인 형식과 그에 따른 메모리 계산식은 다음과 같다.

D(Rb, Ri, S), MEM[Reg[Rb] + S*Reg[Ri] + D]

D: 일정 배수. 1, 2, 4 byte중 하나.

    임의의 데이터 구조에 대해 임의의 offset을 정해주는 용도.

Rb: 베이스 레지스터. %rax를 포함한 16개의 레지스터 중 하나.

     명시되지 않으면 0으로, hw가 작동할 때 D, Ri, S가 무슨 값을 갖던 간에 신경쓰지 않는다.

     메모리의 base 주소를 알려주는 용도.

Ri: 인덱스 레지스터. %rsp를 제외한 모든 레지스터.

    명시되지 않으면 0.

S: scale, size를 의미. 어셈블리어를 지원하는 정수들.

   1, 2, 4, 8 중 하나. 명시되지 않으면 1.

 

아래는 위 기본 형태를 약간씩 변형한 특수 형식이다.

D(Reg), MEM[Reg + D]

(Rb, Ri), MEM[Reg[Rb] + Reg[Ri]]

D(Rb, Ri), MEM[Reg[Rb] + Reg[Ri] + D]

(Rb, Ri, S), MEM[Reg[Rb] + S*Reg[Ri]]

 

아래 예제를 통해 학습해보자.

%rdx = 0xf000, %rcs = 0x0100 일때,

ex1. 0x8(%rdx) = 0xf000 + 0x8 = 0xf008

ex2. (%rdx, %rcx) = 0xf000 + 0x0100 = 0xf100

ex3. (%rdx, %rcx, 4) = 0xf000 + 4*0x0100 = 0xf400

ex4. 0x80( , %rdx, 2) = 0 + 2*0xf000 + 0x80 = 0x1e080 

 

아직도 이 계산방법이 감이 오지 않을 수 있다. 너무 생소할 수 있지만 생각 외로 흔히 아는 곳에 공식이 적용되어 있다. 바로 배열의 주소공간이다. 일전에 c언어 카테고리의 포인터에서 배열을 포인터로 표현할 수 있다고 했다. (링크:

2020/09/12 - [1학년/c언어] - 02. 포인터, 동적메모리할당함수, 포인터배열)

int a[N]; 이란 배열에서, a[0], a[1], ... a[N]은 포인터로 *(a), *(a+1), .... *(a+N)으로 표현할 수 있다고 하였다. int형은 메모리에서 4byte를 차지하기 때문에 실제로는 *(a+n)*4 가 될 것이다. 여기서 위 메모리 공식의 형태가 보인다. 특수 형식 4(Rb, Ri, S)에 해당하며 대입해보면 ( , a+n, 4)이다. 이 외에도 구조체 배열의 offset에서도 이러한 주소계산 방식이 적용됨을 확인할 수 있는데 이에 대해선 스스로 고민해보자.


movq와 유사한 명령어로 leaq가 있다. Load Effective Address의 약자 LEA에 quad woad의 q가 붙은 것으로, 64bit에서 메모리를 참조하는 operand(피연산자)의 구조를 의미한다. 메모리 피연산자는 두가지 요소로 구성된다. 첫번째 요소, segment selector, 두번째 요소 offset or linear address. 여기서 offset에 주목해보자.

offset은 4가지로 구성된다.

1. base: 임의의 레지스터 안에 있는 값

2. index: 임의의 레지스터 안에 있는 값

3. scale factor: index에 곱해줄 2, 4, 8 중 하나의 정수

4. displacement: 8, 16, 32 bit 중 하나의 값

이 4가지 요소들을 이용한 계산식 B + I*S + D으로 최종 offset을 구할 수 있으며 이게 바로 effective address, 즉 LEA가 되는 것이다. 

 

이렇게 보니 movq와 leaq의 연산식이 똑같다는 것을 알 수 있다. 그런데 둘을 굳이 구분짓는 것에는 충분한 이유가 있다. 둘 다 메모리 참조 없이 주소를 계산할 수 있는 명령어지만, movq는 메모리 operand가 참조하는 메모리의 값을 Dest operand로 대입한다. 즉 계산 후 메모리에 접근하여 메모리에 저장된 값을 가져온다는 의미이다. 반면에 leaq는 계산한 값을 취하기만 할 뿐 메모리에 접근하지는 않는다.

 

 

 

 

(이 글이 도움이 됐다면 광고 한번씩만 클릭 해주시면 감사드립니다, 더 좋은 정보글 작성하도록 노력하겠습니다 :) )

반응형