나를 위해, 그것은 펑키 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"
이는 토지됩니다 y
에 EDX
. 8의 스케일 팩터는 각각 Point
크기가 8 바이트 이기 때문 입니다. 이제 “주소”연산자와 함께 사용 된 것과 동일한 표현을 고려하십시오 :
int *p = &points[i].ycoord;
이 경우의 값이 ycoord
아니라 주소를 원합니다 . 곳이다 LEA
(부하 효과적인 주소)에서 제공됩니다. 대신의 MOV
컴파일러는 생성 할 수 있습니다
LEA ESI, [EBX + 8*EAX + 4]
에 주소를로드합니다 ESI
.
답변
로부터 “총회의 선” Abrash의 :
LEA
메모리 어드레싱 계산을 수행하지만 실제로 메모리를 어드레싱하지는 않는 유일한 명령어입니다.LEA
표준 메모리 주소 지정 피연산자를 허용하지만 계산 된 메모리 오프셋을 지정된 레지스터에 저장하는 것 외에는 범용 레지스터 일 수 있습니다.그것은 우리에게 무엇을 제공합니까?
ADD
제공하지 않는 두 가지 :
- 2 개 또는 3 개의 피연산자로 덧셈을 수행하는 기능
- 결과를 임의의 레지스터 에 저장하는 능력 ; 소스 피연산자 중 하나만이 아닙니다.
그리고 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
명령은 같은 조건 코드를 변경하지 않는다는 것입니다 CF
와 ZF
같은 산술 명령어로 주소를 계산하는 동안, 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 아키텍처에서 지원하는 복잡한 주소 지정 모드의 이점을 활용하여 포인터를 효율적으로 조작 할 수 있습니다.
답변
LEA
a 를 사용하는 가장 큰 이유 MOV
는 주소를 계산하는 데 사용하는 레지스터에서 산술을 수행해야하는 경우입니다. 효과적으로, “무료”에 대해 효과적으로 여러 레지스터에서 포인터 산술 연산을 수행 할 수 있습니다.
실제로 혼란스러워하는 것은 일반적으로 LEA
비슷하게 작성 MOV
하지만 실제로 메모리를 역 참조하지는 않는다는 것입니다. 다시 말해:
MOV EAX, [ESP+4]
그러면가 ESP+4
가리키는 내용이로 이동합니다 EAX
.
LEA EAX, [EBX*8]
이렇게하면 유효 주소 EBX * 8
가 해당 위치에있는 주소 가 아닌 EAX로 이동합니다 . 보시다시피, a MOV
는 더하기 / 빼기로 제한되는 반면 두 가지 요인 (확장)을 곱하는 것이 가능합니다 .
![](http://daplus.net/wp-content/uploads/2023/04/coupang_part-e1630022808943-2.png)