2009-12-06 4 views

답변

62

은 DI/SI (또는 1985 년에 ASM을 배우지 않았다면 확장 된 부분)와 몇 가지 작업을 수행 할 수 있습니다. 이들 중에서

REP STOSB 
REP MOVSB 
REP SCASB 

마스크이다 각각 동작을 반복 기억 (= 질량), 로딩 스캔. 당신은 SI 및/또는 DI를 설정하여 어느 한 피연산자 또는 두 피연산자 모두를 가리키게 할 수 있습니다. 아마도 CX에 카운트를 넣고 찢어 버릴 수 있습니다. 이것은 한 번에 여러 바이트에서 작동하는 연산이며 CPU를 자동으로 처리합니다. 루프를 명시 적으로 코딩하지 않아도되므로 루프 코딩보다 루프를 효율적으로 수행합니다.

당신이 궁금해하는 경우를 대비해 : 조작을 어떻게 설정 하느냐에 따라 반복 된 저장은 값 0을 큰 인접한 메모리 블럭에 펀치하는 것과 같이 간단 할 수 있습니다. MOVSB는 하나의 버퍼 (모든 바이트 묶음)에서 다른 버퍼로 데이터를 복사하는 데 사용됩니다. 그리고 SCASB는 검색 기준과 일치하는 바이트를 찾는 데 사용됩니다 (일치 여부를 확인하는 것이 확실하지 않거나 무엇을 – 찾을 수 있는지).

해당 규칙의 대부분입니다. .

+5

과거의 최적화 팁 : * rep stosw *는 rep stosb *보다 훨씬 빠르므로 2와 2 바이트를 복사하면 당신이하려는 일은 손으로 최적화 한 16 비트 x86 어셈블리 코드에서 대신 사용하십시오 ... – Alexander

27

ESI가 가리키는 메모리에서 EDI가 가리키는 메모리로 효율적으로 데이터를 복사하는 MOVSB ​​및 MOVSW와 같은 Opcode. 따라서, 문자열 연산 외에

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

는 (MOVS/INS/STOS/CMPS/SCASB/W/D/Q 등)에 대한 다른 응답에서 언급 I가 있다는 것을 추가 원 "역시보다 암시 적으로 적어도 EDI/RDI를 사용하여 현대 "의 x86 어셈블리 명령어 :

SSE2 MASKMOVDQU (그리고 곧 AVX VMASKMOVDQU) 명령은 선택적으로 메모리에 XMM 레지스터에서 바이트 쓰기는 EDI/RDI에 의해 지적했다.

63

SI = 소스 인덱스
DI = 대상 인덱스

다른 사람들이 지적했듯이, 그들은 문자열 지침에 특별한 용도가 있습니다. 리얼 모드 프로그래밍의 경우, ES 세그먼트 레지스터는

movsb es:di, ds:si 

SI와 DI는 범용 인덱스 레지스터로 사용할 수 있습니다 같이 SIDIDS과 함께 사용해야합니다. 예를 들어,이 ebp+12argv 포함 여기서 C 소스 코드

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

ebxj이다

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

로 컴파일하고 edisrcidx있다.세 번째 명령은 edi을 4로 다중화하고 ebp을 0x54 (위치는 srcp)만큼 추가합니다. 주소 주변의 대괄호는 간접 참조를 나타냅니다.


내가 그것을보고 어디 기억할 수 있지만 하지만 this 그것의 대부분을 확인하고, this (슬라이드 17) 기타 :

AX = 누적
DX = 더블 워드 누적
CX = 카운터
BX =베이스 레지스터

그들은 범용 레지스터처럼 보이지만, (예기치 않게?) 중 하나를 사용하는 구조 - 그러나 어느 것이 - 암묵적으로?

3

대량 작업에 사용되는 레지스터 외에도 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

항을 참조 C가 명령 줄 인수를 보는 방법 12.8.

64 비트 호출 규칙은 32 비트 호출 규칙과 다르므로이 레지스터가 통화 보존인지 여부는 확실하지 않습니다.

+0

"신성한"이라는 말은 들어 본 적이 없지만 대부분의 사람들이 "휘발성"/ "비 휘발성"이라고 부르는 것을 묘사했습니다. 또는 "피 호출자 저장 됨"대 "호출자 저장 됨". 나는 그들이 실제로 어디서나 구원을 얻는다는 것을 암시하지 않기 때문에 "전화가 보존 된"/ "전화가 걸렸습니다"를 좋아합니다. 어쨌든 ESI/RSI와 EDI/RDI는 x86-64 System V ABI에서 통화 보존되지 않습니다. –

+0

또한 일반적인 32 비트 호출 규칙에서 통화 보존으로 EBP 및 ESP를 나열하는 것을 잊었습니다. –

+1

어쨌든 꽤 좋은 지적입니다. 실제 코드에서는 호출 규칙에 따라 EDI/ESI를 선택할 가능성이 높습니다. –

관련 문제