如果 32 位處理器可以處理大約4 GiB的RAM(即 \ $ 2 ^ {32} = 4294967296 \ $ span>)個字節,為什麼我的Arduino Mega 2560具有8 KiB的SRAM,如果是 8 位處理器,則它只能處理256個字節( \ $ 2 ^ 8 \ $ span>)?還是我閱讀以下頁面不正確?
如果 32 位處理器可以處理大約4 GiB的RAM(即 \ $ 2 ^ {32} = 4294967296 \ $ span>)個字節,為什麼我的Arduino Mega 2560具有8 KiB的SRAM,如果是 8 位處理器,則它只能處理256個字節( \ $ 2 ^ 8 \ $ span>)?還是我閱讀以下頁面不正確?
大多數8位CPU都具有16位地址總線,允許它們尋址64 KB,這恰恰是因為256字節確實不足以完成很多工作!這僅表示每次需要加載地址時,它們都需要加載兩個字節而不是一個字節。考慮到它們的大小,速度稍慢但可以忍受。
(是的,有很多例外,大多數例外是在64k變得太小時開發出來的,但是我們在這裡談論的是基本思想)。
地址總線和數據總線是分開的,因此它們可能具有不同的大小。對於任何特定的地址總線大小,有很多技術可以尋址比寄存器位寬更多的內存
最常見的方法是增加地址總線
使用多個寄存器作為地址的寬度
X
, Y
和 Z
數據尋址寄存器,以允許最大64KB的RAM。依次將它們與 RAMPX
, RAMPY
, RAMPZ
配對,以訪問更大版本的更高RAM地址。除了具有超過256字節RAM 1 sup> li的變量中的 SPL
之外,它還具有用於堆棧指針高字節的 SPH
。 > H
& L
, B
& C
, D
& E
可以一起用作16位地址寄存器使用比自然大小大的單個大型特殊寄存器進行尋址
使用特殊寄存器來存儲地址的高位 。當尋址某些存儲器時,默認情況下,地址的低8位將取自8位微控制器上的8位立即數或8位寄存器,而高位將被另一個地址寄存器的值代替。 / p>
call
或 goto
指令時,立即數指示地址的8位或9位低位,其餘部分從當前程序計數器中獲取。因此訪問當前段附近的任何內容僅需使用一條指令,而進一步的地址將需要2條指令(以設置高位)。 PC
中的高6位相結合。實現此目標的另一種方法是 內存銀行 。這是一種有用的方法,如今仍在某些體系結構中使用。在此模型中,內存分為多個 bank 。每次您只能尋址特定的銀行。通常會有隨時可見的全局存儲區或地址範圍,但是對於其他部分,您必須在需要時切換存儲區。
還有一種不太常見的技術,但是可以在中找到英特爾8051 。作為具有8位數據地址的微控制器,它最多可以具有256個地址。一半的空間(高位部分)用於特殊功能寄存器( SFR ),從而將可尋址的實際RAM限制為僅128個字節。但是現代的8051系列製造商發現了一種巧妙的方法來解決此問題,方法是 分離內存訪問 。儘管寄存器將訪問RAM的高端,但直接尋址將訪問 SFR ,而間接尋址將訪問RAM,這意味著現在您有256 + 128 = 384可尋址字節。
1 sup> https://en.wikipedia.org/wiki/Atmel_AVR_instruction_set#Memory_addressing_instructions
最小的內核具有≤256字節的數據地址空間(意味著在除去I / O端口和其他保留地址後,≤128字節的RAM)和≤8192字節(8 KiB)的程序ROM。它們僅具有8位堆棧指針(在SPL中),並且僅支持12位相對跳轉/調用指令RJMP / RCALL。 (由於AVR程序計數器計數的是16位字而不是字節,因此12位偏移量足以尋址213個字節的ROM。)
根據訪問訪問資源的需要,還具有其他的內存尋址功能:
- 具有> 256字節數據地址空間(≥256字節RAM)的模型具有16位堆棧指針,
- ROM大於8 KiB的模型添加2字(22位)JUMP和CALL指令。 (如果在跳過指令後接2字指令,則某些早期模型會出現錯誤。)
- ROM大於64 KiB的模型會添加ELPM指令和相應的RAMPZ寄存器。 LPM指令將ROM地址零擴展到Z; ELPM指令在RAMPZ寄存器前添加高位。這與更通用的LPM指令不同。存在只有ELPM的零操作數形式的“經典”模型(ATmega103和at43usb320)。當自動遞增功能可用時(大多數型號),它會更新包括RAMPZ在內的整個24位地址。
- (稀有)ROM> 128 KiB的型號具有3字節程序計數器。子例程調用和返回使用額外的堆棧空間字節,有一個新的EIND寄存器為工業跳轉和調用提供了附加的高位,還有新的擴展指令EIJMP和EICALL,它們使用EIND:Z作為目標地址。 (以前的IJMP和ICALL指令使用零擴展Z。)
- (稀有)RAM地址空間大於64 KiB的模型通過RAMPX,RAMPY,RAMPZ和RAMPD寄存器擴展了16位RAM尋址限制。 。它們分別為使用X,Y或Z寄存器對或直接尋址指令LDS / STS的尋址模式提供了額外的高位。與ROM訪問不同,沒有明顯的“擴展”指令。而是無條件使用RAMP寄存器。
ol>
數據總線線(引腳)和地址線(引腳)完全分開。簡而言之,數據總線線確定一次最多可傳輸一次(並存儲在存儲器中)的最大位數,而地址線確定一次可以選擇的最大存儲“單元”數。
大部分是32位x86 CPU不能處理超過4GB RAM的市場營銷活動。我記得某個地方在奔騰4 CPU上有A33-34引腳。
幾乎所有8位處理器都具有從低階部分和高階部分形成16位地址的能力。在包括原始8080在內的某些處理器上,有一些專用於保存地址的上部和下部的寄存器(儘管從程序員的角度來看,可能還有某些寄存器,例如8080的堆棧指針,它們沒有提供單獨尋址的指令)。在其他一些處理器中,沒有專門用於地址上半部或下半部的寄存器,但是地址是“即時”彙編的。例如,在6502上,指令“ LDA $ 1234,X”將通過將$ 1234加到8位X寄存器[假定它包含$ F0]而形成的地址裝入累加器。該指令的執行將分4步或5步進行:
如果檢查操作順序,則會注意到一點端架構比大端架構具有明顯優勢,在大多數情況下(儘管未顯示),即使ALU佔用了一個優勢。循環執行加法操作,可以從計算的地址讀取一個字節而無需等待ALU結果,因為通常提取的高字節將是目標操作數的高字節。在具有8位ALU的big-endian機器上,索引加載至少需要5個週期(因為地址的下半部分要到第3步才能讀取,因此將在第4步中進行計算)。
可尋址內存大小和內部寄存器大小之間通常存在某些關係,儘管這種關係由於不同的原因而有所不同。甚至在微處理器的早期,就認為256字節的地址空間太小,因此大多數八位處理器產生16位(兩個字節)的地址,該地址尋址64 KB。但是,通過存儲體切換(基本上使用某些I / O線來產生更多的地址線),可以實現更多的功能。
在前16位和32位處理器中,設備上的引腳總是不足以到達其內部地址寄存器可以尋址的所有空間。例如,在Motorola 68000上,儘管內部地址寄存器為32位寬,但只有足夠的地址引腳(24)可以尋址16 MB的RAM。
我將專門針對您提到的AVR控制器回答此問題。基本原理對於許多其他8位架構也適用。
AVR是8位內核。這意味著它們具有8位寄存器。但是,8位不足以訪問可用的內存量。因此,AVR內核能夠使用一組特定的寄存器,將其組合為16位指針寄存器。寄存器r30和r31(也別名為ZL和ZH)就是一個例子。它們一起形成Z指針。
在彙編中讀取地址0x1234的字節看起來像這樣:
ldi ZL,0x34;用地址的低字節加載r30(ZL)
ldi ZH,0x12;向r31(ZH)加載地址的高字節
ld r16,Z;將字節加載到r16
AVR系列有3個寄存器對可用於此目的。它們是專門為允許此類操作而設計的硬件。
當使用C之類的高級語言進行編程時,編譯器會處理這些東西。
注意:某些AVR甚至支持大於64k的內存大小。這些控制器具有特殊的功能寄存器,其中的其他位地址在訪問之前被寫入。因此,該地址由以下位(MSB至LSB)組成:
特殊功能寄存器(通常僅使用1位),ZH(8位),ZL(8位)。這樣產生的總地址為17位,並允許訪問128 kiB的RAM。
Wikipedia對此進行了很好的解釋:
八位CPU使用8位數據總線,因此可以在一條機器指令中訪問8位數據。 。由於實際和經濟上的考慮,地址總線通常是雙八位位組寬(即16位)。這意味著在大多數8位處理器上,直接地址空間僅為64 KB。
Atmel的8位AVR實際上使用16位數據地址。還有許多其他的16位寄存器,甚至還有一些16位定時器。由於它只是8位處理器,因此通常使用兩個時鐘週期來加載16位寄存器。
處理器的“位寬”建立了處理器可以處理的最大RAM量的觀念是計算中最普遍的神話之一。實際上,行業歷史上充斥著沒有這種關係的CPU。
HP 21MX,HP 1000:16位CPU,內存為16 MB
PDP-11:16位CPU,內存為4 MB
VAX-11 / 780:32位CPU,內存為512 MB
等,等等。