有时通过向右旋转数字我们获得相同的数字。
例如。 01010101(85)可以旋转2,4,6个位置以得到相同的数字。我们可以用不同的位旋转数字以获得相同的数字的次数是多少? 为此,我写了以下代码:
extern printf ; the C function to be called
SECTION .data ; Data section
msg: db "The number of possible rotations are : %d",10,0
inta1: dd 1234567 ; integer 1234567
num: dd 1431655765
SECTION .text ; Code section.
global main ; "C" main program
main:
mov eax, [num]
mov ecx,32
mov ebx,0
mov edx,eax
.loop:
dec ecx
cmp ecx,1
jl .exit
ror eax,1
cmp edx,eax
jne .loop
inc ebx
jmp .loop
.exit:
push ebx
push dword msg
call printf
add esp, 8
以上代码的输出:
可能的旋转次数为:15
当编号:858993459
输出:
可能的旋转次数为:7
。
虽然我得到32位数的正确答案,但我无法在同一代码中使用非32位代替num来获得正确的答案。
例如,当我使用num:85,
我得到了输出:
可能的旋转次数为:0
但它应该是3
也许是因为在第一个剩余位中用零填充。(不确定,只是假设)
如何使用同一组寄存器来显示非32位数的可能旋转值?
答案 0 :(得分:1)
听起来你的功能/程序需要两个输入:数字和旋转宽度。
您可以使用rol
指令进行8,16,32和64位旋转。对于每个操作数大小,您需要不同的循环副本。
如果要支持任意旋转宽度,则必须使用移位和遮罩来模拟它们。 (类似于the pattern of shifts that C compilers recognize as a rotate。)
rcl
会进行9,17,33或65位旋转,但部分数字位于CF
,您无法轻松比较它。我不认为旋转携带会对此有所帮助。
如果要根据数字推断旋转宽度,可以使用bsr
找到最高设置位。您可以选择将其舍入为8,16,32或64。
确保使用input = 0
测试您的程序,因为{0}输入的bsr
寄存器结果未定义。 (其标志结果有ZF设置)。
首先,你的功能并没有返回,所以你只是崩溃,或者幸运地进入一个确实返回的功能。在末尾添加ret
指令。
此外,dec
已经设置了标志。你不需要cmp
。实际上你根本不需要检查,因为你可以保证在旋转回初始值后找到匹配。有可能显着地简化你的循环。它现在应该在Intel CPU上每个周期运行一次。
我还将格式字符串等放在只读数据中,而不是私有可修改数据。
extern printf
SECTION .rodata ; Read-only data section
msg: db "The number of possible rotations are : %d",10,0
num: dd 1431655765
section .text
global main
main:
;mov ebx,0 ; should be xor ebx,ebx. And you need to save/restore ebx if you're going to modify it.
mov eax, [num]
mov edx,eax
xor ecx,ecx
.rotcount:
ror eax, 1
inc ecx
cmp edx, eax
jne .rotcount
;; ecx = number of 32bit rotates to produce a match. Range: 1 to 32
push ecx
push dword msg
call printf
add esp, 8
xor eax,eax # return 0, instead of unpredictable behaviour from fall-through
ret