这是汇编代码。它应该计算,在char中从1转换为0或0到1的转换次数。
void main()
{
unsigned char vet[] = { 0x06 }; //Array di byte (da considerare come
//una sequenza di bit)
unsigned short int len = 4; //Lunghezza (numero di bit)
// Output
unsigned int transizioni01; //Numero di transizioni 0->1
unsigned int transizioni10;
__asm{XOR EAX, EAX
XOR EBX, EBX
MOV transizioni10, 0
MOV transizioni01, 0
TORNO:
CMP BX, len
JA FINE
MOV AL, vet[EBX]
TEST AL, 1
JNZ UNO
INC BX
MOV AL, vet[EBX]
TEST AL, 1
JZ ZEROUNO
UNO: INC BX
CMP BX, len
JA FINE
MOV AL, vet[EBX]
TEST AL, 1
JNZ TORNO
UNOZERO:INC transizioni10
JMP TORNO
ZEROUNO:INC transizioni01
JMP TORNO
FINE:}
它无法正常工作。任何人都建议我改变吗?
答案 0 :(得分:0)
我没有尝试理解您的代码,但以下替代方案可行:
//Assume EAX = pointer to input array of integer
//Assume EDX = length of array in bytes
//Length must be a multiple of 4.
push edi //Save non-volatile registers
push ebx //I.e. everything but eax,ecx,edx
xor edi,edi //change count = 0
lea eax,[eax+edx] //array = end of array
neg edx //length = - length
//we turn the counter around, so the loop is more efficient.
jz @Done //if length = 0 -> done
@OuterLoop:
mov ebx,[eax+edx] //x = array[end - length] => x = array[begin]
@InnerLoop
bsf ecx,ebx //count leading zero's, cl = LSB zero-count
jz @RemainderIsZero
inc edi //If reg is non-zero then at least 1 change.
shr ebx,cl //shift out the bits we've counted
not ebx //Invert the data, force LSB to be zero
jmp @InnerLoop //repeat until data = 0 (until no more changes)
@RemainderIsZero:
add edx,4 //see if more data needs to be processed
jnz @OuterLoop //remember edx is negative
@Done:
mov eax,edi //return the count in eax
pop ebx //restore the non-volatile registers.
pop edi
//ret //You can only do RET if the compiler does NOT
//use stack frames.
答案 1 :(得分:0)
假设数组从低位到高位连接,即两个字节0x0F, 0xF0
将被视为位流0000 1111 1111 0000
,从而导致一个(0-> 1)更改,和(1-> 0)改变。第一个/最后一个位总是"没有变化" (对着它旁边的空隙),所以0xFF, 0xFF
将产生0/0转换,0x00, 0x00
也将产生0/0转换。
代码的想法是使用(X xor (X>>1))
提取位的位掩码,其中发生转换(" edge"),然后计算这些以计算" all&# 34;转换,当and
- 用原始X
值时,只有" 0-> 1"的位掩码。收到过渡,并再次计算。然后在结束时计算" 1-> 0"转换只需要减去" 0-> 1"来自"所有"计数。
; TODO preserve registers which need to be preserved by your ABI
; ax, ebx, ecx, dx, esi, edi will be modified
lea esi,[vet] ; address of byte array
mov ecx,[len] ; number of bytes in array
mov ah,[esi] ; take most significant bit as entry low bit
shr ah,7 ; ah.LSB = [first_byte].MSB (no transition on first bit)
xor ebx,ebx ; counter of ALL transitions
xor edi,edi ; counter of 0->1 transitions
; ## calculate bitmaks of all transitions (marked bit is the second one)
detect_transitions_loop:
mov al,[esi] ; ax = current source byte + low bit of previous in ah
shr ax,1 ; al = 8 bits of array shifted by 1 to right
mov ah,[esi] ; ah = current source byte
inc esi ; ++source byte address
xor al,ah ; al = bitmask of transitions detected
jz no_transition_detected_in_byte
mov dh,al ; dh = copy of all transitions
; ## count all transitions
count_all_transitions:
inc ebx ; increment number of all transitions
; clear least significant set bit of al (removes one transition)
mov dl,al
dec al
and al,dl
jnz count_all_transitions ; until all bits are counted
; ## count 0-1 transitions
and dh,ah ; dh = bits of 0->1 transitions detected
jz no_transition_detected_in_byte
count_01_transitions:
inc edi ; increment number of 0->1 transitions
; clear least significant set bit of dh (removes one transition)
mov dl,dh
dec dh
and dh,dl
jnz count_01_transitions ; until all bits are counted
no_transition_detected_in_byte:
dec ecx
jnz detect_transitions_loop
; ## calculate 1->0 transitions count, and store results
sub ebx,edi
mov [transizioni01],edi
mov [transizioni10],ebx
; TODO restore any registers which had to be preserved
; TODO return
代码可以扩展为一次处理32位(如果填充输入数组包含4个输入字节的乘法),并且(在可用的CPU上)指令popcnt
可用于计算数量检测到的转换位。
mov eax,[esi]
将符合这一点。所以它并不像我想的那么简单。