Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/dart/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly 汇编语言与斐波那契数_Assembly_Masm_Masm32 - Fatal编程技术网

Assembly 汇编语言与斐波那契数

Assembly 汇编语言与斐波那契数,assembly,masm,masm32,Assembly,Masm,Masm32,为了简单起见,我收到了我的第一个MASM32项目,内容如下:“编写一个汇编程序来生成和显示前24个斐波那契数,从1开始,到46368结束。”由于这是我的第一个项目,我真的不知道如何开始或写出这段代码。任何帮助都将不胜感激。非常感谢。fibuncai通常倾向于递归求解,而使用简单循环求解同样简单 您已经知道您的数组将有24个字大, 第一次看,看起来你的循环是24步 虽然已经设置了f(1)和f(2),并且您至少需要使用这两个元素,但所需的元素数量是22,而不是24。。。让我们从我们已经知道的开始 f

为了简单起见,我收到了我的第一个MASM32项目,内容如下:“编写一个汇编程序来生成和显示前24个斐波那契数,从1开始,到46368结束。”由于这是我的第一个项目,我真的不知道如何开始或写出这段代码。任何帮助都将不胜感激。非常感谢。

fibuncai通常倾向于递归求解,而使用简单循环求解同样简单

您已经知道您的数组将有24个字大,
第一次看,看起来你的循环是24步

虽然已经设置了f(1)和f(2),并且您至少需要使用这两个元素,但所需的元素数量是22,而不是24。。。让我们从我们已经知道的开始

fib  dw 24 dup (0)    ; i don't know masm too well, this should create 24 words
    mov word ptr[fib  ],1   ; f(1)
    mov word ptr[fib+2],1   ; f(2)

    mov cx,22           ; this will be the loop counter
l1:
    ; add up the last 2 elements
    dec cx
    jnz l1
好的,到目前为止还不错。“累加最后2个元素”要求存储最后两个元素的2个寄存器不必总是从内存中读取它们。让我们使用AX和BX,AX表示元素n-2,BX表示元素n-1。我们将它们相加,并将结果存储在“next”数组元素中
对于数组,最好使用si和di,在编写时,di(目的地索引)是最好的选择

fib  dw 24 dup (0)    ; i don't know masm too well, this should create 24 words

calculate:
    cld
    mov word ptr[fib  ],1   ; f(1)
    mov ax, 1   
    mov word ptr[fib+2],1   ; f(2)
    mov bx, 1
    mov di, offset fib+4    ; does this work in MASM ?

    mov cx,22           ; this will be the loop counter
l1:
    add ax,bx
    stosw           ; write new element to array   
                    ; note: this is equivalent to mov [di], AX and add si,2

    dec cx
    jnz l1
加起来之后,我们需要用正确的值加载ax和bx,用f(n)加载ax,用f(n-1)加载bx。。。我们可以通过从数组中读取来实现这一点,但如果我们仔细观察,AX是这个循环的f(n)(刚刚计算的最后一个元素),对于下一个循环是f(n-1),而BX是f(n-1),对于下一个循环是f(n-2)。所以我们所要做的就是交换它们

fib  dw 24 dup (0)    ; i don't know masm too well, this should create 24 words

calculate:
    cld
    mov word ptr[fib  ],1   ; f(1)
    mov ax, 1   
    mov word ptr[fib+2],1   ; f(2)
    mov bx, 1
    mov di, offset fib+4    ; does this work in MASM ?

    mov cx,22           ; this will be the loop counter
l1:
    add ax,bx
    stosw           ; write new element to array   
                    ; note: this is equivalent to mov [di], AX and add si,2
    xchg ax,bx      

    dec cx
    jnz l1
et voilá:您已经计算了24个元素


PS:我不确定MASM是否会编译这个,我正在使用另一个汇编器,给我一个提示,我会更正它

到目前为止您尝试了什么?您可以从编写一个显示数字的程序开始。您可以非常简单地创建包含前24个数字的数据并打印出来。;)首先尝试用另一种语言(如C)编写程序,然后看看是否可以用汇编语言再次编写。@DavidHoelzer:在这种情况下,赋值语句表示数字必须由汇编程序生成。push/pop?怎么回事
xchgax,bx做同样的事情。对于循环结束条件,您可以
cmp edi、24*2+偏移fib
或其他方法,而不是在计数器上浪费ecx。当然,您根本不需要存储结果:从循环内部调用
printf
是最简单的方法(在保留调用的寄存器中保持循环状态)。为什么要使用16位指针?OP似乎特别要求32位。此外,斐波那契经常递归实现,但这只是因为人们在教授递归时选择它作为递归函数的示例。递归实现要困难得多,速度也慢得多。(O(Fib(n))而不是O(n),用于一个简单的递归实现而无需记忆。)通过两种方式展开,甚至更少地移动数据:
addebx,edi
/print ebx/
add edi,ebx
/print edi可以实现这一点。无论如何,在我看来,人们应该使用递归有意义的函数来教授递归,循环需要类似堆栈的数据结构。树遍历是一个很好的例子。我可以使用“指针”比较,但不需要CX,而且我喜欢使用寄存器作为计数器,所以我为什么要这样做。这样更易于阅读(至少对我的眼睛来说,但这是我个人的喜好)。但你对交换的看法完全正确,我总是忘记指令(太多的指令集无助于记住哪个指令集包含哪个指令),我改变了它,我不喜欢引入不用于任何用途的计数器
cmp/jcc
甚至可以在SnB之前的AMD和Intel上进行融合,但
dec/jcc
只能在Intel SnB系列上进行融合。与结束指针相比,它仍然绑定了一个寄存器来保存结束指针,因此您是对的,它的优势往往很小。(在实际代码中,端点可以是立即数的情况很少见,因为指针增量通常比索引寻址模式更有效,尤其是在Intel SnB系列上)。然而,对于索引可以向后遍历数组的循环来说,减少索引是非常好的。顺便说一句,
xchg
在Intel上是3个uops。如果希望避免展开循环以消除额外移动,可以使用
lea-esi、[edi,ebx]
/
mov-edi,ebx
/
mov-ebx,esi
或其他方法。