ESI 및 EDI 레지스터의 목적?


답변:


77

DI / SI (또는 1985 년에 ASM을 배우지 않은 경우 확장 된 대응) 로만 할 수있는 몇 가지 작업이 있습니다 . 이들 중

REP STOSB
REP MOVSB
REP SCASB

각각 반복 (= 대량) 저장,로드 및 스캔 작업입니다. 당신이하는 일은 하나 또는 두 피연산자를 가리 키도록 SI 및 / 또는 DI를 설정하고 아마도 CX에 카운트를 넣은 다음 찢어 버리십시오. 이들은 한 번에 많은 바이트에서 작동하는 작업이며 CPU를 자동으로 설정합니다. 루프를 명시 적으로 코딩하지 않기 때문에 수작업으로 코딩 한 루프보다 더 효율적으로 (보통) 작업을 수행합니다.

궁금한 점이있는 경우를 대비하여 작업을 설정하는 방법에 따라 반복 저장은 값 0을 큰 연속 메모리 블록에 펀칭하는 것과 같이 간단 할 수 있습니다. MOVSB는 한 버퍼에서 다른 버퍼로 데이터를 복사하는 데 사용됩니다. SCASB는 일부 검색 기준과 일치하는 바이트를 찾는 데 사용됩니다 (동등성에 대해서만 검색하는지 또는 무엇을 찾을 수 있는지 확실하지 않습니다. :))

그게 바로 그 regs의 대부분입니다.


7
과거의 최적화 팁 : 담당자 stosw은 훨씬 빨리보다 렙 stosb 는 것을, 사용을하려고하는지와이 두 바이트 맞는 복사 그렇다면, 대신에 당신의 손에 최적화 된 16 비트의 x86 어셈블리 코드에서 ...
— 알렉산더

88

SI= 소스 색인
DI= 목적지 색인

다른 사람들이 지적했듯이 그들은 문자열 명령어와 함께 특별한 용도를 가지고 있습니다. 리얼 모드 프로그래밍의 경우, ES세그먼트 레지스터와 함께 사용되어야 DI하고 DS와 SI같이

movsb  es:di, ds:si

SI 및 DI는 범용 인덱스 레지스터로도 사용할 수 있습니다. 예를 들어, C소스 코드

srcp [srcidx++] = argv [j];

컴파일

8B550C         mov    edx,[ebp+0C]
8B0C9A         mov    ecx,[edx+4*ebx]
894CBDAC       mov    [ebp+4*edi-54],ecx
47             inc    edi

경우는 ebp+12포함 argv, ebx이다 j, 그리고 edi있다 srcidx. 세 번째 명령어는 edi4로 다중화를 사용 하고 ebp오프셋을 0x54 (의 위치 srcp)로 추가합니다. 주소 주위의 대괄호는 간접적임을 나타냅니다.


나는 그것을보고 위치를 기억하지만, 수는 없지만 이 확인한다 대부분의 그것의, 그리고 이 (슬라이드 17) 기타 :

AX= 누산기
DX= 더블 워드 누산기
CX= 카운터
BX= 기본 레지스터

범용 레지스터처럼 보이지만 (예기치 않게?) 그중 하나를 사용하지만 어떤 것을 암시 적으로 사용하는 명령어가 많이 있습니다.


37

ESI가 가리키는 메모리에서 EDI가 가리키는 메모리로 데이터를 효율적으로 복사하는 MOVSB ​​및 MOVSW와 같은 Opcode. 그러므로,

mov esi, source_address
mov edi, destination_address
mov ecx, byte_count
cld
rep movsb ; fast!

12

다른 답변에서 언급 된 문자열 연산 (MOVS / INS / STOS / CMPS / SCASB / W / D / Q 등) 외에도 암시 적으로 사용하는 "현대적인"x86 어셈블리 명령이 더 있다는 것을 추가하고 싶습니다. 최소 EDI / RDI :

SSE2 MASKMOVDQU(및 곧 출시 될 AVX VMASKMOVDQU) 명령어는 XMM 레지스터의 바이트를 EDI / RDI가 가리키는 메모리에 선택적으로 기록합니다.


6

대량 연산에 사용되는 레지스터 외에도 32 비트 호출 규칙에서 함수 호출 (호출 보존)을 통해 보존되는 속성에 유용합니다. ESI, EDI, EBX, EBP, ESP는 통화 보존되는 반면 EAX, ECX 및 EDX는 통화 보존되지 않습니다. 호출 보존 레지스터는 C 라이브러리 함수에 의해 존중되며 해당 값은 C 라이브러리 함수 호출을 통해 유지됩니다.

그의 어셈블리 언어 책에있는 Jeff Duntemann에는 명령 줄 인수를 인쇄하기위한 예제 어셈블리 코드가 있습니다. 이 코드는 esi 및 edi를 사용하여 카운터를 저장합니다. C 라이브러리 함수 printf에 의해 변경되지 않습니다. eax, ecx, edx와 같은 다른 레지스터의 경우 C 라이브러리 함수에서 사용되지 않는다는 보장이 없습니다.

https://www.amazon.com/Assembly-Language-Step-Step-Programming/dp/0470497025

섹션 12.8 C가 명령 줄 인수를 보는 방법을 참조하십시오.

64 비트 호출 규칙은 32 비트 호출 규칙과 다르며 이러한 레지스터가 호출 보존 여부는 확실하지 않습니다.


나는 대부분의 사람들이 "휘발성"/ "비 휘발성"이라고 부르는 것을 "신성"이라고 부르는 것을 "신성"이라고 부르는 것을 들어 본 적이 없다. 나는 "call-preserved"/ "call-clobbered"를 좋아하는데, 그것이 그들이 실제로 어디에서나 구원 받았다는 것을 의미하지 않기 때문입니다. 어쨌든 ESI / RSI 및 EDI / RDI는 x86-64 System V ABI에서 호출 보존되지 않습니다.
— Peter Cordes

또한 EBP 및 ESP를 일반적인 32 비트 호출 규칙에 보존 된 호출로 나열하는 것을 잊었습니다.
— Peter Cordes

1
어쨌든, 그것은 꽤 좋은 지적입니다. 실제 코드에서는 명령에 대해 특별하기 때문에 호출 관례 이유에 따라 EDI / ESI를 선택할 가능성이 더 큽니다.
— Peter Cordes

나는 통화 보존을 좋아합니다. 나는 똑같이 대답을 업데이트했습니다. 검토해 주셔서 감사합니다.
— 제이 라즈
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.