Intel x86 Assembly Language & Microarchitecture
최적화
수색…
소개
비고
의심 스러울 때, 당신은 항상 포괄적 인 인텔 64 및 IA-32 아키텍처 최적화 레퍼런스 매뉴얼을 참조 할 수 있습니다. 이것은 x86 아키텍쳐 자체의 훌륭한 자원입니다.
레지스터 비공개
레지스터를 0으로 만드는 명백한 방법은 MOV 를 0 으로 만드는 것입니다 (예 :
B8 00 00 00 00 MOV eax, 0
이것은 5 바이트 명령어입니다.
플래그 ( MOV 가 플래그에 영향을주지 않습니다)를 망가 뜨리려한다면 XOR 명령을 사용하여 레지스터를 비트 단위로 XOR 할 수 있습니다.
33 C0 XOR eax, eax
이 명령어는 2 바이트 만 필요하며 모든 프로세서에서 더 빠르게 실행 됩니다.
캐리 플래그를 레지스터로 이동
배경
캐리 ( C ) 플래그가 레지스터에 넣으려는 값을 보유하고 있다면 순진한 방법은 다음과 같이하는 것입니다.
mov al, 1
jc NotZero
mov al, 0
NotZero:
'sbb'사용
점프를 피하면서보다 직접적인 방법은 "차용과 함께 빼기"를 사용하는 것입니다.
sbb al,al ; Move Carry to al
C 가 0이면 al 은 0이됩니다. 그렇지 않으면 0xFF ( -1 )가됩니다. 0x01 이 필요하면 다음을 추가하십시오.
and al, 0x01 ; Mask down to 1 or 0
찬성
- 같은 크기의 약
- 2 개 또는 1 개의 적은 명령어
- 비싼 점프
단점
- 이 기술에 익숙하지 않은 독자에게는 불투명합니다.
- 다른 플래그를 변경합니다.
0에 대한 레지스터 테스트
배경
레지스터에 0이 들어 있는지 알아 보려면 순진한 방법은 다음과 같습니다.
cmp eax, 0
그러나 이것에 대한 opcode를 보면 다음과 같이 나타납니다 :
83 F8 00 cmp eax, 0
test 사용
test eax, eax ; Equal to zero?
당신이 얻는 opcode를 검사하십시오 :
85 c0 test eax, eax
찬성
- 2 바이트 만!
단점
- 이 기술에 익숙하지 않은 독자에게는 불투명하다.
이 기술에 대한 Q & A 질문을 살펴볼 수도 있습니다.
리눅스 시스템 콜은 덜 부 풀린다.
32 비트 리눅스에서 시스템 호출은 일반적으로 sysenter 명령어를 사용하여 수행됩니다 (오래된 프로그램은 현재 사용되지 않는 int 0x80 사용하기 때문에 보통 말합니다). 그러나 이것은 프로그램에서 많은 공간을 차지할 수 있습니다. 단축하고 속력을 높이기 위해 모서리를자를 수 있습니다.
이는 일반적으로 32 비트 Linux에서 시스템 호출의 레이아웃입니다.
mov eax, <System call number>
mov ebx, <Argument 1> ;If applicable
mov ecx, <Argument 2> ;If applicable
mov edx, <Argument 3> ;If applicable
push <label to jump to after the syscall>
push ecx
push edx
push ebp
mov ebp, esp
sysenter
그것은 엄청난 권리 다! 그러나이 혼란을 피하기 위해 우리가 끌어낼 수있는 몇 가지 트릭이 있습니다.
첫 번째는 ebp를 3 개의 32 비트 레지스터 크기 (12 바이트)만큼 줄인 esp 값으로 설정하는 것입니다. 이것은 ebp, edx 및 ecx를 쓰레기로 덮어 쓰는 것이 좋습니다 (예 : 어쨌든 그 레지스터에 직접 값을 이동시킬 때와 같이). LEA 명령을 사용하여이 작업을 수행 할 수 있으므로 필요하지 않습니다. ESP 자체의 가치에 영향을줍니다.
mov eax, <System call number>
mov ebx, <Argument 1>
mov ecx, <Argument 2>
mov edx, <Argument 3>
push <label to jump to after the syscall>
lea ebp, [esp-12]
sysenter
그러나 시스템 호출이 sys_exit이라면 아무것도 수행하지 않고 도망 갈 수 있습니다!
mov eax, 1
xor ebx, ebx ;Set the exit status to 0
mov ebp, esp
sysenter
3 또는 5로 곱하기
배경
레지스터와 상수의 곱을 얻고 다른 레지스터에 저장하려면 순진한 방법은 다음과 같습니다.
imul ecx, 3 ; Set ecx to 5 times its previous value
imul edx, eax, 5 ; Store 5 times the contend of eax in edx
lea 사용
곱셈은 값 비싼 연산입니다. 이동과 추가의 조합을 사용하는 것이 더 빠릅니다. esp 또는 rsp 가 아닌 32 비트 또는 64 비트 레지스터의 경쟁을 3 또는 5 씩 섞는 특별한 경우에 lea 명령을 사용할 수 있습니다. 이것은 주소 계산 회로를 사용하여 제품을 신속하게 계산합니다.
lea ecx, [2*ecx+ecx] ; Load 2*ecx+ecx = 3*ecx into ecx
lea edx, [4*edx+edx] ; Load 4*edx+edx = 5*edx into edx
많은 어셈블러들도 이해할 것입니다.
lea ecx, [3*ecx]
lea edx, [5*edx]
다른 모든 가능한 피승수가 ebp 또는 rbp 경우, 결과 명령어 길이는 imul 을 사용할 때와 동일합니다.
찬성
- 훨씬 더 빨리 실행
단점
- 당신의 피승수 인 경우
ebp또는rbp는 한 바이트 이상 그들을 사용합니다imul - 어셈블러가 바로 가기를 지원하지 않는다면 더 많이 입력하십시오.
- 이 기술에 익숙하지 않은 독자에게는 불투명하다.