[assembly] LEA 교육의 목적은 무엇입니까?

나를 위해, 그것은 펑키 MOV처럼 보인다. 그 목적은 무엇이며 언제 사용해야합니까?



답변

다른 사람들이 지적했듯이 LEA (부하 유효 주소)는 종종 특정 계산을 수행하기위한 “트릭”으로 사용되지만 이는 기본 목적이 아닙니다. x86 명령어 세트는 Pascal 및 C와 같은 고급 언어를 지원하도록 설계되었으며, 특히 배열 int 또는 작은 구조체 배열이 일반적입니다. 예를 들어 (x, y) 좌표를 나타내는 구조체를 고려하십시오.

struct Point
{
     int xcoord;
     int ycoord;
};

이제 다음과 같은 진술을 상상해보십시오.

int y = points[i].ycoord;

points[]의 배열은 어디 입니까 Point? 어레이의 기본 가정은 이미 EBX한 변수 i이다 EAX하고 xcoord그리고 ycoord각각 32 비트 (너무되어 ycoord구조체 오프셋 4 바이트로된다),이 문에 컴파일 될 수있다 :

MOV EDX, [EBX + 8*EAX + 4]    ; right side is "effective address"

이는 토지됩니다 yEDX. 8의 스케일 팩터는 각각 Point크기가 8 바이트 이기 때문 입니다. 이제 “주소”연산자와 함께 사용 된 것과 동일한 표현을 고려하십시오 :

int *p = &points[i].ycoord;

이 경우의 값이 ycoord아니라 주소를 원합니다 . 곳이다 LEA(부하 효과적인 주소)에서 제공됩니다. 대신의 MOV컴파일러는 생성 할 수 있습니다

LEA ESI, [EBX + 8*EAX + 4]

에 주소를로드합니다 ESI.


답변

로부터 “총회의 선” Abrash의 :

LEA메모리 어드레싱 계산을 수행하지만 실제로 메모리를 어드레싱하지는 않는 유일한 명령어입니다. LEA표준 메모리 주소 지정 피연산자를 허용하지만 계산 된 메모리 오프셋을 지정된 레지스터에 저장하는 것 외에는 범용 레지스터 일 수 있습니다.

그것은 우리에게 무엇을 제공합니까? ADD제공하지 않는 두 가지 :

  1. 2 개 또는 3 개의 피연산자로 덧셈을 수행하는 기능
  2. 결과를 임의의 레지스터 에 저장하는 능력 ; 소스 피연산자 중 하나만이 아닙니다.

그리고 LEA플래그를 변경하지 않습니다.

  • LEA EAX, [ EAX + EBX + 1234567 ]계산 EAX + EBX + 1234567(세 피연산자)
  • LEA EAX, [ EBX + ECX ]결과 EBX + ECX를 무시하지 않고 계산 합니다.
  • LEA EAX, [ EBX + N * EBX ](N은 1,2,4,8이 될 수 있음) 처럼 사용하면 상수로 곱하기 (2, 3, 5 또는 9 ).

다른 유스 케이스는 루프에 편리합니다 : 차이 LEA EAX, [ EAX + 1 ]와는 INC EAX그 후자의 변화입니다 EFLAGS하지만 전자는하지 않습니다; 이것은 CMP상태를 유지 합니다.


답변

의 또 다른 중요한 기능 LEA명령은 같은 조건 코드를 변경하지 않는다는 것입니다 CFZF같은 산술 명령어로 주소를 계산하는 동안, ADD또는 MUL한다. 이 기능은 명령어 간의 종속성 수준을 낮추므로 컴파일러 또는 하드웨어 스케줄러에 의해 추가 최적화를위한 공간을 만듭니다.


답변

모든 설명에도 불구하고 LEA는 산술 연산입니다.

LEA Rt, [Rs1+a*Rs2+b] =>  Rt = Rs1 + a*Rs2 + b

단지 shift + add 연산의 이름이 멍청하다는 것입니다. 그 이유는 이미 최고 등급의 답변에서 설명되었습니다 (즉, 높은 수준의 메모리 참조를 직접 매핑하도록 설계되었습니다).


답변

LEA 교육에 관한 또 다른 것. 레지스터에 3, 5 또는 9를 빠르게 곱하기 위해 LEA를 사용할 수도 있습니다.

LEA EAX, [EAX * 2 + EAX]   ;EAX = EAX * 3
LEA EAX, [EAX * 4 + EAX]   ;EAX = EAX * 5
LEA EAX, [EAX * 8 + EAX]   ;EAX = EAX * 9


답변

lea“로드 유효 주소”의 약어입니다. 소스 피연산자가 위치 참조의 주소를 대상 피연산자로로드합니다. 예를 들어, 다음과 같은 용도로 사용할 수 있습니다.

lea ebx, [ebx+eax*8]

단일 명령 으로 ebx포인터 eax항목을 64 비트 / 요소 배열로 더 이동 합니다. 기본적으로 x86 아키텍처에서 지원하는 복잡한 주소 지정 모드의 이점을 활용하여 포인터를 효율적으로 조작 할 수 있습니다.


답변

LEAa 를 사용하는 가장 큰 이유 MOV는 주소를 계산하는 데 사용하는 레지스터에서 산술을 수행해야하는 경우입니다. 효과적으로, “무료”에 대해 효과적으로 여러 레지스터에서 포인터 산술 연산을 수행 할 수 있습니다.

실제로 혼란스러워하는 것은 일반적으로 LEA비슷하게 작성 MOV하지만 실제로 메모리를 역 참조하지는 않는다는 것입니다. 다시 말해:

MOV EAX, [ESP+4]

그러면가 ESP+4가리키는 내용이로 이동합니다 EAX.

LEA EAX, [EBX*8]

이렇게하면 유효 주소 EBX * 8가 해당 위치에있는 주소 가 아닌 EAX로 이동합니다 . 보시다시피, a MOV는 더하기 / 빼기로 제한되는 반면 두 가지 요인 (확장)을 곱하는 것이 가능합니다 .