배가 된 정수 정밀도는 특별한 경우에 불과합니다. 임의의 정밀도 . 어셈블리 언어의 수준에서 이것이 어떻게 구현되는지는 ISA에 달려 있습니다. (비록 여러분이 x86에 대해 특별히 질문을했지만, 나는 몇 가지 추가 정보를 제공 할 것입니다.)
더하기 및 빼기를 위해 많은 ISA (예 : ARM, Power, x86)는 빌려 (차용을 위해 차용) 비트를 제공하고 차용 명령어를 사용하여 특수 가산 및 빼기를 제공합니다.
ADD r1, r2, r3; // r1 = r2 + r3, set or clear carry bit
ADDC r4, r5, r6; // r4 = r5 + r6 + carry bit (also sets/clears carry)
일부 ISA (예 : 알파 (항상 64 비트였던 MIPS)는 캐리 비트 및 특수한 덧셈 / 뺄셈 명령어를 제공하지 않습니다. 이들은 결과가 피연산자 중 하나보다 작은 지 여부를 테스트하기 위해 set-on-less-than 명령어 (레지스터가 0보다 작거나 1보다 작은 경우 레지스터를 설정)를 사용할 수 있습니다 (결과가 캐리를 생성했는지 여부를 결정 함) ).
ADD r1, r2, r3; // r1 = r2 + r3
ADD r4, r5, r6; // r4 = r5 + r6
SLT r7, r1, r2; // r7 = (r1 < r2)? 1 : 0 (determining carry)
ADD r4, r4, r7; // r4 = r4 + r7 (adding in carry)
(다수의 정밀 연산이 일반적이지 않기 때문에 단일 캐리 비트가 슈퍼 스칼라 연산을 방해하는 데이터 종속성을 도입하고 특수 비트는 순서가 잘못된 실행에 대한 레지스터 이름 바꾸기를 더 복잡하게 만들기 때문에 캐리 비트를 제공하지 않기로 선택한 ISA 설계자는 그렇게했습니다 .)
곱셈의 경우 배가 된 정밀도는 정교한 알고리즘을보다 효율적으로 만드는 데 충분하지 않을 수 있으므로 부분 곱을 생성하고 결과를 합산하는 간단한 방법이 선호 될 수 있습니다. 이 수식을 사용합니다 (여기서 a와 c는 배가 된 정밀도 값의 위쪽 절반 임).
(a + b) * (c + d) = a*c + a*d + b*c + b*d.
(간단히하기 위해, 다음은 초과 된 부분을 무시하고 두 배로 된 정밀도 결과를 가정하므로 제품 용어 a * c는 완전히 무시됩니다.)
단일 곱셈으로부터 높은 결과와 낮은 결과를 모두 제공하는 ISA (예 : MIPS, x86)의 경우 작업이 비교적 간단합니다. 다음은 거칠게 x86에 대한 근사값 (세부 사항에 익숙하지 않음) :
MUL r2:r0, r3, r7; // multiply a*d
MOV r1, r0; // preserve low result of a*d
MUL r2:r0, r5, r6; // multiply b*c
MOV [temp], R0; // preserve low result on stack at temp
MUL r2:r0, r5, r7; // multiply b*d
ADD r2, r1; // add high b*d and low b*c for part of
// higher result
ADD r2, [temp]; // add partial higher result and low a*d
// doubled precision product is now in r2:r0
ISA (예 : Alpha)가 높은 결과에 대해 별도의 곱셈을 제공하고 낮은 결과에 대해 여러 명령을 제공하는 경우 (곱셈은 기본적으로 배가 된 정밀도 값을 산출 함)이 연산은 다소 비슷합니다.
// a*c result is beyond doubled precision range
MULL r16, r1, r4; // low multiply result (a*d)
// high a*d result is beyond doubled precision range
MULL r17, r2, r3; // low multiply result (b*c)
// high b*c result is beyond doubled precision range
MULL r18, r2, r4; // low multiply result (b*d)
MULH r19, r2, r4; // high multiply result (b*d)
ADD r20, r19, r17; // sum high (b*d) and low (b*c)
// for part of higher result
ADD r20, r20, r16; // sum partial result and low (a*d)
// double precision result is in r20:r16
(일부 ISA는 곱셈의 결과가 더 높아지는 수단을 제공하지 않습니다. 이러한 ISA의 경우 피연산자를 절반 크기 단위로 나누고 4 배 정밀도 곱셈을 수행 할 수 있지만 더 정교한 알고리즘이있을 수 있습니다. add 명령어는 분명히 덧셈과 곱셈 중 두 개를 곱셈 - 덧셈에 병합 할 수 있습니다.)
위의 의사 어셈블리 코드에서는 오버플로가 문제가되지 않는다고 가정하고 성능에 맞게 최적화되지 않았습니다. 실제 구현은 적절하게 처리 할 수 있습니다.
GNU 다중 정밀 산술 라이브러리 , 임의 정밀도 산술을위한 오픈 소스 라이브러리는 실제 구현의 세부 사항을 제공합니다.
주소 공간 제한 사항
32 비트 프로세서가 (단순한 의미에서) 4 GiB의 메모리 만 사용할 수있는 이유는 32 비트 포인터 / 주소를 사용하고 바이트 주소 지정을 사용한다는 것입니다 (따라서 2 32 주소를 사용할 수 있음). 전통적으로 가상 메모리 시스템을 사용해도 4 GiB보다 큰 물리적 주소 공간 (메모리 매핑 I / O 주소 포함)은 불필요한 것으로 간주되었습니다. (4 GiB 물리적 주소 공간은 32 비트 페이지 테이블 항목에도 편리하며 4 KiB 페이지를 사용할 때 10 비트를 사용하여 유효성, 사용 권한 및 기타 메타 데이터를 정의 할 수 있습니다 .64 비트 페이지 테이블 항목을 사용하면 소형 시스템의 경우 초과 메모리, 초기 32 비트 시스템은 작았습니다.)
32 비트 ISA의 수명을 연장하기 위해 일부 ISA (예 : ARM, x86)는 64 비트 페이지 테이블 항목을 사용하여 더 큰 실제 주소를 허용하는 실제 주소 확장을 추가했습니다. 이 해결 방법은 특히 OS (모든 실제 메모리를 관리해야 함)의 경우 어색합니다.
HP PA-RISC와 같은 일부 ISA는 사용자 수준 프로그램이 주소 상단에 특수 용도 세그먼트 레지스터를 추가하여 더 큰 주소 공간을 주소 지정할 수있는 세그먼트 화 시스템을 제공했습니다. (전원 [PC]도 세그먼트를 사용하지만 권한이없는 [즉, 응용 프로그램] 소프트웨어로는 값을 수정할 수 없습니다.)
(이론적으로, ISA는 레지스터 쌍을 사용하여 일부 8 비트 프로세서와 같은 메모리 어드레싱 기능을 확장 할 수 있지만, 64 비트 ISA 로의 이전은 일반적으로 더 의미가 있습니다.)