2012-10-17 4 views
1

저는 배우면서 QWORD를 많이 사용하는 어셈블러 변환 (x86-32bit)에서 작업하고 있습니다. 이제는 내 참조 자료가 32 비트 레지스터로 분할하는 것 이상의 값으로 작업하는 데 아무런 관련이 없습니다. 나는 그들이 옛날에있는 것 같아. 최신 프로세서에는 mmx 및 sse 명령어 등이 있습니다. 이 문제를 해결하기위한 지침을 잘 살펴 보았습니까? QWORD 값에 대한 작업을 처리하는 가장 좋은 방법은 무엇입니까?QWord로 작업하기

답변

1

64 비트 정수로 작업하는 것이 쉽지 않을 수도 있습니다. 수행 할 작업의 유형에 따라 다릅니다.

불리언 산술 (AND, OR, XOT, NOT)의 경우 모든 길이의 정수를 분할하는 것만으로 쉽게 작업 할 수 있습니다.

덧셈과 뺄셈을 위해이 함께 ADC 체인에 의해 길이의 정수를 지원하기 위해 쉽게 또는 SBB 지침 (대출 빼기) (캐리와 함께 추가). 예 (128 비트)의 경우 :

add eax,[value] 
adc ebx,[value+4] 
adc ecx,[value+8] 
adc edx,[value+12] ;edx:ecx:ebx:eax = 128-bit result of addition 

부정은 감산 (-x = 0 - x)이다.

왼쪽/오른쪽으로 시프트 할 때 SHLD 또는 SHRD 명령을 연결하여 길이가 다른 정수를 쉽게 지원할 수 있습니다. (예를 들어, 128 비트) 시프트 카운트가 너무 크면

shld edx,ecx,12 
shld ecx,ebx,12 
shld ebx,eax,12 
shl eax,12   ;edx:ecx:ebx:eax = 128-bit result of shift left by 12 

(예에서는 44 비트만큼 왼쪽으로 시프트 할) 다음 MOD (32)를 첫 번째로 데이터를 이동하고 "일본어 카운트로 전환해야 ". 예 :

mov edx,ecx 
mov ebx,ebx 
mov ebx,eax 
mov eax,0   ;edx:ecx:ebx:eax = original value shifted left by 32 
shld edx,ecx,12 
shld ecx,ebx,12 
shld ebx,eax,12 
shl eax,12   ;edx:ecx:ebx:eax = original value shifted left by 44 

곱셈의 경우 CPU는 "32 비트 * 32 비트 = 64 비트 결과"를 지원합니다. 더 큰 것이면 너비 정수를 임의의 너비 정수와 곱할 수 있습니다. 이것은 base4294967296 (각 숫자는 32 비트 정수)을 사용하는 것을 제외하고는 base10 (각 숫자는 0에서 9까지의 값)을 사용하여 많은 수를 손으로 곱하는 것과 같습니다. 예를 들어, 사용하여 유효한 시간 (58)에 의해 다수의 (34)에 당신이 할 것 : 위치 추적을 유지하면서

result_digit0to1 = 4*8 = 32 
result_digit1to2a = 4*5 = 20 
result_digit1to2b = 3*8 = 24 
result_digit2to3 = 3*5 = 15 
result = result_digit0to1 + (result_digit1to2 + result_digit1to2) * 10 + result_digit2to3 * 100; 
result = 32 + (20 + 24) * 10 + 15 * 100 
result = 32 + 440 + 1500 
result = 1972 

기본적으로, 하나 개의 번호의 각 숫자를 다른 숫자의 각 숫자를 곱/숫자의 크기; 결과는 중간 결과의 합계입니다. 대한

"64 비트 * 64 비트 = 128 = 비트 결과"당신이 좋아하는 일을 할 것입니다 : 그러나

result_bits0to63 = first_bits0to31 * second_bits0to31; 
result_bits32to95a = first_bits32to64 * second_bits0to31; 
result_bits32to95b = first_bits0to31 * second_bits32to64; 
result_bits64to128 = first_bits32to64 * second_bits32to64; 
result = result_bits0to63 + ((result_bits32to95a + result_bits32to95b) << 32) + (result_bits64to128 << 64) 

, 부호없는 정수에 대해이 경우에만 작동합니다. 부호있는 정수의 경우 부호 비트를 제거하고 부호없는 곱셈을 수행 한 다음 결과에 부호 (result_sign_bit = first_sign_bit XOR second_sign_bit)를 설정해야합니다.

분할의 경우, 결국 "base2 long division"이됩니다. 가장 높은 세트 비트를 잃지 않고 가능한 한 왼쪽으로 제수를 이동합니다 ("비트 이동"을 추적하는 동안). 그런 다음 나누어 진 값과 비교하면서 한 번에 한 비트 씩 원래 위치로 다시 이동합니다. 쉬프트 된 제수가 나뉘는 값보다 작 으면, 나뉘는 값에서 쉬프트 된 제수를 빼고 결과에서 해당 비트를 설정합니다.제수가 원래 위치로 돌아온 후에 나뉘는 값은 나머지가됩니다.

곱셈과 마찬가지로 분류는 실제로 부호없는 정수에서만 작동하며 사전에 부호 비트를 제거한 다음 부호없는 나누기를 수행 한 다음 나중에 부호와 결과 및 나머지를 설정해야합니다.

이 모든 것을 이해한다면; 그러면 64 비트 CPU를 사용하는 512 비트 연산이나 16 비트 CPU를 사용하는 65536 비트 연산 또는 CPU의 "임의의 폭"연산을 수행 할 수 있습니다.

0

최선의 방법은 코스에서 명시 적으로 금지하지 않는 한 QWORD에서 작동하는 명령어를 사용하는 것입니다. 그런 다음 32 비트 레지스터를 사용하여 작업을 수행해야합니다. QWORD를 사용하여 기본 논리 명령어를 수행 할 수있는 몇 가지 서브 루틴을 작성할 수 있습니다.

+0

이것은 물론 작동하지 않지만 ASM을 배우는 동안 (나는 결과를 합리적으로 * 빨리 원합니다.) 가장 잘 작동하는 것이 무엇인지 알고 싶습니다. – Glenn1234

+0

그러면 이미 말했듯이 : * 가장 좋은 방법은 QWORDs *로 작동하는 명령어를 사용하는 것입니다. 이것은 32 비트 명령어로 수행하는 것보다 빠릅니다. – m0skit0