Tôi vừa thử một cái gì đó trong MSVC 2010 trên máy 32-bit của tôi ở đây và phát hiện ra rằng tôi có thể sử dụng __int64 trong các chương trình của tôi - mà thực sự làm việc!__int64 trên máy 32 bit?
- Làm cách nào có thể?
Tôi vừa thử một cái gì đó trong MSVC 2010 trên máy 32-bit của tôi ở đây và phát hiện ra rằng tôi có thể sử dụng __int64 trong các chương trình của tôi - mà thực sự làm việc!__int64 trên máy 32 bit?
Cùng một cách số học 32 bit hoạt động trên hệ thống 16 bit.
Trong trường hợp này, nó sử dụng 2 địa chỉ bộ nhớ 32 bit để tạo thành số 64 bit cùng nhau. Ngoài ra/chất nền là dễ dàng, bạn làm điều đó bởi các bộ phận, chỉ gotcha là lấy carry-over từ phần dưới lên phần cao hơn. Đối với phép nhân/chia, khó hơn (tức là thêm hướng dẫn).
Rõ ràng là chậm, chậm hơn một chút so với số học 32 bit cho phép nhân, nhưng nếu bạn cần nó, nó có sẵn cho bạn. Và khi bạn nâng cấp lên bộ xử lý
64 bit
, nó sẽ tự động được tối ưu hóa thành một lệnh có kích thước chữ lớn hơn.
Visual Studio 2010 thực hiện chuyên nghiệp của chút nhân 64 trên một bộ xử lý 32-bit, biên soạn trong chế độ phát hành, là:
_allmul PROC NEAR
A EQU [esp + 4] ; stack address of a
B EQU [esp + 12] ; stack address of b
mov eax,HIWORD(A)
mov ecx,HIWORD(B)
or ecx,eax ;test for both hiwords zero.
mov ecx,LOWORD(B)
jnz short hard ;both are zero, just mult ALO and BLO
mov eax,LOWORD(A)
mul ecx
ret 16 ; callee restores the stack
hard:
push ebx
A2 EQU [esp + 8] ; stack address of a
B2 EQU [esp + 16] ; stack address of b
mul ecx ;eax has AHI, ecx has BLO, so AHI * BLO
mov ebx,eax ;save result
mov eax,LOWORD(A2)
mul dword ptr HIWORD(B2) ;ALO * BHI
add ebx,eax ;ebx = ((ALO * BHI) + (AHI * BLO))
mov eax,LOWORD(A2) ;ecx = BLO
mul ecx ;so edx:eax = ALO*BLO
add edx,ebx ;now edx has all the LO*HI stuff
pop ebx
ret 16 ; callee restores the stack
Như bạn có thể thấy, đó là một LOT chậm hơn so với nhân bình thường.
Tại sao bạn thấy nó đáng ngạc nhiên? Không có gì để ngăn trình biên dịch hỗ trợ các kiểu số nguyên 64, 128 hoặc nhiều bit trên máy 32 bit. Trình biên dịch thậm chí có thể hỗ trợ các loại 57 và 91 bit, nếu nó cảm thấy thích nó. Trong thực tế hỗ trợ số học số nguyên 2N-bit trên một máy N-bit là một nhiệm vụ tương đối dễ dàng, vì tập lệnh của một máy điển hình thường được thiết kế với kiểu chức năng này trong tâm trí.
32 bit chỉ đơn thuần là kích thước gốc của từ máy, có nghĩa là chúng có thể được xử lý trong một lần, không có nghĩa là các mục lớn hơn không thể xử lý được, chúng chỉ cần được xử lý riêng biệt 32- đơn vị bit theo nhiều bước, giống như cách chúng có thể nhỏ hơn từ máy, trong trường hợp đó chỉ là một phần của từ máy đầy đủ sẽ được xử lý.
Nó hoạt động vì loại dữ liệu số nguyên 64 bit là một phần của đặc tả ngôn ngữ.
Trình biên dịch cho ngôn ngữ PHẢI cho phép bạn làm việc với các số nguyên 64 bit (và nhận được kết quả chính xác, tất nhiên).
Chương trình của bạn phải hoạt động (và hoạt động chính xác), cho dù bạn nhắm mục tiêu máy 64 bit, 32 bit, 16 bit hoặc 8 bit (bất kể trình biên dịch nào cho phép).
Ai đã viết trình biên dịch buộc phải làm cho nó làm bất cứ điều gì là cần thiết để làm chomỗi hỗ trợ công việc kiểu dữ liệu trên mỗi nhắm mục tiêu loại xử lý.
Hỗ trợ các loại dữ liệu "cao hơn" có khả năng hỗ trợ đã được chăm sóc, để bạn không phải tự mình làm.
Làm cách nào?Rõ ràng, chấp nhận mã lệnh điều khiển số học 16 bit và dịch nó thành mã máy chạy trên bộ vi xử lý 16 bit (hoặc cao hơn) là công việc "dễ dàng" cho trình biên dịch, gần như là bản dịch trực tiếp. Z = X + Y
có thể dịch thành mov a,(X); add a,(Y); mov (Z),a;
.
Ngược lại, chấp nhận mã lệnh điều khiển số học 64 bit và dịch nó thành mã máy chạy trên bộ xử lý 32 bit (hoặc thấp hơn) phức tạp hơn. Trình biên dịch có nhiều việc phải làm, hoạt động trên các phần 32 bit của mỗi toán hạng tại một thời điểm. Có nhiều cách để làm điều đó.
Mã máy kết quả có thể sử dụng nhiều hướng dẫn nội tuyến (mã lớn hơn, thực thi nhanh hơn). Z = X + Y
có thể dịch thành mov a,(X); adc a,(Y); mov (Z),a; mov a,CARRY; adc a,(X+1); adc a,(Y+1); mov (Z+1),a;
.
Mã máy kết quả có thể gọi các chương trình con số học mở rộng (mã nhỏ hơn, thực thi chậm hơn). Z = X + Y
có thể dịch thành mov a,X; call GET64; mov a,Y; call ADD64; mov a,Z; call STORE64;
.
Bạn thậm chí có thể sử dụng tiêu chuẩn int64_t! –
@ el.pescado: 'int64_t' chỉ là tiêu chuẩn trong C99; nó không phải là một phần của tiêu chuẩn C++, nhưng sẽ được thêm vào trong C++ 0x sắp tới. –
Trong thực tế, máy 32 bit của bạn (tức là> Pentium) có một số hỗ trợ 64bit bản địa, nó cũng có 36bit không gian địa chỉ. Chỉ là các cửa sổ chọn giới hạn bạn đến 32bit –