Số đã ký và không dấu


17

Làm thế nào ALU trong bộ vi xử lý sẽ phân biệt giữa một số đã ký, -7 được ký hiệu là 1111 và số 15 không dấu, cũng được ký hiệu là 1111?


3
Xem câu trả lời của câu hỏi liên quan: cs.stackexchange.com/a/30047/28999 . Nhân tiện, ký -7 không được biểu thị là 1111. Đó là -1. Sau đó, ví dụ 1111 - 0001 = 1110 trong cả trường hợp đã ký và không dấu (-2 so với 14)
Albert Hendriks

2
@AlbertHendriks Công bằng, một số máy tính cũ hơn sử dụng "biểu diễn cường độ ký hiệu" (một bit bit và độ lớn), và chúng tôi vẫn sử dụng kiểu đó cho ví dụ như phao nổi của IEEE. Chúng không phù hợp và khó làm việc so với hai phần bù. n1
Draconis

1
Sự khác biệt chính là cách các toán tử lớn hơn / ítThan hoạt động và liệu dịch chuyển phải có lấp đầy với bit cao nhất hay không. Khi bạn thực sự nhân và chia, kết quả là như nhau.
Cướp


2
@Rob Điều đó không hoàn toàn chính xác. Phép cộng, phép trừ và phép nhân đều giống nhau giữa phép bổ trợ không dấu và twos - giả sử đầu vào và đầu ra của bạn có cùng kích thước. Phân chia không giống nhau 6/2 là 3, nhưng -2/2 là -1. Và nhiều CPU có các hướng dẫn nhân trong đó hai đầu vào có kích thước giống hệt nhau, nhưng đầu ra có kích thước gấp đôi, trong trường hợp này không dấu và twos bổ sung cũng không giống nhau.
kasperd

Câu trả lời:


14

Câu trả lời ngắn gọn và đơn giản là: không. Không có CPU CPU CPU hiện đại nào hoạt động theo cách bạn nghĩ.

Đối với CPU, nó chỉ là một mẫu bit. Tùy thuộc vào bạn, lập trình viên, để theo dõi ý nghĩa của mẫu bit đó.

Nói chung, ISAs không phân biệt giữa các loại dữ liệu khác nhau, khi nói đến lưu trữ. (Bỏ qua các thanh ghi có mục đích đặc biệt như các thanh ghi nổi trong một FPU.) Nó chỉ là một mẫu bit vô nghĩa đối với CPU. Tuy nhiên, ISA làm có các loại khác nhau của các hướng dẫn mà có thể giải thích các mẫu bit theo những cách khác nhau. Ví dụ, hướng dẫn số học như MUL, DIV, ADD, SUBgiải thích các mẫu bit như một số loại số, trong khi hướng dẫn logic như AND, OR, XORgiải thích nó như một mảng các phép toán. Vì vậy, tùy thuộc vào, lập trình viên, (hoặc tác giả của trình thông dịch hoặc trình biên dịch nếu bạn sử dụng ngôn ngữ cấp cao hơn) để chọn hướng dẫn chính xác.

Ví dụ, rất có thể có các hướng dẫn riêng cho các số được ký so với số không dấu. Một số ISA cũng có hướng dẫn về số học với số thập phân được mã hóa nhị phân.

Tuy nhiên, lưu ý rằng tôi đã viết "ISA chính thống hiện đại" ở trên. Trên thực tế, có những ISA không chính thống hoặc lịch sử hoạt động khác nhau. Ví dụ, cả ISA CISC 48 bit gốc của IBM AS / 400 cũng như ISA RISC 64 bit dựa trên POWER hiện tại của hệ thống hiện được gọi là IBM i, phân biệt giữa các con trỏ và các giá trị khác. Con trỏ luôn được gắn thẻ và chúng bao gồm thông tin loại và quản lý quyền. CPU biết liệu một giá trị có phải là con trỏ hay không và chỉ hạt nhân i / OS đặc quyền mới được phép thao tác con trỏ một cách tự do. Các ứng dụng người dùng chỉ có thể thao tác các con trỏ mà họ sở hữu để trỏ vào bộ nhớ mà họ sở hữu bằng một số lượng nhỏ các hướng dẫn an toàn.

Ngoài ra còn có một số thiết kế ISA lịch sử bao gồm ít nhất một số hình thức nhận thức hạn chế.


Lưu ý rằng mã byte Java cũng được tính là một ISA. Và nó cũng quan tâm nhiều đến các loại dữ liệu ...
John Dvorak

Mã byte Java thực hiện sắp xếp thứ tự như một ISA, theo nghĩa là nó được triển khai trong silicon. Tuy nhiên, kiểm tra kiểu cơ bản của loại này là kiểm tra được thực hiện bởi trình nạp lớp, vì vậy các loại chủ yếu có thể bị bỏ qua trong thời gian chạy. Và dĩ nhiên, mã byte Java không có kiểu không dấu ở vị trí đầu tiên.
Bút danh

@Pseudonym: Vâng, về mặt kỹ thuật, nó khôngchar, mà là một unsigned loại 16-bit. Tất nhiên, vẫn không có hướng dẫn số học không dấu trong mã byte Java, vì mọi chargiá trị được tự động thăng cấp lên int(ký 32 bit) cho số học.
Ilmari Karonen

42

Phiên bản ngắn: không biết. Không có cách nào để nói.

Nếu 1111đại diện cho -7, thì bạn có biểu diễn cường độ ký hiệu , trong đó bit đầu tiên là dấu hiệu và phần còn lại của các bit là độ lớn. Trong trường hợp này, số học có phần phức tạp, vì một phép cộng không dấu và một phép cộng được ký sử dụng logic khác nhau. Vì vậy, bạn có thể có một SADDvà một UADDopcode, và nếu bạn chọn sai, bạn sẽ nhận được kết quả vô nghĩa.

Tuy nhiên, thường xuyên hơn, 1111đại diện cho -1, trong cái được gọi là đại diện bổ sung của hai . Trong trường hợp này, ALU đơn giản là không quan tâm nếu các số được ký hoặc không dấu! Ví dụ: hãy thực hiện các hoạt động của 1110 + 0001. Trong số học đã ký, điều này có nghĩa là "-2 + 1" và kết quả sẽ là -1 ( 1111). Trong số học không dấu, điều này có nghĩa là "14 + 1" và kết quả sẽ là 15 ( 1111). Vì vậy, ALU không biết bạn muốn có kết quả đã ký hay chưa ký và điều đó không quan tâm. Nó chỉ thực hiện bổ sung như thể nó không được ký và nếu bạn muốn coi đó là số nguyên đã ký sau đó, điều đó tùy thuộc vào bạn.

EDIT: Do Ruslan và Daniel Schepler hoàn toàn chỉ ra trong các bình luận, một số toán hạng vẫn cần các phiên bản được ký và không dấu riêng biệt, ngay cả trên máy hai phần bù. Phép cộng, phép trừ, phép nhân, đẳng thức và tất cả đều hoạt động tốt mà không cần biết các số có được ký hay không. Nhưng sự phân chia và bất kỳ so sánh lớn hơn / ít hơn so với phải có các phiên bản riêng biệt.

EDIT EDIT: Cũng có một số đại diện khác, như bổ sung của một người , nhưng về cơ bản chúng không bao giờ được sử dụng nữa nên bạn không cần phải lo lắng về chúng.


À, gotcha. Cảm ơn vì điều này :)
noorav

10
Trong biểu diễn bổ sung của hai, ba phép toán số học là ký hiệu - bất khả tri: phép cộng, phép trừ và phép nhân (với sản phẩm có cùng độ dài là toán hạng). Chỉ phân chia phải được xử lý khác nhau cho toán hạng đã ký.
Ruslan

4
Ngoài ra còn có sự so sánh: < <= >= >khác nhau đối với các toán hạng được ký so với không dấu trong khi đó ==!=là tính không xác định.
Daniel Schepler

Phép nhân thường có các giống đã ký và không dấu: 0xFFFFFFFF * 0xFFFFFFFF là 0xFFFFFFFE00000001 nếu không dấu và 0x0000000000000001 nếu được ký. Các bộ xử lý như Intel trả về kết quả trong 2 thanh ghi và thanh ghi trên cùng khác nhau đối với ký và không dấu. Thanh ghi dưới cùng là 1 trong cả hai tình huống.
Rudy Velthuis

9

Một trong những lợi thế lớn của toán học bổ sung hai, mà tất cả các kiến ​​trúc hiện đại sử dụng, là các hướng dẫn cộng và trừ hoàn toàn giống nhau cho cả hai toán hạng đã ký và không dấu.

Nhiều CPU thậm chí không có các lệnh nhân, chia hoặc mô đun. Nếu họ làm như vậy, họ phải có các hình thức hướng dẫn được ký và không dấu riêng biệt, và trình biên dịch (hoặc lập trình viên ngôn ngữ lắp ráp) chọn một hình thức phù hợp.

CPU cũng thường có các hướng dẫn khác nhau để so sánh có chữ ký hoặc không dấu. Ví dụ: x86 có thể theo a CMPvới JL(Nhảy nếu nhỏ hơn) nếu so sánh được ký hoặc JB(Nhảy nếu dưới) nếu so sánh không được ký. Một lần nữa, trình biên dịch hoặc lập trình viên sẽ chọn đúng hướng dẫn cho kiểu dữ liệu.

Một vài hướng dẫn khác thường có các biến thể được ký và không dấu, chẳng hạn như dịch chuyển phải hoặc tải một giá trị vào một thanh ghi rộng hơn, có hoặc không có phần mở rộng ký.


1
Ngay cả phép nhân cũng giống nhau đối với các số nguyên không dấu và ký (hai phần bù), miễn là bạn không cần kết quả để có nhiều bit hơn các đầu vào . Tuy nhiên, nếu bạn đang làm một cái gì đó như phép nhân 8 × 8 → 16 bit (hoặc 16 × 16 → 32 bit, v.v.), bạn cần phải ký mở rộng đầu vào (hoặc kết quả trung gian) .
Ilmari Karonen

@IlmariKaronen Điều này đúng; ARM A32 / A64 là bộ giảng dạy có nhiều hình thức hướng dẫn nhân, trong đó có dấu hiệu-agnostic multiply-add mà viết chỉ các bit bậc thấp hơn, mà còn smulhumulhlợi nhuận mà chỉ có các bit trên của phép nhân và hướng dẫn signed và unsigned mà trả về kết quả trong một thanh ghi rộng gấp đôi các toán hạng nguồn.
Davislor

6

Nó không. Bộ xử lý dựa vào tập lệnh để cho nó biết loại dữ liệu nào đang xem và nơi gửi nó. Không có gì về 1 và 0 trong toán hạng vốn có thể báo hiệu cho ALU xem dữ liệu có phải là char, float, int, đã ký int hay không, v.v ... Nếu 1111 đó sẽ chuyển sang mạch điện dự kiến ​​sẽ bổ sung 2s, nó sẽ đi được giải thích như là một bổ sung 2s.


Không có thứ gọi là charở cấp độ phần cứng. Có thể ngày xửa ngày xưa, trở lại thời của máy điện báo. Nhưng ngày hôm nay, một charchỉ một số xa như phần cứng là có liên quan. Lý do tại sao các số khác nhau tương ứng với các hình dạng chữ cái khác nhau trên màn hình của bạn là vì các số đó được sử dụng để chọn các bitmap khác nhau hoặc các thói quen vẽ khác nhau từ một bảng lớn (nghĩa là từ "phông chữ").
Solomon chậm

3

Tôi muốn đưa ra một bổ sung cho các câu trả lời đã được thực hiện:

Trong hầu hết các câu trả lời khác, lưu ý rằng trong số học bổ sung twos, kết quả là giống nhau cho các số có chữ ký và không dấu:

-2 + 1 = -1     1110 + 0001 = 1111
14 + 1 = 15     1110 + 0001 = 1111

Tuy nhiên , có những trường hợp ngoại lệ:

Division:
  -2 / 2 = -1     1110 / 0010 = 1111
  14 / 2 = 7      1110 / 0010 = 0111
Comparison:
  -2 < 2 = TRUE   1110 < 0010 = TRUE
  14 < 2 = FALSE  1110 < 0010 = FALSE
"Typical" (*) multiplication:
  -2 * 2 = -4     1110 * 0010 = 11111100
  14 * 2 = 28     1110 * 0010 = 00011100

(*) Trên nhiều CPU, kết quả của phép nhân hai số n bit là (2 * n) bit.

Đối với các hoạt động như vậy, CPU có các hướng dẫn khác nhau cho số học đã ký và không dấu.

Điều này có nghĩa là lập trình viên (hoặc trình biên dịch) phải sử dụng các hướng dẫn khác để ký và số học không dấu.

Ví dụ, CPU x86 có một lệnh được đặt tên divđể thực hiện phân chia không dấu và một lệnh được đặt tên idivđể thực hiện phân chia đã ký.

Ngoài ra còn có các hướng dẫn "có điều kiện" khác nhau (nhảy có điều kiện, set-bit-on-condition) cũng như các hướng dẫn nhân cho số học đã ký và không dấu.

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.