할 수 있는 방법을 곱 두 64 비트 숫자를 사용하여 86 어셈블리 언어입니까?

StackOverflow https://stackoverflow.com/questions/87771

  •  01-07-2019
  •  | 
  •  

문제

어떻게 이동해...

  • 두 개의 곱 64 비트 숫자

  • 곱하여 두 개의 16 진수 자리 숫자

...사용하여 어셈블리 언어입니다.

나는 사용자만 사용할 수 있 등록%eax,%ebx,%우 exc%edx,그리고 스택입니다.

편집:오하이오,나는 사용하 ATT 구문에 86
EDIT2:허용하지 않는 디컴파일 어셈블리로...

도움이 되었습니까?

해결책

무엇을 사용해야의 과정을 교과서,랜드의 예술"어셈블리의 언어"라고 합니다.

4.2.4-는 확장된 정밀도는 곱하기

지만 8x8,16x16,또는 32x32 곱은 일반적으로 충분한 시간이 있을 때할 수 있습을 곱다 큰 값을 함께합니다.당신이 사용하 86 단일 연산자 MUL 및 IMUL 지침에 대한 확장된 정밀도는 곱셈..

아마도 가장 중요한 것은 기억하기 를 수행할 때 확장된 정밀도는 곱해야한다는 것입니다 당신은 또한 수행하는 여러 정밀한 동시에.추가 모든 부분이 제품이 필요 여러 추가하는 결과를 얻을.다음과 같은 목록 적절한 방법을 보여줍니 곱 두 64 비트 값에서 32 비트 프로세서..

(링크를 참조에 대한 전체 어셈블리 목록과 그림이 있습니다.)

다른 팁

이 64x86,

function(x, y, *lower, *higher)
movq %rx,%rax     #Store x into %rax
mulq %y           #multiplies %y to %rax
#mulq stores high and low values into rax and rdx.
movq %rax,(%r8)   #Move low into &lower
movq %rdx,(%r9)   #Move high answer into &higher

에 있기 때문에 당신은 x86 야 할 4 궁리다.분 64 비트 양으로 두 개의 32 비트 단어와 곱하면 낮은 단어를 가장 낮은 그리고 제 2 장 낮은 단어의 결과는 다음 두 쌍의 낮고 높은 단어를 다른 번호로부터(그들은 2 층과 3 가장 낮은 단어의 결과)그리고 마지막으로 모두 높은 단어로 2 가장 높은 단어의 결과입니다.추가 모두 함께 그들을 잊지 않을 거래 수행한다.을 지정하지 않은 메모리 레이아웃의 입력과 출력하는 것은 불가능하다 그래서 작성 예제 코드입니다.

이 코드에서 당신이 원하는 x86(지 코드 x64),당신은 아마만 원하는 64 비트 제품,그리고 당신이에 대해 걱정하지 않 오버플로나 서명된 번호입니다.(서명된 버전과 비슷).

MUL64_MEMORY:
     mov edi, val1high
     mov esi, val1low
     mov ecx, val2high
     mov ebx, val2low
MUL64_EDIESI_ECXEBX:
     mov eax, edi
     mul ebx
     xch eax, ebx  ; partial product top 32 bits
     mul esi
     xch esi, eax ; partial product lower 32 bits
     add ebx, edx
     mul ecx
     add ebx, eax  ; final upper 32 bits
; answer here in EBX:ESI

이지 않는 명예의 정확한 등록의 제약 조건을 협동,하지만 결과에 맞는 전적으로 레지스터에 의해 제공되는 x86.(이 코드는 검증되지 않은,그러나 내가 생각하는 그의 오른쪽).

[참고:나는 양도(나)이 응답에서 또 다른 문제는 폐기 때문에,다른"답은"여기로 직접 질문에 대답].

따라 어떤 언어를 사용하고 있습니다.에서 내가 기억에서 배우며 어셈블리가 움직임에서 높은 명령을에서 이동 명령 소호,또는 mflo 및 mfhi.mfhi 저장하는 최상 64 비트는 동안 mflo 저장 낮은 64 비트 전체의 숫자입니다.

아 어셈블리,이후 잠시 있었다 나는 그것을 사용했습니다.그래서 나는 가정하고 실제 문제가 여기에는 마이크로컨트롤러(내가 사용하는 코드를 작성을 위해서 어셈블리는 어쨌든)에서 작업하지 않는 64 비트 레지스터?이 경우에는,당신이 휴식의 숫자 작업과 떨어져 수행 여러 개의 곱셈과 조각이다.

이 같은 소리의 숙제에서는 방법 당신은 말로 그것은,그래서 나는지 그것을 밖으로 철이 훨씬 더:P

다만 정상적인 오 곱하기,당신을 곱하의 쌍 2-자리 숫자를 제외하고,각각의"자리"정말 32 비트의 정수입니다.만약 당신이 곱하여 두 번호에 주소를 X,Y 고 그 결과를 저장하에서 Z,다음 당신이 원하는 무엇(의사)이다:

Z[0..3] = X[0..3] * Y[0..3]
Z[4..7] = X[0..3] * Y[4..7] + X[4..7] * Y[0..3]

우리가 참고 폐기 위한 64 비트의 결과이기 때문에(64 비트 숫자간에는 64 비트 숫자는 128 비트의 번호).또한 참고로 이것은 가정 little-endian.또한,주의해서 서명된 대한 부호 없는 곱합니다.

이 찾는 C 컴파일러 지원하는 64 비트(GCC 는 IIRC)컴파일하는 프로그램은 단지 않는,다음의 분해합니다.GCC 수 있습 뱉어 자신의에서 얻을 수 있는 그 밖의 개체 파일이 오른쪽에 도구입니다.

새로운 그들은 32bX32b=64b op 에 86

a:b * c:d = e:f
// goes to
e:f = b*d;
x:y = a*d;  e += x;
x:y = b*c;  e += x;

다른 모든 범람

(스트)

편집 Unsigned 만

난 당신 학생은,그래서 당신이 일을 할 수 있습:그것을 말씀으로 사용하고,비트 바뀝니다.이 생각하는 가장 효율적인 솔루션입니다.주의인 비트입니다.

하려는 경우 128 모이...

__uint128_t AES::XMULTX(__uint128_t TA,__uint128_t TB)
{
    union
    {
        __uint128_t WHOLE;
        struct
        {
            unsigned long long int LWORDS[2];
        } SPLIT;
    } KEY;
    register unsigned long long int __XRBX,__XRCX,__XRSI,__XRDI;
    __uint128_t RESULT;

    KEY.WHOLE=TA;
    __XRSI=KEY.SPLIT.LWORDS[0];
    __XRDI=KEY.SPLIT.LWORDS[1];
    KEY.WHOLE=TB;
    __XRBX=KEY.SPLIT.LWORDS[0];
    __XRCX=KEY.SPLIT.LWORDS[1];
    __asm__ __volatile__(
                 "movq          %0,             %%rsi           \n\t"       
                 "movq          %1,             %%rdi           \n\t"
                 "movq          %2,             %%rbx           \n\t"
                 "movq          %3,             %%rcx           \n\t"
                 "movq          %%rdi,          %%rax           \n\t"
                 "mulq          %%rbx                           \n\t"
                 "xchgq         %%rbx,          %%rax           \n\t"
                 "mulq          %%rsi                           \n\t"
                 "xchgq         %%rax,          %%rsi           \n\t"
                 "addq          %%rdx,          %%rbx           \n\t"
                 "mulq          %%rcx                           \n\t"
                 "addq          %%rax,          %%rbx           \n\t"
                 "movq          %%rsi,          %0              \n\t"
                 "movq          %%rbx,          %1              \n\t"
                 : "=m" (__XRSI), "=m" (__XRBX)
                 : "m" (__XRSI),  "m" (__XRDI), "m" (__XRBX), "m" (__XRCX)
                 : "rax","rbx","rcx","rdx","rsi","rdi"
                 );
    KEY.SPLIT.LWORDS[0]=__XRSI;
    KEY.SPLIT.LWORDS[1]=__XRBX;
    RESULT=KEY.WHOLE;
    return RESULT;
}

당신이 원하는 128 비트의 곱셈 다음이 작동해야이에서는 AT&T 형식입니다.

__uint128_t FASTMUL128(const __uint128_t TA,const __uint128_t TB)
{
    union
    {
        __uint128_t WHOLE;
        struct
        {
            unsigned long long int LWORDS[2];
        } SPLIT;
    } KEY;
    register unsigned long long int __RAX,__RDX,__RSI,__RDI;
    __uint128_t RESULT;

KEY.WHOLE=TA;
__RAX=KEY.SPLIT.LWORDS[0];
__RDX=KEY.SPLIT.LWORDS[1];
KEY.WHOLE=TB;
__RSI=KEY.SPLIT.LWORDS[0];
__RDI=KEY.SPLIT.LWORDS[1];
__asm__ __volatile__(
    "movq           %0,                             %%rax                   \n\t"
    "movq           %1,                             %%rdx                   \n\t"
    "movq           %2,                             %%rsi                   \n\t"
    "movq           %3,                             %%rdi                   \n\t"
    "movq           %%rsi,                          %%rbx                   \n\t"
    "movq           %%rdi,                          %%rcx                   \n\t"
    "movq           %%rax,                          %%rsi                   \n\t"
    "movq           %%rdx,                          %%rdi                   \n\t"
    "xorq           %%rax,                          %%rax                   \n\t"
    "xorq           %%rdx,                          %%rdx                   \n\t"
    "movq           %%rdi,                          %%rax                   \n\t"
    "mulq           %%rbx                                                   \n\t"
    "xchgq          %%rbx,                          %%rax                   \n\t"
    "mulq           %%rsi                                                   \n\t"
    "xchgq          %%rax,                          %%rsi                   \n\t"
    "addq           %%rdx,                          %%rbx                   \n\t"
    "mulq           %%rcx                                                   \n\t"
    "addq           %%rax,                          %%rbx                   \n\t"
    "movq           %%rsi,                          %%rax                   \n\t"
    "movq           %%rbx,                          %%rdx                   \n\t"
    "movq           %%rax,                          %0                      \n\t"
    "movq           %%rdx,                          %1                      \n\t"
    "movq           %%rsi,                          %2                      \n\t"
    "movq           %%rdi,                          %3                      \n\t"
    : "=m"(__RAX),"=m"(__RDX),"=m"(__RSI),"=m"(__RDI)
    :  "m"(__RAX), "m"(__RDX), "m"(__RSI), "m"(__RDI)
    : "rax","rbx","ecx","rdx","rsi","rdi"
);
KEY.SPLIT.LWORDS[0]=__RAX;
KEY.SPLIT.LWORDS[1]=__RDX;
RESULT=KEY.WHOLE;
return RESULT;
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top