2011-12-09 35 views
8

Tôi tự hỏi liệu có thực sự không có chức năng nội tại phân chia 128 bit trong Visual C++ không?Phân chia nội tại 128-bit trong Visual C++

Có một hàm nội tại nhân 64x64 = 128 bit được gọi là _umul128(), phù hợp với hướng dẫn lắp ráp M64 x64.

Đương nhiên, tôi cho rằng sẽ có một bộ phận nội tại 128/64 = 64 bit (mô hình hóa lệnh DIV), nhưng tôi không thấy Visual C++ hay Intel C++, ít nhất nó không được liệt kê trong intrin.h.

Ai đó có thể xác nhận điều đó không? Tôi đã cố gắng grep'ing cho các tên chức năng trong các tập tin thực thi trình biên dịch, nhưng không thể tìm thấy _umul128 ở nơi đầu tiên, vì vậy tôi đoán tôi nhìn vào chỗ sai.

Cập nhật: ít nhất tôi đã tìm thấy mẫu "umul128" (không có dấu gạch dưới) trong c1.dll của Visual C++ 2010. Tất cả nội tại khác được liệt kê xung quanh nó, nhưng tiếc là không có "udiv128" hoặc tương tự (Vì vậy, có vẻ như họ thực sự đã "quên" để thực hiện nó.

Để làm rõ: Tôi không chỉ tìm kiếm loại dữ liệu 128 bit, mà còn là cách để chia một bit vô hướng 128 bit bằng 64 bit int trong C++. hoặc là một nội tại chức năng hoặc mẹ đẻ 128-bit hỗ trợ số nguyên sẽ giải quyết vấn đề của tôi.

Edi t: Câu trả lời là không, không có _udiv128 nội tại trong Visual Studio 2010 hoặc 2012.

+1

Nó không phải là một phần của CRT. Nó là một nội tại, đi kèm miễn phí với bộ vi xử lý. Nhưng chỉ ở chế độ 64 bit. Không có freebie cho div cho đến khi bạn nhận được một bộ xử lý 128-bit. Với phạm vi rộng lớn của pow (2, 128), bạn nên tìm kiếm thư viện chính xác tùy ý. Rất nhiều người xung quanh. –

+0

@TreeMonkie: __int18 không được hỗ trợ bởi VS, xem http://stackoverflow.com/questions/6759592/how-to-enable-int128-on-visual-studio – cxxl

+2

@Hans: xin lỗi, tôi không hiểu. Nó không chỉ là bản chất, thậm chí không ở chế độ 64 bit. Và tôi cần nó để * viết * một lib chính xác tùy ý :) – cxxl

Trả lời

1

Tôi không có chuyên môn, nhưng tôi đào này lên:

http://research.swtch.com/2008/01/division-via-multiplication.html

Thú vị thứ. Hy vọng nó giúp.

EDIT: Đây là sâu sắc quá: (chế độ 64-bit chỉ, không kiểm tra) http://www.gamedev.net/topic/508197-x64-div-intrinsic/

+0

Nó thực sự là một nỗi đau.Ngay cả khi bạn tìm thấy sự thay đổi đối ứng + cần thiết, bạn vẫn còn phải nhân số 128bit của bạn với nghịch đảo và lấy 64 bit hàng đầu từ kết quả, đó là một PITA nghiêm trọng – yonil

+0

Ngoài ra tôi thấy khó tin rằng toàn bộ bằng cách nào đó tốt hơn chỉ dẫn DIV/IDIV. – yonil

10

Nếu bạn không nhớ hacks ít, điều này có thể giúp:

#include <windows.h> 
#include <stdio.h> 

unsigned char udiv128Data[] = 
{ 
    0x48, 0x89, 0xD0, // mov rax,rdx 
    0x48, 0x89, 0xCA, // mov rdx,rcx 
    0x49, 0xF7, 0xF0, // div r8 
    0x49, 0x89, 0x11, // mov [r9],rdx 
    0xC3    // ret 
}; 

unsigned char sdiv128Data[] = 
{ 
    0x48, 0x89, 0xD0, // mov rax,rdx 
    0x48, 0x89, 0xCA, // mov rdx,rcx 
    0x49, 0xF7, 0xF8, // idiv r8 
    0x49, 0x89, 0x11, // mov [r9],rdx 
    0xC3    // ret 
}; 

unsigned __int64 (__fastcall *udiv128)(unsigned __int64 numhi, 
             unsigned __int64 numlo, 
             unsigned __int64 den, 
             unsigned __int64* rem) = 
    (unsigned __int64 (__fastcall *)(unsigned __int64, 
            unsigned __int64, 
            unsigned __int64, 
            unsigned __int64*))udiv128Data; 

__int64 (__fastcall *sdiv128)(__int64 numhi, 
           __int64 numlo, 
           __int64 den, 
           __int64* rem) = 
    (__int64 (__fastcall *)(__int64, 
          __int64, 
          __int64, 
          __int64*))sdiv128Data; 

int main(void) 
{ 
    DWORD dummy; 
    unsigned __int64 ur; 
    __int64 sr; 
    VirtualProtect(udiv128Data, sizeof(udiv128Data), PAGE_EXECUTE_READWRITE, &dummy); 
    VirtualProtect(sdiv128Data, sizeof(sdiv128Data), PAGE_EXECUTE_READWRITE, &dummy); 
    printf("0x0000ABCDEF000000000000/0x0001000000000000 = 0x%llX\n", 
     udiv128(0x0000AB, 0xCDEF000000000000, 0x0001000000000000, &ur)); 
    printf("-6/-2 = %lld\n", 
     sdiv128(-1, -6, -2, &sr)); 
    return 0; 
} 
+1

Đối với MSVC, người dùng có thể sử dụng phần #pragma để đặt các hàm này vào phân đoạn mã trong khi biên dịch –

+0

@Maratyszcza: bạn nói đúng. –

+0

Tại sao bạn không thể sử dụng lắp ráp nội tuyến? –

2

Một cải tiến nhỏ - một hướng dẫn ít hơn

extern "C" digit64 udiv128(digit64 low, digit64 hi, digit64 divisor, digit64 *remainder); 

; Arguments 
; RCX  Low Digit 
; RDX  High Digit 
; R8  Divisor 
; R9  *Remainder 

; RAX  Quotient upon return 

.code 
udiv128 proc 
    mov rax, rcx ; Put the low digit in place (hi is already there) 
    div r8  ; 128 bit divide rdx-rax/r8 = rdx remainder, rax quotient 
    mov [r9], rdx ; Save the reminder 
    ret  ; Return the quotient 
udiv128 endp 
end 
Các vấn đề liên quan