簡體   English   中英

使用 rN 寄存器 (r8,r9,...) 的匯編比其他寄存器具有更多的代碼大小

[英]Assembly using rN registers (r8,r9,...) have more code-size than other registers

我有一個關於使用“rN”寄存器的問題(r8,r9,r10,....)

我想在我的程序中使用 r8,r9,... 寄存器(大量使用!)但我發現代碼大小問題!

例如,

mov eax, DWORD [rdi+4]

等於 ( 8b 47 04 ) (反匯編程序)

但是當我使用“rN”寄存器時,情況就不一樣了!

mov eax, DWORD [r9+4]

它等於 ( 41 8b 41 04 ) (它有一個額外的字節(前綴)!)

所以使用rN寄存器比使用其他寄存器有更多的代碼大小!!!!!!!!!!!!!!!!!!!!! 首先,為什么?!!!

其次,除了代碼大小問題,如果我們使用 rN 寄存器 (r8,r9,r10,...) 而不是其他寄存器,是否還有其他問題,例如 (CACHE, CYCLE, ...)?

所以使用 rN 寄存器比使用其他寄存器有更多的代碼大小

是的,這是眾所周知且有據可查的事實。 REX 前綴是 x86-64 機器碼與早期模式相比最重要的變化之一,這個問題只值得在性能部分回答(見下文)。

x86 機器碼只有 3 位的寄存器字段。 第 4 位(如果非零)需要來自 REX 前綴。

這就是 AMD64 重新利用0x4? 操作碼字節(在 32 位機器代碼中,它們是 1 字節 inc/dec reg 指令)。

為了讓 x86-64 解碼在與 16/32 位模式解碼相同的晶體管上運行,而不是在前端需要一個全新的解碼器塊,AMD 選擇不從頭開始重新設計 x86 機器代碼。 所以他們被困在寄存器的 3 位字段中,不得不使用前綴字節。

有關 REX 前綴的更多信息,請閱讀 Intel 的 vol.2 手冊。 或者https://wiki.osdev.org/X86-64_Instruction_Encoding#REX_prefix有一些有用的東西,包括比特含義的細節。 它還解釋了:

在以下情況下必須對 REX 前綴進行編碼:

  • 使用 64 位操作數大小並且指令不默認為 64 位操作數大小(大多數指令默認為 32 位操作數大小); 或者
  • 使用擴展寄存器之一(R8 到 R15、XMM8 到 XMM15、YMM8 到 YMM15、CR8 到 CR15 和 DR8 到 DR15); 或者
  • 使用統一字節寄存器 SPL、BPL、SIL 或 DIL 之一。

並且在使用 AH、CH、BH 或 DH 時不能使用。 (一個 REX 前綴,即使沒有設置位,也會將 AH 的編碼含義更改為 SPL,依此類推。)

(帶有 VEX 前綴(例如 AVX 和一些 BMI/BMI2)或 EVEX (AVX512) 的指令使用它代替 REX 來獲取額外的寄存器位。一個 2 字節的 VEX 可以將 X/YMM8..15 編碼為目標或第一個源,無需使用更寬的 3 字節 VEX 前綴。)


其次,除了代碼大小問題,如果我們使用 rN 寄存器 (r8,r9,r10,...) 而不是其他寄存器,是否還有其他問題,例如 (CACHE, CYCLE, ...)?

不,只是代碼大小(以及某些 CPU 的總前綴數) 帶有 uop 緩存的 CPU 大多不受代碼大小的直接影響,但間接影響如更大的 I-cache 占用空間(以及 uop 緩存的密度較低)仍然是一個問題。 當然,在大規模上,更大的二進制文件。

但是一些 CPU(特別是 Silvermont 系列)解碼超過 3 個前綴的指令很慢,因此例如任何帶有 REX 前綴的 SSSE3/SSE4 指令都會使解碼器停頓 請參閱Agner Fog 的 microarch pdf 在 Silvermont,即使是 2 字節操作碼的0F操作碼轉義字節也算作 3 個之一,以及 SIMD 指令編碼的強制性前綴。

  401000:       66 0f 38 00 07          pshufb xmm0,XMMWORD PTR [rdi]   # 3 prefixes before the 00 opcode
  401005:       66 41 0f 38 00 00       pshufb xmm0,XMMWORD PTR [r8]    # 4 prefixes

后者在 Silvermont 上會特別慢。 在其他有 3 個前綴限制的 CPU 上很好(一些 AMD IIRC); 只有 Silvermont-family 將 0F 字節計為前綴。

主流 Intel CPU 可以解碼任意數量的前綴而不會停頓,僅受它們在尋找指令之間邊界的預解碼階段每個時鍾周期可以查看多少字節機器碼的限制,以及主要解碼階段最多可將 5 條指令(或更多使用宏融合)轉換為最多 5 條指令。 (Skylake) 其中之一的長度限制為每個周期 16 個字節; IIRC 它是預解碼; 如果重要,請查看 Agner Fog 的指南。

暫無
暫無

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

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