(2에 의한 멀티 포트) : 그래서VC의 인라인 어셈블리 - RCL (RCR)로 이동 내가 1 비트에 의해 벡터의 데이터를 이동하기 위해 다음과 같은 기능을 사용하고
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? (허용 대답)에서 온 :
첫째, 캐리 플래그가 제로 있는지 확인합니다. 캐리 비트는 항상 내 경우 RCL 다시 밖으로
를 반복 다음 4 바이트
3. 쓰기에서 그러나 -
1. 풀 레지스터
2 RCR로 4 바이트 : 그럼 I 좌측 회전시에 (또는 오른쪽으로 동일한 결과를 시도 : vec(2,0,0,0,0...)
경우에서이다 vec(1, uint_max/2 + 1, uint max/2 + 1, ...)
)
PS : I가 작동 시프트 반송을 방지하고, 최상위 비트를 체크했다하지만 내 생각 overcomplicated이다 :
_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를 삭제했습니다. 푸시와 팝프? –