Làm thế nào để một máy tính xác định kiểu dữ liệu của một byte?


31

Ví dụ: nếu máy tính đã 10111100lưu trữ trên một byte RAM cụ thể, làm thế nào máy tính biết để giải thích byte này dưới dạng một số nguyên, ký tự ASCII hoặc một cái gì khác? Là loại dữ liệu được lưu trữ trong một byte liền kề? (Tôi không nghĩ đây là trường hợp vì điều này sẽ dẫn đến việc sử dụng gấp đôi dung lượng cho một byte.)

Tôi nghi ngờ rằng có lẽ một máy tính thậm chí không biết loại dữ liệu, mà chỉ có chương trình sử dụng nó mới biết. Tôi đoán là vì RAM là R AM và do đó không được đọc tuần tự, nên một chương trình cụ thể chỉ yêu cầu CPU lấy thông tin từ một địa chỉ cụ thể và chương trình xác định cách xử lý nó. Điều này có vẻ phù hợp với những thứ lập trình như nhu cầu về typecasting.

Có phải tôi đang trên đường ray bên phải không?


4
Như một lưu ý phụ: Nếu bạn đang nói về các loại, bạn phải làm điều đó trong ngữ cảnh ngôn ngữ. Nó để lại cho trình biên dịch để xử lý loại điều đó (ký hiệu, loại kiểm tra, thao tác, truyền, ram địa chỉ, v.v.). CPU và RAM chỉ biết byte
jean

4
Kiểu dữ liệu của một byte là một byte. Ngoài ra, máy tính không biết gì cả. Một chương trình có thể hiểu một byte hoặc một nhóm byte là một loại dữ liệu cụ thể và cố gắng thực hiện các hoạt động trên các byte đó, nhưng không có hạn chế nào ở đó. Cùng một nhóm byte có thể được hiểu là nhiều hơn một loại dữ liệu (nghĩa là truyền con trỏ tới các loại giá trị, các hiệp hội giống như C, v.v.). RAM không được đọc tuần tự không thực sự phù hợp. - Đó là nhiều hơn vì RAM là mục đích chung. - Các thanh ghi chẳng hạn cũng không được đọc tuần tự, nhưng chúng được gõ.
BrainSlugs83

5
Không biết xấu hổ về bản thân, nhưng câu hỏi này về cơ bản đã được hỏi về các lập trình viên SE khoảng một tháng trước. Đây là câu trả lời của tôi cho nó . Nó khá dài vào thời điểm này, nhưng tấn công nó từ nhiều góc độ khác nhau.
Shaz

2
Một hậu quả hữu ích của thực tế là phần cứng là kiểu dữ liệu bất khả tri là một byte đơn (hoặc từ, v.v.) có thể được diễn giải theo nhiều cách bởi một chương trình. Đáng chú ý, tạm thời giải thích một số dấu phẩy động như một số nguyên được sử dụng để tính căn bậc hai nghịch đảo nhanh .
Aoeuid

@ BrainSlugs83, bạn có thể cân nhắc chuyển đổi nó thành câu trả lời không?
DW

Câu trả lời:


38

Sự nghi ngờ của bạn là chính xác. CPU không quan tâm đến ngữ nghĩa của dữ liệu của bạn. Đôi khi, mặc dù, nó làm cho một sự khác biệt. Ví dụ, một số phép toán số học tạo ra các kết quả khác nhau khi các đối số được ký hoặc không dấu. Trong trường hợp đó, bạn cần cho CPU biết bạn dự định giải thích gì.

Tùy thuộc vào lập trình viên để hiểu ý nghĩa của dữ liệu của cô ấy. CPU chỉ tuân theo mệnh lệnh, không biết ý nghĩa hay mục tiêu của chúng.


1
Về "khi các đối số được ký kết hoặc không dấu", CPU sẽ biết như thế nào? Các hoạt động của CPU chỉ nhìn thấy các byte tham số và thiếu loại nhận thức ngữ cảnh kiểu dữ liệu đó. Bạn ngụ ý kiểu dữ liệu bằng cách chọn hoạt động CPU thích hợp (hoặc trình biên dịch của bạn thực hiện).
Shiv

4
@Shiv Trong những trường hợp như vậy, CPU thực sự được ban hành một hướng dẫn khác để xử lý các số đã ký so với số không dấu. Như những nghi ngờ của OP, chương trình bắt buộc phải cung cấp những chi tiết đó, vì CPU không biết.
Cort Ammon - Phục hồi Monica

2
Tôi đã làm việc với máy tính miễn là tôi nhớ bản thân mình và mặc dù tôi biết rằng CPU không quan tâm đến các cấu trúc cấp cao mà chúng tôi sử dụng trong lập trình cấp cao, nhưng thỉnh thoảng sự phân tách các khái niệm này vẫn khiến tôi hoảng sợ
Loupax

1
@Loupax Vâng, làm việc với một hội đồng cấp thấp thực sự giúp ích khá nhiều - thậm chí mov al, 42là loại cấp cao - rõ ràng chỉ có một hướng dẫn khả thi mà điều này có thể gọi, nhưng nó vẫn hơi bị trừu tượng hóa. Tuy nhiên, việc sử dụng mov.8 al, 42rõ ràng làm cho điều này rõ ràng đau đớn :)
Luaan

1
@Shiv: Tôi muốn lưu ý rằng có những máy mà dữ liệu trong bộ nhớ được nhập. Chúng được gọi là kiến ​​trúc bộ nhớ được gắn thẻ (hoặc đơn giản là kiến ​​trúc được gắn thẻ) nhưng chúng không thành công về mặt thương mại như các kiến ​​trúc thông thường một phần vì chúng ta hiện lập trình chủ yếu bằng các ngôn ngữ được biên dịch thay vì lắp ráp và trình biên dịch sẽ lo việc gõ. Xem: vi.wikipedia.org/wiki/Tagged_arch
architecture

14

Như những người khác đã trả lời, các CPU thông thường ngày nay không biết vị trí bộ nhớ cụ thể chứa gì; phần mềm quyết định.

Tuy nhiên, có những khả năng khác. Ví dụ, Lisp Machines đã sử dụng một kiến trúc được gắn thẻ lưu trữ loại của từng vị trí bộ nhớ; theo cách đó, bản thân phần cứng có thể thực hiện một số công việc của các ngôn ngữ cấp cao.

Và ngay cả bây giờ, tôi đoán bạn có thể coi bit NX trong Intel, AMD, ARM và các kiến ​​trúc khác tuân theo cùng một nguyên tắc: phân biệt ở cấp độ phần cứng cho dù một vùng bộ nhớ nhất định có chứa dữ liệu hoặc hướng dẫn hay không.

Ngoài ra, chỉ để hoàn thiện, trong các kiến trúc và dữ liệu của các kiến trúc Harvard (như một số bộ vi điều khiển) được tách biệt về mặt vật lý, do đó CPU có một số ý tưởng về những gì nó đang đọc.

Trong câu hỏi Quora này, có một số bình luận về cách bộ nhớ được gắn thẻ hoạt động, ý nghĩa hiệu suất và sự sụp đổ của nó, v.v.


Kiến trúc được gắn thẻ là một lưu ý thú vị. Nó sẽ nhanh hơn đáng kể?
Bassinator

4

Vâng. Chương trình chỉ cần lấy một byte từ bộ nhớ và nó có thể diễn giải nó theo ý muốn.


3

Không có chú thích loại.
RAM lưu trữ dữ liệu thuần túy, và sau đó chương trình xác định những việc cần làm.

Với các thanh ghi CPU khó hơn một chút, nếu bạn có các thanh ghi loại đã cho (như FPU), bạn cho biết những gì bên trong.
Hoạt động trên các thanh ghi dấu phẩy động được sử dụng rõ ràng bằng cách sử dụng dữ liệu đánh máy. Bạn hoặc trình biên dịch của bạn cho biết những gì và khi nào nên được đặt ở đó, vì vậy bạn không có tự do như vậy.
Máy tính không đưa ra bất kỳ giả định nào về dữ liệu cơ bản trong RAM và trong các thanh ghi có một ngoại lệ - các thanh ghi được gõ trong CPU thuộc loại đã biết, được tối ưu hóa để xử lý nó. Điều này chỉ để chỉ ra rằng có những nơi dữ liệu thuộc loại dự kiến, nhưng không có gì ngăn bạn truyền chuỗi sang phao và nhân chúng.

Trong các ngôn ngữ lập trình, bạn chỉ định loại hoặc trong ngôn ngữ cấp cao hơn, dữ liệu chung và trình biên dịch / trình thông dịch / VM mã hóa những gì bên trong có phí.
Ví dụ trong C, kiểu con trỏ của bạn cho biết phải làm gì với dữ liệu, cách truy cập nó.

Tất nhiên bạn có thể đọc chuỗi (ký tự) và sau đó coi là giá trị dấu phẩy động, số nguyên và trộn chúng.


Ngay cả các bit trong thanh ghi FPU không luôn biểu thị các giá trị dấu phẩy động. Ngày xưa (có thể không còn nhiều nữa?), Một tối ưu hóa phổ biến là sử dụng các thanh ghi dấu phẩy động (64 bit hoặc lớn hơn) để sao chép dữ liệu nhanh hơn các thanh ghi mục đích / số nguyên (32 bit), lớn gấp đôi, họ thường có thể sao chép dữ liệu nhanh gấp đôi.
Seth

1
Tôi hoàn toàn đồng ý với bạn, đó là lý do tại sao tôi đã viết ai đó có thể đẩy chuỗi ở đó. Và trong cùng thời gian, mọi người đã thực hiện các phép toán dấu phẩy động trên các số nguyên, vì nó nhanh hơn. Đó là điểm!
Ác

@HCBPshenanigans có các hướng dẫn thao tác các giá trị dấu phẩy động. Nếu FADD được sử dụng, điều đó chỉ có nghĩa là các nhóm bộ nhớ (4,8 hoặc 10) có các số dấu phẩy động. Điều đó đúng với một số loại hướng dẫn: nhân hai số nguyên chỉ có ý nghĩa nếu chúng là số nguyên, nhảy chỉ có ý nghĩa nếu đó là một địa chỉ.
JDługosz

@seth và evilJS không được coi là trường hợp của dấu phẩy động kế thừa xếp chồng 8087, nhưng là trường hợp cho các thanh ghi CIMD mới hơn có thể được sử dụng chỉ để tải / lưu mà không cần giải thích (mặc dù chúng phải được căn chỉnh) và một cảnh báo rằng nếu các thanh ghi CIMD không bao giờ được sử dụng thì chúng không cần phải được lưu trong một chuyển đổi ngữ cảnh. Nếu bạn (chỉ) di chuyển 8 byte qua đăng ký XMM thì đó là tổn thất ròng vì toàn bộ tập hợp cần phải được lưu.
JDługosz

3

CPU không quan tâm, nó thực thi mã lắp ráp, nó chỉ đơn thuần di chuyển dữ liệu xung quanh, dịch chuyển nó, thêm hoặc nhân nó ...

Các loại dữ liệu là một khái niệm ngôn ngữ cấp cao hơn: trong C hoặc C ++, bạn cần chỉ định các loại cho mỗi phần dữ liệu bạn thao tác; Trình biên dịch C / C ++ đảm nhiệm việc chuyển đổi các phần dữ liệu này thành các lệnh phù hợp để CPU xử lý (trình biên dịch ghi mã lắp ráp)

Trong một số ngôn ngữ cấp cao hơn, các loại có thể được suy ra: trong Python hoặc Javascript, chẳng hạn, người ta không phải chỉ định loại dữ liệu, tuy nhiên dữ liệu có một loại và bạn không thể thêm một chuỗi có số nguyên, nhưng bạn có thể thêm một số float với một số nguyên: 'trình biên dịch' (trong trường hợp Javascript là Trình biên dịch JIT (Just in Time). Javascript thường được gọi là ngôn ngữ 'phiên dịch' vì các trình duyệt trước đây diễn giải mã Javascript, nhưng ngày nay các công cụ Javascript là trình biên dịch.

Mã, luôn luôn được biên dịch thành mã máy, nhưng rõ ràng định dạng mã máy phụ thuộc vào máy bạn đang nhắm mục tiêu (mã x86 64 bit sẽ không hoạt động trên máy x86 32 bit hoặc bộ xử lý ARM chẳng hạn)

Vì vậy, thực sự có rất nhiều lớp liên quan đến việc chạy mã được diễn giải.

Java và C # là những thứ thú vị khác, vì mã Java hoặc C # về mặt kỹ thuật được 'biên dịch' thành nhị phân Java (mã byte), nhưng chính mã đó sau đó được Java Runtime giải thích, dành riêng cho phần cứng cơ bản (cần cài đặt JRE nhắm mục tiêu đúng máy để chạy nhị phân Java (Jars))


Một trình biên dịch biên dịch, có thể là JIT hoặc không; và một trình thông dịch phiên dịch mà không cần biên dịch (vì nếu không nó sẽ là trình biên dịch!). Chúng là những thứ rất khác nhau. Và liên quan đến việc "Java trở nên buồn cười" vì giải thích mã byte, hãy xem xét rằng ngay cả mã máy x86 sẽ thực sự được giải thích (hoặc thậm chí được biên dịch?) Bởi bộ vi xử lý thành vi mã .
hmijail

Cảm ơn đã làm rõ ... Đồng ý: trình biên dịch biên dịch và trình thông dịch phiên dịch. Trong trường hợp Javascript mặc dù câu chuyện hơi phức tạp do một số trình duyệt cũ giải thích mã, trong khi các trình duyệt hiện đại hơn thực sự biên dịch đúng lúc, đó có thể là lý do tại sao nó vẫn được gọi là ngôn ngữ 'diễn giải' mặc dù nó là về mặt kỹ thuật không còn nữa.
MrE

Nhưng AFAIK, JS bắt đầu diễn giải, và sau đó có thể được biên dịch khi cần thiết. Và JIT có thể chuyển từ phiên dịch sang biên dịch sang giải thích lại, tùy thuộc vào rất nhiều thứ. Ví dụ, một đoạn mã có thể được biên dịch cho một biến có kiểu đã cho; nhưng sau đó mã được chạy lại với biến mà có một kiểu khác nhau, do các mã biên dịch hiện tại không thể được sử dụng để thông dịch nhảy trong - cho đến khi mã được biên dịch một lần nữa cho kiểu mới ...
hmijail

Bạn đang trích dẫn tôi về điều mà tôi không nói, xin vui lòng xóa nó vì nó hoàn toàn sai. Microcode KHÔNG CÓ gì để làm với HĐH; đó là một cái gì đó bên trong bộ vi xử lý. 32 bit hoặc 64 bit cũng không có gì để làm với nó.
hmijail

3

Datatypes không phải là một tính năng phần cứng. CPU biết một vài lệnh (tốt, rất nhiều) các lệnh khác nhau. Chúng được gọi là tập lệnh của CPU.

Một trong những cái được biết đến nhiều nhất là tập lệnh x86 . Nếu bạn tìm kiếm "nhân" trên trang này, bạn sẽ nhận được 50 kết quả. MULPDMULSDcho phép nhân đôi, FIMULcho phép nhân số nguyên, ...

Những lệnh này làm việc trên các thanh ghi. Các thanh ghi là các khe nhớ có thể chứa một số bit cố định (thường là 32 hoặc 64, tùy thuộc vào kiến ​​trúc mà CPU của bạn sử dụng), bất kể các bit này thể hiện điều gì. Do đó, lệnh CPU diễn giải các giá trị của các thanh ghi theo một cách khác, nhưng bản thân các giá trị không có kiểu.

Một ví dụ đã được đưa ra tại PyCon 2017 bởi Stuart Williams :

nhập mô tả hình ảnh ở đây


1
Lưu ý rằng điều này không hoàn toàn đúng: có các thanh ghi mục đích đặc biệt không thể chứa các giá trị tùy ý (ví dụ: các thanh ghi con trỏ không chỉ bất kỳ địa chỉ nào và không cho phép bổ sung tùy ý hoặc các thanh ghi dấu phẩy động nơi bạn có thể 't lưu trữ các giá trị không chuẩn hóa). Nhưng câu trả lời của bạn là chính xác cho các thanh ghi mục đích chung trên hầu hết các kiến trúc.
Gilles 'SO- ngừng trở nên xấu xa'

2

... rằng một chương trình cụ thể chỉ yêu cầu CPU lấy thông tin từ một địa chỉ cụ thể và chương trình xác định cách xử lý nó.

Chính xác. Nhưng RAM không được đọc "tuần tự" và nó là viết tắt của Bộ nhớ truy cập ngẫu nhiên hoàn toàn ngược lại.

Bên cạnh việc biết byte là gì , bạn thậm chí không biết đó là byte hay một mảnh của một mục lớn hơn như số dấu phẩy động.

Tôi muốn thêm vào các câu trả lời khác bằng cách đưa ra một số ví dụ cụ thể.

Hãy xem xét 01000001. Chương trình có thể sao chép nó từ nơi này sang nơi khác như một phần của một lô dữ liệu lớn mà không liên quan đến ý nghĩa của nó. Nhưng sao chép nó vào địa chỉ được sử dụng bởi bộ đệm video ở chế độ văn bản sẽ khiến chữ cái Ahiển thị ở một số vị trí trên màn hình. Hành động chính xác tương tự khi thẻ ở chế độ đồ họa CGA sẽ hiển thị pixel màu đỏ và pixel màu xanh.

Trong một thanh ghi, nó có thể là số 65 dưới dạng một số nguyên. Làm số học để thiết lập bit của 32 có thể có nghĩa bất cứ điều gì mà không bối cảnh, nhưng đặc biệt có thể thay đổi một bức thư cho chữ thường.

CPU 8086 (vẫn) có các hướng dẫn đặc biệt được gọi là DAA được sử dụng khi thanh ghi giữ 2 chữ số thập phân, vì vậy nếu bạn chỉ sử dụng lệnh đó, bạn sẽ hiểu nó là hai chữ số 41.

Các chương trình bị sập vì một từ bộ nhớ được đọc nghĩ rằng đó là một con trỏ khi một thứ khác được lưu trữ ở đó.

Sử dụng trình gỡ lỗi, kiểm tra bộ nhớ, bản đồ được sử dụng để hướng dẫn diễn giải để hiển thị. Không có thông tin ký hiệu này, trình gỡ lỗi cấp thấp cho phép bạn chỉ định: hiển thị địa chỉ này dưới dạng các từ 16 bit, hiển thị địa chỉ này dưới dạng dấu phẩy động dài, dưới dạng chuỗi ... bất cứ điều gì. Nhìn vào một kết xuất gói mạng hoặc định dạng tệp không xác định, đánh đố nó là một thách thức.

Đó là một nguồn sức mạnh và tính linh hoạt chính trong kiến ​​trúc máy tính hiện đại: một ô nhớ có thể có nghĩa là bất cứ thứ gì , dữ liệu hoặc chỉ dẫn, chỉ ẩn trong ý nghĩa của nó đối với chương trình bởi những gì nó làm với giá trị và ảnh hưởng của nó đến các hoạt động tiếp theo. nghĩa là sâu hơn chiều rộng nguyên: những ký tự này ... ký tự trong ascii hay ebcdic? Hình thành từ bằng mã sản phẩm tiếng Anh hoặc SQU? Địa chỉ để gửi đến hoặc địa chỉ trả lại nó đến từ đâu? Việc giải thích thấp nhất cấp (bit logic; số nguyên-như, ký kết hoặc unsigned; float; BCD; con trỏ) là ngữ cảnh ở cấp hướng dẫn-set, nhưng nhận thấy rằng đó là tất cả các bối cảnh ở một mức độ nào: sự đểđịa chỉ là những gì nó là do vị trí nó được in trên phong bì. Nó theo ngữ cảnh của các quy tắc của người đưa thư, không phải CPU. Bối cảnh là một liên tục lớn, với các bit ở một đầu của nó.


※ Chú thích: Lệnh DAA được mã hóa dưới dạng byte 00100111. Vì vậy, byte đó là lệnh đã nói ở trên nếu được đọc trong luồng lệnh và các chữ số 27nếu được hiểu là các chữ số bcd và 0x27 = 39 là một số nguyên, là số 9 trong ASCII và là một phần của bảng ngắt (một nửa của INT 13 Địa chỉ 2 byte, được sử dụng cho các thói quen dịch vụ BIOS).


1

Cách duy nhất mà máy tính biết rằng một vị trí bộ nhớ là một lệnh là một thanh ghi mục đích đặc biệt được gọi là con trỏ lệnh trỏ đến chúng tại điểm này hay điểm khác. Nếu con trỏ lệnh trỏ đến một từ bộ nhớ, nó được tải dưới dạng một lệnh. Ngoài ra, máy tính không có cách nào biết được sự khác biệt giữa các chương trình và các loại dữ liệu khác.

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.