簡體   English   中英

CPU如何從內存中檢索多字節

[英]how does CPU retrieve multibyte from memory

嗨,我只是匯編編程的新手。 我很困惑CPU如何從內存中檢索多字節(例如32位機器為32位)。 假設我們有一個整數i,它在內存中占據4個字節(起始地址為0x100),因此當我們使用IA32匯編編程時,我們只寫類似以下內容:

movl 8(%esp), %eax

esp是當前堆棧指針。 8只是從堆棧指針地址到變量i的偏移量,因此當執行ia32指令時,cpu只是檢索0x100處的字節,其余的0x101、0x102、0x103處的字節呢? CPU如何一次檢索全部32位?

編輯:新問題 我認為我在理解單詞大小上是根本錯誤的。 但是我仍然很困惑,但是32位計算機如何檢索8字節64位的長整數,也許使用movq,但是又如何訪問256字節的對象呢? CPU只會發出movq 4次嗎? cpu如何事先知道發出mov命令以檢索大尺寸對象需要多少時間?

32位機器如何檢索8字節64位長整數

如果要在整數寄存器中執行此操作, 則編譯器必須使用多個指令 ,因為該體系結構沒有提供一次加載兩個32位寄存器的指令。 因此,CPU僅看到兩個單獨的加載指令。

考慮一下這些函數,這些函數gcc7.3 -O3 -m32為32位x86編譯 ,並在堆棧上傳遞了args,並且在edx:eax返回了64位整數(EDX中的高位,EAX中的低位)。 即i386 System V ABI。

int64_t foo(int64_t a) {
    return a + 2;
}
    movl    4(%esp), %eax
    movl    8(%esp), %edx
    addl    $2, %eax
    adcl    $0, %edx                   # add-with-carry
    ret


int64_t bar(int64_t a, int64_t b) {
    return a + b;
}

    movl    12(%esp), %eax      # low half of b
    addl    4(%esp), %eax       # add low half of a
    movl    16(%esp), %edx
    adcl    8(%esp), %edx       # carry-in from low-half add
    ret

CPU本身提供了指令,供程序員/編譯器在處理大於寄存器的數據時使用。 CPU僅支持作為指令集一部分的寬度,而不支持任意width 這就是我們擁有軟件的原因。

在x86上,編譯器可以選擇使用movq到XMM或MMX寄存器中,並使用paddq ,特別是如果這是一個更大的函數的一部分,該函數可以將64位結果存儲在內存中的某個地方,而不需要在整數寄存器中使用。 但這只能達到向量寄存器的極限,並且它們僅支持最大64位寬的元素。 沒有128位加法指令。

cpu如何事先知道發出mov命令以檢索大尺寸對象需要多少時間?

CPU只需按程序順序執行一次每條指令即可。 (或者在內部做任何想做的錯覺 )。

x86 CPU必須知道如何將任何可能的x86指令解碼為正確的內部操作。 如果CPU一次只能加載128位,則它必須將256位矢量加載(例如vmovups (%edi), %ymm0為內部多個加載操作(就像AMD一樣)。 請參閱David Kanter關於Bulldozer微體系結構的文章

或者可以將其解碼為特殊的加載操作,該操作在加載端口(如Sandybridge)中需要兩個周期,因此256位加載/存儲不會花費額外的前端帶寬,而只會在加載/存儲端口中花費額外的時間。

或者,如果它從L1d緩存到執行單元的內部數據路徑足夠寬(Haswell和更高版本),它可以解碼為一個簡單的加載uop,由緩存/加載端口在內部進行處理,就像mov (%edi), %eax或特別是vmovd (%edi), %xmm0 (將32位零擴展加載到向量寄存器中)。

256 個字節是32個qword; 當前的x86 CPU在單個操作中無法負載那么多。

256 是4個ymm或一個AVX ymm寄存器。 現代的Intel CPU(Haswell和更高版本)具有很寬的內部數據路徑,並且實際上可以一次將256位從高速緩存傳輸到向量加載執行單元,以單個vmovups ymm0, [rdi]執行vmovups ymm0, [rdi] 請參閱如何快速地進行緩存? 有關緩存的寬負載如何為L1d緩存提供極高的吞吐量/帶寬的更多詳細信息。

通常,CPU可以從內存中加載多個字節,因為它們被設計為可以加載,而ISA支持。

例如,它們的寄存器,內部總線,緩存設計和內存子系統就是為此目的而設計的。 從物理上講,能夠加載64位值的處理器可能在不同位置具有64條並行線以在CPU周圍移動64位(8字節)-但其他設計也是可行的,例如較小的16位總線可以傳輸兩個字節一次,甚至是一次串行傳輸一個位的位串行點對點連接。 同一CPU的不同部分可能使用不同的設計和不同的物理寬度。 例如,從DRAM讀取N位可以實現為從C芯片並行讀取M位,結果在存儲器控制器處合並,因此與內核到存儲路徑的其他部分相比,芯片需要支持的並行度更低。

ISA固有支持的寬度可能與硬件實現的自然寬度不同。 例如,當英特爾添加AVX ISA擴展,這是第一個支持256位(16字節)加載和存儲的擴展時,底層硬件最初將其實現為一對128位操作。 后來的CPU體系結構(Haswell)最終將其實現為完整的256位寬度的操作。 即使在今天,成本較低的x86芯片也可能會將大型裝載/存儲操作拆分為較小的單元。

最終,這些都是CPU的內部細節。 您可以依靠的是已記錄的行為,例如可以自動加載多少大小的值,或者對於記錄了該值的CPU,加載類型值需要多長時間。 內部如何實現它更多是電氣工程/ CPU設計問題,並且有很多方法可以實現。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM