汇编语言制作一个运行n / 10次的for循环

时间:2017-11-07 02:26:12

标签: assembly x86 masm

我是汇编语言编程的初学者,我正在寻找一些帮助来创建一个在n / 10秒内运行的for循环。

我无法理解如何将这个Java for循环转换为循环汇编语言。 N是用户输入的值。 for(i = 1; i< = n; i ++)

我正朝着正确的方向前进吗? 如果我不在哪里,我犯了错误? 我只是想让循环工作,我会担心以后的运行时间。

代码:

.586
.MODEL FLAT

INCLUDE io.h            ; header file for input/output

.STACK 4096

.DATA

number1 DWORD   ?

sum DWORD   ?

prompt1 BYTE    "Enter a number between 1-100", 0

string  BYTE    40 DUP (?)

.CODE

_MainProc PROC

    input   prompt1, string, 40      ; read ASCII characters
    atod    string          ; convert to integer
    mov     ecx, eax    ; store input to memory this is n
    mov     eax, 0  ; //set eax to 0
    mov     edx, 0  //This is sum
    mov ebx, 1      //Create i
    cmp ecx, ebx    //compare i to n
    jnle ecx        //jump when negative or less than ecx
    add edx, ebx    //adds i to sum
    inc ebx         //i++
    jmp ebx         //jump to ebx repeat
_MainProc ENDP

END                             ; end of source code

1 个答案:

答案 0 :(得分:0)

循环一小部分东西的最简单方法是在循环中添加或减去10。

不是进行除法以获得迭代计数,而是在循环内重复进行减法。重复的add / sub通常是一种可靠的乘法/除法方式,但是你想要多次循环,所以你使用那个作为循环计数器。这被称为"强度降低"优化,因为分工是更强大的" (比较慢/更贵)。比减法。

执行此操作的一种方法是在计数器变为负数(符号小于)时,或者当它越过零(无符号进位)时向下计数并跳出循环。

atod会在eax中返回结果,因此您可以使用mov eax, 0对其进行破坏。

    ... code to get input, and call atod
    ; atod return value in eax = n

    xor    edx, edx       ; sum = edx = 0

    ; loop n/10 times  (integer division truncates towards 0)
@loop:                    ; do {
    add    edx, eax         ; sum += i

    sub    eax, 10          ; i -= 10
    jnc    @loop          ; } while(i didn't wrap around);

    mov    eax, edx      ; eax=sum

或者使用jg循环}while(i>0),或使用jge循环}while(i>=0)。添加零是一个无操作,所以我们可以让循环在i=0时运行一次,但如果您不需要支持,jg会很好起始值大于最大的有符号32位整数。 (即如果你不需要签名)。

如果要向上循环,可以使用比较和分支

来实现
    ... code to get input, and call atod
    ; atod return value in eax = n

    xor    edx, edx       ; sum = edx = 0
    mov    ecx, 1         ;   i = ecx = 1

    ; if the loop might need to run 0 times, test eax,eax / jz to the bottom.
    ; or cmp eax, 10 or whatever.
@loop:                    ; do {
    add    edx, ecx         ; sum += i

    add    ecx, 10          ; i += 10
    cmp    ecx, eax
    jb     @loop          ; } while(i < n);

    mov    eax, edx      ; eax=sum

根据需要进行调整以进行签名比较,或jbe进行<=或其他任何操作。

  

用n / 10表示。

O(n)复杂度类不计算常数因子,因此O(n)= O(n / 10)。我假设你的意思是&#34;运行n / 10次&#34;就像你在标题中说的那样,不是n循环中的for次,或者是O(n)次(这将允许任何一个错误或常数乘数)。

如果你想要一个只在循环中递增1的计数器,你可以倒数循环终止条件(朝零)并计算另一个寄存器。你的Java并没有在任何地方显示因子10,所以IDK就在你想要的地方。

尽可能避免使用divit's about 30x slower than add