装配x86右转n次以获得相同的数字

时间:2016-05-11 15:38:18

标签: x86 nasm

有时通过向右旋转数字我们获得相同的数字。

例如。 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位数的可能旋转值?

1 个答案:

答案 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设置)。

RE:您的实际代码:

首先,你的功能并没有返回,所以你只是崩溃,或者幸运地进入一个确实返回的功能。在末尾添加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