我喜欢在32位数中计算1到0的转换数。我发现使用shr从0到1的转换次数是相反的,但我没有得到所需的结果。我该怎么办?
extern printf
SECTION .data
msg: db "The number of transitions are : %d",10,0
inta1: dd 1234567 ; integer 1234567
num: dd 4660
SECTION .text
global main
main:
mov eax, [num]
mov ecx,32
mov ebx,0
.loop: dec ecx
cmp ecx,0
jl .exit
shr eax,1
jc .loop
dec ecx
shr eax, 1
jnc .loop
inc ebx
jmp .loop
.exit:
push ebx
push dword msg
call printf
add esp, 8 输出:
过渡的次数如下:2
而对于4660 (00000000000000000001001000110100),1到0的跃迁数是4。
发布于 2016-05-11 19:25:13
基本的问题是,您的代码寻找一个0,后面跟着一个1,如果不匹配,它将重新开始。因此,如果它看到00,它就会重新寻找另一个0,如果下一个位是1,它就会重新开始。因此,当过渡被偶数的0所取代时,您就会错过它们。
注意,您还说您需要1到0转换,但您正在寻找0到1转换,但您是从右到左(lsb到msb),因此这可能是正确的,这取决于您想要的位顺序。
显而易见的解决方案是将jnc .loop更改为不重新启动,而是只返回到dec ecx前面的那个,尽管您在那里还需要一个cmp ecx,0; jl .exit。
注意,您还可以通过使用由ecx指令设置的Z标志(在eax中的结果为所有0位)来计算位数,从而消除对eax的需求。
加在一起,你会发现:
.loop1: shr eax, 1
jc .loop1
.loop2: jz .exit
shr eax, 1
jnc .loop2
inc ebx
jmp .loop1发布于 2016-05-11 19:27:28
琐事:几个月前,我在尝试实现基于位图的内存管理器的一个方面时考虑过这个问题。
我发现的最有效的解决方案如下(我根据您的示例代码对其进行了调整):
global main
main:
mov eax, [num]
; --- here starts the relevant code ---
mov ebx, eax
shl ebx, 1
not eax
and ebx, eax
popcnt ebx, ebx ; --- count the changed bits ---
; --- continue with your exit routine
.exit:
push ebx
push dword msg
call printf
add esp, 8 注意,计算是在没有循环的情况下完成的。它是纯粹的比特篡改设置位数,最后由POPCNT指令,给出所需的结果。
作为一个应用于给定值4660的例子,该算法的功能如下:
00000000000000000001001000110100 --- MOV EBX, EAX
00000000000000000010010001101000 --- SHL EBX, 1
11111111111111111110110111001011 --- NOT EAX
00000000000000000010010001001000 --- AND EBX, EAX => 'and' the last two lines
=> POPCNT (count the bits of the last line) to get the result of 1 to 0 transitions.https://stackoverflow.com/questions/37170378
复制相似问题