Notice
Recent Posts
01-24 19:43
관리 메뉴

프로그래밍 잡화점

Load Effective Address 본문

카테고리 없음

Load Effective Address

Luana7 2024. 11. 14. 23:10

어셈블리 기본 Instruction중 하나인 LEA(Load Effective Address)에 대해 알아보자.

Effective Address가 무엇인가?

예전에 어셈블리와 기계어에 대한 포스트에서 언급한 바 있는 SIB란 녀석이 있었다.

 

Base + Scale * Index로 계산되는데, 여기에 Displacement까지 더해서 나온 주솟값.

이 주솟값을 Effective Address, 한국어론 유효 주소라고 부른다.

 

 

그렇다면 어셈블리에서 LEA는 주로 어디에 사용되는가?

 

가장 간단한 예시로는 특정 레지스터의 주소를 기반으로 다른 주소를 구할 때 사용할 수 있을 것이다.

 

예를 들어, 가장 간단한 함수에서 사용하는 변수에 접근한다고 생각해보자.

그럼 다음과 같은 코드를 작성할 수 있을 것이다.

...
    ; int i : [ebp-4]
    
    ; eax = i;
    mov eax, [ebp-4]
    
    ; i = 3;
    mov eax, 3
    mov [ebp-4], eax
...

 

그렇다면 변수의 주소를 얻어와야 한다면?

 

특정 레지스터에 ebp 주소를 넣고 sub 4를 할 수도 있을 것이다.

 

그러나 어셈블리에선 LEA 명령어를 통해서 더 간소화된 방식을 지원하는 것이다.

...
    ; int i : [ebp-4]
    
    ; eax = &i; no lea
    mov eax, ebp
    sub eax, 4
    
    ; eax = &i; use lea
    lea eax, [ebp-4]
...

 

이 외에도 SIB에서 Scale과 Index를 사용하여 배열 인덱싱에도 적용할 수 있을 것이다.

(직접 코드를 작성해보기를 바란다.)

 

 

필자가 이 글을 쓰는데에는 추가적인 이유가 있다.

 

이러한 유효한 주소를 가져오는데에만 사용될 것만 같은 이 Instruction은 의외의 기능으로도 사용되고 있다.

 

 

다음 C언어 코드를 보자.

r = a + 4;

 

 

어셈블리에서는 다음과 같이 표현될 것이다.

...
    ; int r : [ebp-4], int a : [ebp-8]
    ; r = a + 4
    mov eax, [ebp-8]
    add eax, 4
    mov [ebp-4], eax
...

 

이 코드에서 add 대신 재미난 방법을 사용해 이를 처리할 수 있다.

 

LEA는 해당 주소가 실제 접근할 수 없는 주소라도 연산을 해준다(!!)

 

즉, 위에 코드가 다음과 같이 될 수도 있다는 이야기이다.

...
    ; int r : [ebp-4], int a : [ebp-8]
    ; r = a + 4
    mov eax, [ebp-8]
    lea eax, [eax+4]
    mov [ebp-4], eax
...

 

 

"엥? 별 차이 없는거 아니에요? 그냥 add하면 되지 왜 lea를 써요?"

 

맞는 이야기이다만, 이번에는 다른 예제를 살펴보자.

 

r = a * 4 + 3;

 

이번에는 식이 조금 더 복잡해졌다. 어셈블리 코드를 보자.

...
    ; int r : [ebp-4], int a : [ebp-8]
    ; r = a * 4 + 3
    mov eax, [ebp-8]
    ; mul 최적화. 나중에 포스팅을 통해 따로 다룰 예정.
    shl eax, 2
    add eax, 3
    mov [ebp-4], eax
...

 

그럼 이 코드를 LEA를 사용해서 만들어 볼 수 있을까?

 

...
    ; int r : [ebp-4], int a : [ebp-8]
    ; r = a * 4 + 3
    mov eax, [ebp-8]
    lea eax, [eax*4+3]
    mov [ebp-4], eax
...

 

훨씬 간단한 코드가 만들어졌다.

(SIB의 특성상, Scale에는 1, 2, 4, 8 (3, 5, 9) 만 사용될 수 있음에 주의.)

 

이 뿐만 아니라, SIB의 특성상 상수를 제외하고도 레지스터가 추가적으로 들어갈 수 있어, 더 많은 단축이 가능한 셈이다.

 

LEA를 사용하는데 있어 좋은 점은 이뿐만이 아니다.

 

lea를 사용하게 되면, 연산을 하면서 생기는 레지스터 소모가 사라진다는 것이다.

 

즉, 특정 레지스터의 값을 바꾸지 않으면서 연산을 진행하여 결과를 도출해낼 수 있다는 의미이다.

 

 

이러한 LEA의 사용은 많은 상황에서 쓰일 수 있는 것은 아니지만, 간간히 특정 식에 대해 최적화를 진행할 수 있을 것이다.

 

 

Comments