我使用下面的函數由1位的矢量的數據進行移位(由2多重峯):VC內聯彙編 - 與RCL(RCR)移
vec shl(vec n) {
n.resize(n.size() + 1, 0);
unsigned int* adr = n.data();
unsigned int s = n.size();
_asm {
clc
mov ecx, 0
mov edx, dword ptr [adr]
nloop:
mov eax, dword ptr[edx + ecx * 4]
rcl eax, 1
mov dword ptr [edx + ecx * 4], eax
inc ecx
jc carryisset ; check carry - breakpoint
jmp nocarry ; ~ breakpoint
carryisset : ; ~ breakpoint
jmp nocarry ; ~ breakpoint
nocarry: ; ~ breakpoint
cmp ecx, dword ptr [s]
jl nloop
};
return n;
};
所以,我讀過rcl
使用進位位並將其添加到高位。但是,當進位位未根據調試器設置時,rcl繼續將其添加到eax
。
例如:
#include <iostream>
#include <vector>
typedef std::vector<unsigned int> vec;
const unsigned int uint_max = (unsigned int)(~0);
vec n1 = { uint_max, 2, 2, 1, 0, 0, 0 };
vec n2
int main() {
n2 = shl(n1);
for (auto i : n2)
std::cout << i << " ";
return 0;
};
輸出:
4294967294 5 5 3 1 1 1 1
通過與調試代碼步進:
loop: first iteration (ecx = 0)
eax <- uint_max
eax <- rotate left with carry (rcl)
now eax is uint_max - 1
jumps to carryisset (with jc), so there is a carry
loop: second iteration (ecx = 1)
eax <- 2
eax <- rotate left with carry (rcl)
now eax is 2 << 2 + (carry)1 = 5
jumps to nocarry (with jc), so there is no carry
loop: third iteration (ecx = 2)
eax <- 2
eax <- rotate left with carry (rcl)
now eax is 2 << 2 + carry (should be 0, not set), but eax gives 5 too, like there were carry.
jumps to nocarry (with jc), so there is no carry (at least according to jc)
...ect
因此,有在這種情況下,第一迭代後沒有進位,但進位不會「重置」。 此實現來自SO帖子Large binary shifts in 8086 assembly?(接受的答案):
首先,確保進位標誌爲零。然後:
1.將4個字節到寄存器
2. RCR - 在我的情況RCL 3.寫回
4.重複下一個4個字節
但是進位總是就當我向左旋轉(或試圖與權利,同樣的結果:在vec(2,0,0,0,0...)
情況下,它是vec(1, uint_max/2 + 1, uint max/2 + 1, ...)
)
PS:我做了一個工作班次避免攜帶和檢查的最高位,但它是一個過於複雜,我認爲:
_asm {
clc
mov edx, dword ptr [adr]
xor ebx, ebx
xor ecx, ecx
xor eax, eax
nloop:
mov eax, dword ptr[edx + ecx * 4]
push edx
mov edx, ebx
mov ebx, eax
and ebx, 0x80000000
shr ebx, 31
shl eax, 1
add eax, edx
pop edx
mov dword ptr [edx + ecx * 4], eax
inc ecx
xor eax, eax
cmp ecx, dword ptr [s]
jl nloop
};
第一個代碼有什麼問題,如何使用rcl
和rcr
進行移位?
在C中編寫代碼並查看編譯器輸出的內容 – James
CMP指令更改進位。你需要重新考慮這一點。 –
hm,我已經刪除了CMP,確實有效(只能用調試器檢查),但是現在我必須找到一些東西來檢查計數器來結束循環。 pushf和popf? –