어셈블리어에서 movq(mov)는 크게 헷갈리지 않는다. 특정값을 이동하는 것. 괄호()로 쌓여있으면 주소에 접근하여 이동한다.
이때 source는 Register, Memory, Immediate 모두가 가능하고, dest는 Register와 Memory만 가능하다.
또한 D(Rb, Ri, S) 연산도 가능하다.
그렇다면 leaq(lea)는 무엇일까? lea는 Load Effective Address로, 뭔가 효율적인 '주소' 연산을 위해 설계된 것이다.
lea의 헷갈리는 점은 바로 기본적으로 source에 괄호()를 사용한다는 것이다. 괄호는 해당 Register에 있는 주소에 접근하는 포인터의 역할을 하는데, lea에서는 딱히 포인터라고 하기는 애매한 느낌이 있다.
다른 헷갈리는 점은 주소 연산을 위해 설계된 것과는 달리 효과적인 산술 연산을 위해 사용한다는 점이다. 주소 연산을 위한 것도 아니고 그냥 3을 곱하기 위하여 leaq (%rsi, %rsi, 2) 같은 걸 쓰고 있으면 갑자기 여기에 왜 괄호가 쓰여야 하지 라는 생각이 들 수밖에 없다.
결국 lea가 헷갈리는(불편한) 것들은 아래와 같이 이해하면 좀 더 편해지는 듯하다.
1. lea의 source는 괄호()와 함께 쓴다. lea에서만은 괄호가 메모리를 나타내는 것이 아니다.
&가 붙여져 있다고 생각하면 이해가 편할 수 있다. &가 있는데 포인터를 안 주고 그냥 값을 주면 오류가 발생하지 않겠는가? 그런 이유로 무조건 ()가 필요하다 생각하면 좋다.
2. lea의 시작은 빠른 주소 연산이었으나 어떻게 하다 보니 컴파일러가 산술연산을 빠르게 하기 위해 사용하게 되었다.
마지막으로 그렇다면 lea의 source에 괄호 없이 register을 주면 어떻게 될까? 이를 찾기 위해서 열심히 Stack overflow와 구글링 그리고 교재를 찾아봤으나, 그런 예시는 찾을 수 없었고, 질문을 하고 lea에는 반드시 괄호()가 필요하다는 답변을 받을 수 있었다. 이렇게 모든 것을 찾아보고 나서 나는 lea는 그냥 규칙적으로 반드시 ()를 써야 한다고 납득할 수 있었다.