Làm thế nào một điểm nổi 80 bit có thể được sử dụng bởi hệ thống 32 bit? [bản sao]


13

Vì hệ thống 32 bit không thể quản lý số 2 ^ 33 (vì giới hạn 32 bit rõ ràng), làm thế nào có thể quản lý Điểm nổi 80 bit con số?

Nó cần "80-bit" ...


8
Giống như cách nó thực hiện một số dấu phẩy động 64 bit. Nó sử dụng 3 hoặc (2) thanh ghi 32 bit. Do số dấu phẩy động 80 bit thậm chí không phải là kích thước tiêu chuẩn, nên nó thực sự sẽ là một số 96 bit chỉ với 80 bit được sử dụng.
Ramhound

5
Khi bạn lo lắng về sự bẻ khóa của nền tảng, bạn lo lắng về hoạt động bên trong của CPU như những người khác đã nói và cách các hướng dẫn thường được chạy trên hệ thống. Các số IEEE754 thường có thể được xử lý trực tiếp trong các đơn vị thực thi FPU của CPU của bạn, trong khi đó, số 128 bit sẽ yêu cầu sử dụng nhiều lệnh được lập trình để chúng có thể tổng hợp ý nghĩa của giá trị mà ứng dụng đang đánh giá. khiến việc xử lý số lên đến ứng dụng.
Frank Thomas

2
@ Cʜιᴇ007 Không hoàn toàn là một bản sao của cái đó một. Đó là nhiều hơn về sự khác biệt giữa một số và đại diện văn bản / ASCII của nó, mặc dù một số câu trả lời cũng có thể giải quyết điều này.
Bob

3
Trong hầu hết tất cả các máy hiện đại, điểm nổi được xử lý bởi một bộ xử lý riêng (mặc dù thường trên cùng một chip với bộ xử lý chính). Tất cả các bộ xử lý như vậy đều biết cách xử lý 80 bit (mặc dù một số xử lý nhanh hơn rất nhiều so với các bộ xử lý khác). ( Và "chiều rộng" của bộ xử lý dù sao cũng chỉ là hư cấu. )
Daniel R Hicks

6
@Ramhound: Không, 80 bit là đặc thù 8087 và nó sử dụng 1 thanh ghi FP. Nó chắc chắn không phải là một số 96 bit.
MSalters

Câu trả lời:


35

Một trong những ý nghĩa của CPU 32 bit là các thanh ghi của nó rộng 32 bit. Điều này không có nghĩa là nó không thể đối phó với các số 64 bit, chỉ là nó phải xử lý nửa dưới 32 bit trước, sau đó là 32 bit trên nửa giây. (Đó là lý do tại sao CPU có một mang cờ .) Nó chậm hơn nếu CPU chỉ có thể tải các giá trị trong một thanh ghi 64 bit rộng hơn, nhưng vẫn có thể.

Do đó, "độ bit" của hệ thống không nhất thiết giới hạn kích thước của các số mà chương trình có thể xử lý, bởi vì bạn luôn có thể chia các hoạt động không phù hợp với các thanh ghi CPU thành nhiều hoạt động. Vì vậy, nó làm cho các hoạt động chậm hơn, tiêu thụ nhiều bộ nhớ hơn (nếu bạn phải sử dụng bộ nhớ làm "Scratchpad") và khó lập trình hơn, nhưng các thao tác vẫn có thể.

Tuy nhiên, không có vấn đề nào, ví dụ, bộ xử lý Intel 32 bit và dấu phẩy động, vì phần dấu phẩy động của CPU có các thanh ghi riêng và chúng có chiều rộng 80 bit. (Đầu tiên trong lịch sử của x86, khả năng dấu phẩy động là một con chip riêng biệt, nó được tích hợp trong CPU bắt đầu với 80486DX.)


Câu trả lời của Đột phá đã truyền cảm hứng cho tôi để thêm điều này.

Các giá trị dấu phẩy động, trong khi chúng được lưu trữ trong các thanh ghi FPU, hoạt động rất khác so với các giá trị nguyên nhị phân.

80 bit của một giá trị dấu phẩy động được chia cho một số mũ và số mũ (cũng có "cơ sở" trong các số dấu phẩy động luôn luôn là 2). Lớp phủ chứa các chữ số có nghĩa và số mũ xác định các chữ số có nghĩa đó lớn đến mức nào. Vì vậy, không có "tràn" vào một thanh ghi khác, nếu số của bạn quá lớn để phù hợp với lớp phủ, số mũ của bạn tăng và bạn mất độ chính xác - tức là khi bạn chuyển đổi nó thành một số nguyên, bạn sẽ mất số thập phân bên phải - đây là lý do tại sao nó được gọi là điểm nổi.

Nếu số mũ của bạn quá lớn, thì bạn có tràn điểm nổi, nhưng bạn không thể dễ dàng mở rộng nó sang một thanh ghi khác vì số mũ và mantissa được gắn với nhau.

Tôi có thể không chính xác và sai về một số điều đó, nhưng tôi tin rằng đó là ý chính của nó. (Điều này Bài viết trên Wikipedia minh họa ở trên một chút ngắn gọn hơn.)

Không sao, điều này hoạt động hoàn toàn khác vì toàn bộ phần "điểm nổi" của CPU thuộc loại trong thế giới riêng của nó - bạn sử dụng các hướng dẫn CPU đặc biệt để truy cập vào nó và như vậy. Ngoài ra, về phía câu hỏi, bởi vì nó tách biệt, độ bit của FPU không được kết hợp chặt chẽ với bitness của CPU gốc.


4
Mọi thứ bạn thêm vào từ cảm hứng của tôi đều chính xác, vì vậy đừng lo lắng :) Chỉ cần một điểm tôi nên đề cập, mặc dù bạn có thể sử dụng các hướng dẫn CPU gốc có tồn tại đơn vị dấu phẩy động, người ta cũng có thể thực hiện các thao tác dấu phẩy động trong phần mềm (với bitwise tương đương hoặc các phép toán số nguyên). Để mở rộng đến thời điểm đó, được cung cấp đủ bộ nhớ, bạn cũng có thể có số chính xác tùy ý . GNU Nhiều thư viện chính xác ).
Breakthrough

1
Nitpick: FPU tích hợp đầu tiên của Intel là trong 80486DX, không phải 80386.
spudone

2
@markzzz: Không có gì là điên rồ nếu được yêu cầu. Sử dụng phao 16 bit để mô phỏng bom nguyên tử để đánh giá kho dự trữ hạt nhân của bạn là điên rồ vì nó không đủ chính xác để bạn tự tin vào kết quả. Trong trường hợp đó cần 32 bit (và vâng, ngày xưa, các phép tính này được thực hiện trên các PDP 16 bit). Tương tự, sử dụng folats 32 bit để mô phỏng khí hậu không đủ chính xác do tính chất hỗn loạn của các tính toán.
slebetman

2
FWIW, cách phổ biến để thực hiện các thao tác dấu phẩy động trên các máy không có đơn vị FP có kích thước bạn muốn là thực hiện trong phần mềm bằng hướng dẫn số nguyên. Bởi vì, vào cuối ngày, cả số mũ và số mũ của số dấu phẩy động chỉ là số nguyên. Đó là cách chúng tôi giải thích chúng mang lại cho chúng ý nghĩa đặc biệt của chúng.
slebetman

2
@PTwr trên x86 bạn thực sự có 7 GPR có thể sử dụng được cho dữ liệu, bao gồm EBP. Chỉ là ABI của hầu hết các ngôn ngữ triển khai dự trữ đăng ký này cho con trỏ khung ngăn xếp. Nhưng ví dụ với GCC bạn có thể sử dụng -fomit-frame-pointer để có được đăng ký trở lại.
Ruslan

13

Tất cả 32 bit, 64 bit và 128 bit đều đề cập đến độ dài từ của bộ xử lý, có thể được coi là "kiểu dữ liệu cơ bản". Thông thường, đây là số bit được truyền đến / từ RAM của hệ thống và độ rộng của con trỏ (mặc dù không có gì ngăn bạn sử dụng phần mềm để truy cập thêm RAM, sau đó một con trỏ có thể truy cập).

Giả sử tốc độ đồng hồ không đổi (cũng như mọi thứ khác trong kiến ​​trúc là không đổi) và giả sử bộ nhớ đọc / ghi là cùng tốc độ (chúng tôi giả sử 1 chu kỳ đồng hồ ở đây, nhưng điều này khác xa với thực tế thêm hai số 64 bit trong một chu kỳ xung nhịp đơn trên máy 64 bit (ba nếu bạn đếm tìm nạp các số từ RAM):

ADDA [NUM1], [NUM2]
STAA [RESULT]

Chúng tôi cũng có thể làm tính toán tương tự trên máy 32 bit ... Tuy nhiên, trên máy 32 bit, chúng ta cần thực hiện điều này trong phần mềm, vì trước tiên phải thêm 32 bit, bù cho tràn, sau đó thêm 64 bit trên:

     ADDA [NUM1_LOWER], [NUM2_LOWER]
     STAA [RESULT_LOWER]
     CLRA          ; I'm assuming the condition flags are not modified by this.
     BRNO CMPS     ; Branch to CMPS if there was no overflow.
     ADDA #1       ; If there was overflow, compensate the value of A.
CMPS ADDA [NUM1_UPPER], [NUM2_UPPER]
     STAA [RESULT_UPPER]

Xem qua cú pháp lắp ráp hoàn chỉnh của tôi, bạn có thể dễ dàng thấy các thao tác có độ chính xác cao hơn có thể mất thời gian lâu hơn theo cấp số nhân trên một máy có độ dài từ thấp hơn. Đây là chìa khóa thực sự cho bộ xử lý 64 bit và 128 bit: chúng cho phép chúng tôi xử lý số lượng bit lớn hơn trong một hoạt động. Một số máy bao gồm các hướng dẫn để thêm số lượng khác mang theo (ví dụ: ADC trên x86), nhưng ví dụ trên có các giá trị chính xác tùy ý.


Bây giờ, để mở rộng câu hỏi này, thật đơn giản để xem làm thế nào chúng ta có thể thêm các số lớn hơn các thanh ghi mà chúng ta có sẵn - chúng ta chỉ chia vấn đề thành các phần của kích thước các thanh ghi và làm việc từ đó. Mặc dù như đã đề cập bởi @MatteoItalia , ngăn xếp x87 FPU có hỗ trợ riêng cho số lượng 80 bit, trong các hệ thống thiếu hỗ trợ này (hoặc bộ xử lý thiếu đơn vị điểm nổi hoàn toàn!), phải thực hiện tính toán / thao tác tương đương trong phần mềm .

Vì vậy, đối với số 80 bit, sau khi thêm từng phân đoạn 32 bit, người ta cũng sẽ kiểm tra xem có bị tràn vào bit 81 bit hay không và tùy chọn không đưa ra các bit thứ tự cao hơn. Các kiểm tra / số không này được thực hiện tự động cho một số lệnh x86 và x86-64 nhất định, trong đó kích thước toán hạng nguồn và đích được chỉ định (mặc dù các kích thước này chỉ được chỉ định trong các mức 2 bắt đầu từ rộng 1 byte).

Tất nhiên, với các số dấu phẩy động, người ta không thể thực hiện phép cộng nhị phân một cách đơn giản vì phần tử và các chữ số có nghĩa được đóng gói cùng nhau ở dạng bù. Trong ALU trên bộ xử lý x86, có một mạch phần cứng để thực hiện điều này cho các phao nổi 32 bit và 64 bit của IEEE; Tuy nhiên , ngay cả khi không có đơn vị dấu phẩy động (FPU), các phép tính tương tự có thể được thực hiện trong phần mềm (ví dụ: thông qua việc sử dụng Thư viện khoa học GNU , sử dụng một FPU khi được biên dịch trên các kiến ​​trúc, quay lại thuật toán phần mềm nếu không có phần cứng dấu phẩy động nào [ví dụ: đối với các vi điều khiển nhúng thiếu FPU]).

Cho đủ bộ nhớ, người ta cũng có thể thực hiện tính toán trên các số tùy ý (hoặc "vô hạn" - trong giới hạn thực tế), sử dụng nhiều bộ nhớ hơn vì cần độ chính xác cao hơn. Một thực hiện này tồn tại trong GNU Nhiều thư viện chính xác , cho phép độ chính xác không giới hạn (tất nhiên cho đến khi RAM của bạn đầy) trên các hoạt động số nguyên, hợp lý và dấu phẩy động.


2
Bạn không đề cập đến chi tiết quan trọng nhất: x87 FPU trên nền tảng x86 có các thanh ghi dấu phẩy động rộng 80 bit, do đó, các phép tính riêng của nó thực sự được thực hiện trên các phao 80 bit, không cần mô phỏng bất cứ thứ gì trong phần mềm.
Matteo Italia

@MatteoItalia Bây giờ tôi thấy điều đó, cảm ơn bạn. Tôi nghĩ rằng câu hỏi ban đầu là hỏi về tổng quan chung hơn về cách người ta có thể thực hiện các thao tác trên các số lớn hơn kích thước từ của bộ xử lý và không triển khai cụ thể các số float 80 bit mở rộng trong x86 (cũng là lý do tại sao ví dụ của tôi là 90 bit thay vì 80 ...). Tôi đã cập nhật câu trả lời ngay bây giờ để phản ánh tốt hơn điều này, cảm ơn bạn đã ủng hộ.
Breakthrough

5

Kiến trúc bộ nhớ của hệ thống chỉ có thể cho phép bạn di chuyển 32 bit cùng một lúc - nhưng điều đó không ngăn nó sử dụng số lớn hơn.

Hãy nghĩ về phép nhân. Bạn có thể biết các bảng nhân của mình lên tới 10 x 10, nhưng có lẽ bạn không gặp vấn đề gì khi thực hiện 123x321 trên một tờ giấy: bạn chỉ chia nó thành nhiều vấn đề nhỏ, nhân các chữ số riêng lẻ và chăm sóc v.v.

Bộ xử lý có thể làm điều tương tự. Trong "thời xa xưa", bạn có bộ xử lý 8 bit có thể thực hiện phép toán dấu phẩy động. Nhưng họ đã rất chậm.


1
Họ đã chậm chỉ sau một thời điểm nhất định. Bạn có thể viết các phép toán dấu phẩy động "nhanh" nếu bạn giới hạn ở một đặc điểm kỹ thuật nhất định.
Ramhound

3

"32-bit" thực sự là một cách phân loại bộ xử lý, không phải là phán quyết chính thức. bộ xử lý "32 bit" thường có các thanh ghi mục đích chung 32 bit để làm việc.

Tuy nhiên, không có yêu cầu nào được đặt ra rằng mọi thứ trong bộ xử lý phải được thực hiện trong 32 bit. Ví dụ, không có gì lạ khi máy tính "32 bit" có bus địa chỉ 28 bit, vì nó rẻ hơn để làm phần cứng. Máy tính 64 bit thường chỉ có bus bộ nhớ 40 bit hoặc 48 bit vì lý do tương tự.

Số học dấu phẩy động là một nơi khác có kích thước khác nhau. Nhiều bộ xử lý 32 bit hỗ trợ số dấu phẩy động 64 bit. Họ đã làm như vậy bằng cách lưu trữ các giá trị dấu phẩy động trong các thanh ghi đặc biệt rộng hơn các thanh ghi mục đích chung. Để lưu trữ một trong những số dấu phẩy động lớn này trong các thanh ghi đặc biệt, trước tiên người ta sẽ chia số đó cho hai thanh ghi mục đích chung, sau đó đưa ra một hướng dẫn để kết hợp chúng thành một dấu phẩy trong các thanh ghi đặc biệt. Khi đã ở trong các thanh ghi dấu phẩy động đó, các giá trị sẽ được xử lý dưới dạng các phao 64 bit, thay vì một nửa các nửa 32 bit.

Số học 80 bit mà bạn đề cập là một trường hợp đặc biệt của điều này. Nếu bạn đã làm việc với các số dấu phẩy động, bạn sẽ quen với sự thiếu chính xác phát sinh từ các vấn đề làm tròn điểm nổi. Một giải pháp cho việc làm tròn là có nhiều bit chính xác hơn, nhưng sau đó bạn phải lưu trữ số lượng lớn hơn và buộc các nhà phát triển sử dụng các giá trị dấu phẩy động lớn bất thường trong bộ nhớ.

Giải pháp của Intel là các thanh ghi dấu phẩy động có tất cả 80 bit, nhưng các hướng dẫn để di chuyển các giá trị đến / từ các thanh ghi đó hoạt động chủ yếu với các số 64 bit. Miễn là bạn hoạt động hoàn toàn trong ngăn xếp dấu phẩy động x87 của Intel, tất cả các hoạt động của bạn đều được thực hiện với độ chính xác 80 bit. Nếu mã của bạn cần kéo một trong các giá trị đó ra khỏi các thanh ghi dấu phẩy động và lưu trữ nó ở đâu đó, nó sẽ cắt nó thành 64 bit.

Đạo đức của câu chuyện: các phân loại như "32-bit" luôn nguy hiểm hơn khi bạn hiểu sâu hơn về mọi thứ!


Nhưng nếu tôi sử dụng các giá trị dấu phẩy động 32 bit vào hệ thống 16 bit (hoặc giá trị dấu phẩy động 64 bit vào hệ thống 32 bit) thì chỉ cần thêm bộ nhớ (vì phải đăng ký hai lần)? Hoặc xử lý thông tin sẽ thêm chi phí, vì vậy sẽ mất nhiều thời gian hơn?
markzzz

@markzzz: Làm việc với nhiều thanh ghi hầu như luôn mất nhiều thời gian hơn
Mooing Duck

Tải giá trị dấu phẩy động 32 bit vào các thanh ghi mục đích đặc biệt sẽ mất nhiều thời gian hơn. Tuy nhiên, một khi chúng được lưu trữ dưới dạng float 32 bit trong các thanh ghi dấu phẩy động mục đích đặc biệt, phần cứng sẽ hoạt động trên các giá trị điểm nổi đó ở tốc độ tối đa. Hãy nhớ rằng, "16-bit" chỉ đề cập đến kích thước của các thanh ghi mục đích CHUNG. Các thanh ghi dấu phẩy động có kích thước đặc biệt cho nhiệm vụ của chúng và có thể rộng hơn (rộng 32 bit trong trường hợp của bạn)
Cort Ammon

2

CPU "32 bit" là một trong đó hầu hết các thanh ghi dữ liệu là các thanh ghi 32 bit và hầu hết các lệnh hoạt động trên dữ liệu trong các thanh ghi 32 bit đó. CPU 32 bit cũng có khả năng truyền dữ liệu đến và từ bộ nhớ 32 bit mỗi lần. Hầu hết các thanh ghi là 32 bit không có nghĩa là tất cả các thanh ghi là 32 bit. Câu trả lời ngắn gọn là CPU 32 bit có thể có một số tính năng sử dụng các bitcount khác, chẳng hạn như các thanh ghi dấu phẩy động 80 bit và các hướng dẫn tương ứng.

Như @spudone đã nói trong một nhận xét về câu trả lời của @ ultrasawblade, CPU x86 đầu tiên được tích hợp các hoạt động điểm nổi là Intel i486 (cụ thể là 80486DX nhưng không phải là 80486SX), theo Trang 15-1 của Tài liệu tham khảo Lập trình viên vi xử lý i486 , bao gồm trong các thanh ghi số "Tám thanh ghi số 80 bit có thể định địa chỉ riêng lẻ". I486 có bus bộ nhớ 32 bit, do đó, việc chuyển giá trị 80 bit sẽ mất 3 thao tác bộ nhớ.

Tiền thân của thế hệ 486, i386, không có bất kỳ hoạt động điểm nổi tích hợp nào. Thay vào đó, nó có hỗ trợ cho việc sử dụng "bộ đồng xử lý" dấu phẩy động bên ngoài, 80387. Bộ đồng xử lý này có chức năng gần như được tích hợp vào i486, như bạn có thể thấy từ Trang 2-1 của Tài liệu tham khảo dành cho lập trình viên 80387 .

Định dạng dấu phẩy động 80 bit dường như bắt nguồn từ 8087, bộ đồng xử lý toán học cho 8086 và 8088. 8086 và 8088 là CPU 16 bit (với bus bộ nhớ 16 bit và 8 bit), và vẫn có thể để sử dụng định dạng dấu phẩy động 80 bit, bằng cách tận dụng các thanh ghi 80 bit trong bộ đồng xử lý.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.