2026
05
26
12
34
[C] VC compiler的最佳化
剛剛猛看這段組語還以為編譯器弄錯了.
因為 dec rcx (idx) 被放在後面了.
int idx = CRYPTO_SIZE_QUIC_IV;
while (full_pn != 0 && idx > 0) {
00007FF7F2EBA6E3 test rax,rax
00007FF7F2EBA6E6 je $err_to_free+3Ch (07FF7F2EBA708h)
00007FF7F2EBA6E8 mov ecx,0Ch
00007FF7F2EBA6ED nop dword ptr [rax]
00007FF7F2EBA6F0 test rcx,rcx
00007FF7F2EBA6F3 jle $err_to_free+3Ch (07FF7F2EBA708h)
hkdf_res.quic_iv[--idx] ^= full_pn & 0xff;
00007FF7F2EBA6F5 xor byte ptr [rsp+rcx+0AFh],al
00007FF7F2EBA6FC dec rcx
full_pn >>= 8;
00007FF7F2EBA6FF shr rax,8
00007FF7F2EBA703 test rax,rax
00007FF7F2EBA706 jne $err_to_free+24h (07FF7F2EBA6F0h)
}
}
我為了再次確認, 問了 claude code, 它認為這是正確的.
以下是 claude code的回答.
因為 dec rcx (idx) 被放在後面了.
int idx = CRYPTO_SIZE_QUIC_IV;
while (full_pn != 0 && idx > 0) {
00007FF7F2EBA6E3 test rax,rax
00007FF7F2EBA6E6 je $err_to_free+3Ch (07FF7F2EBA708h)
00007FF7F2EBA6E8 mov ecx,0Ch
00007FF7F2EBA6ED nop dword ptr [rax]
00007FF7F2EBA6F0 test rcx,rcx
00007FF7F2EBA6F3 jle $err_to_free+3Ch (07FF7F2EBA708h)
hkdf_res.quic_iv[--idx] ^= full_pn & 0xff;
00007FF7F2EBA6F5 xor byte ptr [rsp+rcx+0AFh],al
00007FF7F2EBA6FC dec rcx
full_pn >>= 8;
00007FF7F2EBA6FF shr rax,8
00007FF7F2EBA703 test rax,rax
00007FF7F2EBA706 jne $err_to_free+24h (07FF7F2EBA6F0h)
}
}
我為了再次確認, 問了 claude code, 它認為這是正確的.
以下是 claude code的回答.
dec rcx 的位置是正確的。這是編譯器實作 --idx(前置遞減)的一種等價轉換。
關鍵:offset 從 0xB0 調整為 0xAF
假設 quic_iv 的起始位址是 [rsp + 0xB0],C 語言的 quic_iv[--idx] 語意是:
先把 idx 減 1,再用新的 idx 當索引
編譯器有兩種等價的組語寫法:
寫法 A(dec 在前):
dec rcx ; idx = 12 → 11
xor byte ptr [rsp + rcx + 0B0h] ; quic_iv[11]
寫法 B(dec 在後,offset 補償)← 編譯器選擇的版本:
xor byte ptr [rsp + rcx + 0AFh] ; 0xAF = 0xB0 - 1,等同 quic_iv[rcx-1] = quic_iv[11]
dec rcx ; idx: 12 → 11,留給下一輪迴圈條件使用
寫法 A(dec 在前):
dec rcx ; idx = 12 → 11
xor byte ptr [rsp + rcx + 0B0h] ; quic_iv[11]
xor byte ptr [rsp + rcx + 0B0h] ; quic_iv[11]
寫法 B(dec 在後,offset 補償)← 編譯器選擇的版本:
xor byte ptr [rsp + rcx + 0AFh] ; 0xAF = 0xB0 - 1,等同 quic_iv[rcx-1] = quic_iv[11]
dec rcx ; idx: 12 → 11,留給下一輪迴圈條件使用
兩種寫法在每次迭代存取的位址完全相同,因為 0xAF = 0xB0 - 1 把「還沒遞減」的差距直接補在常數 offset 上。
我才知道現在編譯器最佳化有到這種程度了.
PS: 我有去驗證的確編譯器是有偷減offset.