Assembly 斐波那契x86-16汇编

Assembly 斐波那契x86-16汇编,assembly,x86-16,Assembly,X86 16,我正试图在调试x86-16 dosbox assembler中执行fibonnachi序列,但遇到了麻烦,我一直得到这个奇怪的打印输出: 我试着把它一块一块地分解,但这是我到目前为止所做的 mov cx, 15 mov al, 01 mov bl, 00 cmp cl, 1 je 010B ;next line with mov ah, 2 mov ah, 2 int 21 inc cl cmp cl,2 je 0115 ;next line with mov ah, 2 m

我正试图在调试x86-16 dosbox assembler中执行fibonnachi序列,但遇到了麻烦,我一直得到这个奇怪的打印输出:

我试着把它一块一块地分解,但这是我到目前为止所做的

mov cx, 15
mov al, 01
mov bl, 00
cmp cl, 1
je  010B     ;next line with mov ah, 2
mov ah, 2
int 21
inc cl
cmp cl,2
je  0115     ;next line with mov ah, 2
mov ah, 2
int 21
inc cl
add al, bl
mov bl, al
mov cl, bl
mov ah,2
int 21
loop (inc cl line)
rcx 
4A
w
q
我不确定它是否正确,但它应该打印出斐波那契序列中的前20个数字,如果可以,请帮助

编辑: 我用它来打印01

mov cx, 15
dec cx
mov al, 30
mov bl, 31
mov cl, 31
cmp cl, 31
je 010F
mov dl, al
mov ah, 2
int 21
dec cx
inc cl
cmp cl, 32
je 011c
mov dl, bl
mov ah, 2
dec cx
inc cl
int 21
int 20
现在我只需要有ax=bl+al,al=bl,和bl=ax,知道怎么做吗?

应该输出一个字节到标准输出,其中该字节要在DL寄存器中传递。您的代码甚至从未初始化DL,因此它输出垃圾也就不足为奇了

你还有其他几个问题。如果您想要可读的输出,您必须进行二进制到十进制的转换,然后转换为ASCII;您的代码似乎根本没有尝试这样做。此外,您正在8位AL、BL寄存器中执行所有算术运算,但第20个斐波那契数大于8位,因此在某个点上它将溢出,您将无法得到正确的答案

最后,如果您想用汇编语言编写一个真正的程序,那么调试是一种非常不方便的方式。它已经有40年没有进化了。获取一个真正的文本编辑器和一个真正的汇编程序,以及一个真正的调试器。

应该将一个字节输出到标准输出,其中该字节将在DL寄存器中传递。您的代码甚至从未初始化DL,因此它输出垃圾也就不足为奇了

你还有其他几个问题。如果您想要可读的输出,您必须进行二进制到十进制的转换,然后转换为ASCII;您的代码似乎根本没有尝试这样做。此外,您正在8位AL、BL寄存器中执行所有算术运算,但第20个斐波那契数大于8位,因此在某个点上它将溢出,您将无法得到正确的答案

最后,如果您想用汇编语言编写一个真正的程序,那么调试是一种非常不方便的方式。它已经有40年没有进化了。获得一个真正的文本编辑器和一个真正的汇编程序,以及一个真正的调试器

现在我只需要有ax=bl+al,al=bl,和bl=ax,你知道怎么做吗

对于al=bl和bl=al,您可以使用交换指令:

        xchg    al,bl
除了您需要使用16位寄存器才能升到fib24 46368,因此:

        add     ax,bx
        xchg    ax,bx
或者,您可以先执行xchg

        xchg    ax,bx
        add     ax,bx
您需要使用除ax之外的寄存器,因为将二进制转换为十进制和int 21调用都需要它

如果您还没有这样做,您可以将debug.com作为一个粗略的汇编程序,通过重定向其输入,从文本文件读取其命令。命令将输入指令和数据,然后使用n给出要写入的程序的名称,使用rcx将cx设置为要写入的字节数,然后使用w命令写入程序。q退出调试

这允许您编辑文本文件,直到程序开始工作,而不是直接使用debug输入命令。下面是名为fib16.in的Fibonacci程序的示例输入文件:

a100
sub  sp,+10
mov  bp,sp
mov  byte ptr [bp+05],0d
mov  byte ptr [bp+06],0a
mov  byte ptr [bp+07],24
mov  di,ffff
mov  si,0001
mov  cx,0019
mov  bx,000a
xchg si,di
add  si,di
mov  bp,sp
add  bp,+05
mov  ax,si
dec  bp
xor  dx,dx
div  bx
or   dl,30
mov  [bp+00],dl
cmp  bp,sp
jnz  0128
mov  ah,09
mov  dx,sp
int  21
loop 011d
add  sp,+10
mov  ax,4c00
int  21

nfib16.com
rcx
47
w
q
要组装此文件,请输入以下命令:

debug <fib16.in
现在我只需要有ax=bl+al,al=bl,和bl=ax,你知道怎么做吗

对于al=bl和bl=al,您可以使用交换指令:

        xchg    al,bl
除了您需要使用16位寄存器才能升到fib24 46368,因此:

        add     ax,bx
        xchg    ax,bx
或者,您可以先执行xchg

        xchg    ax,bx
        add     ax,bx
您需要使用除ax之外的寄存器,因为将二进制转换为十进制和int 21调用都需要它

如果您还没有这样做,您可以将debug.com作为一个粗略的汇编程序,通过重定向其输入,从文本文件读取其命令。命令将输入指令和数据,然后使用n给出要写入的程序的名称,使用rcx将cx设置为要写入的字节数,然后使用w命令写入程序。q退出调试

这允许您编辑文本文件,直到程序开始工作,而不是直接使用debug输入命令。下面是名为fib16.in的Fibonacci程序的示例输入文件:

a100
sub  sp,+10
mov  bp,sp
mov  byte ptr [bp+05],0d
mov  byte ptr [bp+06],0a
mov  byte ptr [bp+07],24
mov  di,ffff
mov  si,0001
mov  cx,0019
mov  bx,000a
xchg si,di
add  si,di
mov  bp,sp
add  bp,+05
mov  ax,si
dec  bp
xor  dx,dx
div  bx
or   dl,30
mov  [bp+00],dl
cmp  bp,sp
jnz  0128
mov  ah,09
mov  dx,sp
int  21
loop 011d
add  sp,+10
mov  ax,4c00
int  21

nfib16.com
rcx
47
w
q
要组装此文件,请输入以下命令:

debug <fib16.in

这是我打出来的,mov-dl,1 mov-ah,2 int 21打印出一张笑脸,我不太懂这种语言我用的是ASCII,15=21,01=1,所以我使用ASCII,dosbox不允许我使用eax或任何其他更大的registers@PeterCordes:这不是你要做的
特别是SBOX,汇编程序是模拟器中运行的任何DOS版本的调试命令中的一个,AFAIK从来都不支持32位指令。我希望我可以使用其他的东西,但这是我的教授告诉我的家庭作业use@rcgldr:添加eax,16位模式下的edx可使用66操作数大小前缀进行编码。所以这并不是天生的障碍,正如内特所说,这只是软件的局限性。无论如何,OP的问题是在应该使用16位寄存器时使用8位寄存器。Fib20不需要32位,如果需要的话,可以使用adc来扩展精度。相关::105字节的x86-32机器代码,用于一个完整的Linux程序打印Fib10^9的前1000位十进制数字,运行时间约为1分钟,1 mov啊,,2 int 21打印出一张笑脸,我不太懂这种语言我用的是ASCII,15=21,01=1,所以我使用ASCII,dosbox不允许我使用eax或任何其他更大的registers@PeterCordes:具体来说,不是DOSBOX,而是emulator中运行的任何DOS版本的调试命令中的汇编程序,AFAIK从未支持32位指令。我希望我可以使用其他的东西,但这是我的教授对我说的家庭作业use@rcgldr:添加eax,16位模式下的edx可使用66操作数大小前缀进行编码。所以这并不是天生的障碍,正如内特所说,这只是软件的局限性。无论如何,OP的问题是在应该使用16位寄存器时使用8位寄存器。Fib20不需要32位,如果需要的话,可以使用adc来扩展精度。相关::105字节的x86-32机器代码,用于打印Fib10^9的前1000位十进制数字的完整Linux程序,运行时间约为1分钟。OP的代码似乎有数字分支目标。在调试中没有使用标签的方法吗?若并没有,那个么这是一种教汇编的可怕方式,因为每次添加或删除指令时都必须去修复分支偏移!我想OP已经在使用一个文件的输入了。你的答案解释了OP第一次代码转储中循环指令后明显的尾部垃圾。如果这个问题引起了你的兴趣,那就发一些有趣的代码吧。我认为行动已经开始了,除非他们做出回应,否则我不会费心去帮助他们。OP的代码有太多的bug,你甚至无法回答任何问题。inc-cl后面跟着mov-cl、bl,然后是loop看起来像是胡说八道,至少有两个单独的bug对cx-for-loop和inc-cl结果进行了重击,而没有使用它…@PeterCordes-我更新了我的答案。斐波那契步骤只是两条指令xchg,add。代码的其余部分将转换为十进制字符串并显示它。我使用堆栈作为十进制字符串。使用所有寄存器,除了字符串之外,不需要任何基于内存的变量。至少旧的16位Microsoft工具集仍然有效。很好。我可能使用了比main0和main1更有意义的标签名,并且可能在块之间留下了一条空行。另外,可能mov cx,25比mov cx,0019h更容易读取,因为我们认为计数是十进制数。另外,在您分sp之前,按0240dH’等等,16’是将字符串数据放入堆栈的更有效的方法。如果您需要另一个reg,您可以欺骗和cmp si、Fib24或其他内容作为循环条件,而不是cx中的计数器。或者检测进位,因为Fib25是第一个不适合16位的。OP的代码似乎有数字分支目的地。在调试中没有使用标签的方法吗?若并没有,那个么这是一种教汇编的可怕方式,因为每次添加或删除指令时都必须去修复分支偏移!我想OP已经在使用一个文件的输入了。你的答案解释了OP第一次代码转储中循环指令后明显的尾部垃圾。如果这个问题引起了你的兴趣,那就发一些有趣的代码吧。我认为行动已经开始了,除非他们做出回应,否则我不会费心去帮助他们。OP的代码有太多的bug,你甚至无法回答任何问题。inc-cl后面跟着mov-cl、bl,然后是loop看起来像是胡说八道,至少有两个单独的bug对cx-for-loop和inc-cl结果进行了重击,而没有使用它…@PeterCordes-我更新了我的答案。斐波那契步骤只是两条指令xchg,add。代码的其余部分
是转换为十进制字符串并显示它。我使用堆栈作为十进制字符串。使用所有寄存器,除了字符串之外,不需要任何基于内存的变量。至少旧的16位Microsoft工具集仍然有效。很好。我可能使用了比main0和main1更有意义的标签名,并且可能在块之间留下了一条空行。另外,可能mov cx,25比mov cx,0019h更容易读取,因为我们认为计数是十进制数。另外,在您分sp之前,按0240dH’等等,16’是将字符串数据放入堆栈的更有效的方法。如果您需要另一个reg,您可以欺骗和cmp si、Fib24或其他内容作为循环条件,而不是cx中的计数器。或者检测进位,因为Fib25是第一个不适合16位的。此分配是否要求将结果输出到控制台窗口?如果是这样,那么您需要创建一个函数来将二进制数转换为字符串以显示字符串。我不知道x86-16汇编如何比斐波那契x86-16汇编更好。它们都没有描述您遇到的实际问题,只是描述了您遇到的环境,但是如果有任何问题,您应该使标题更具体,而不是更少。此赋值是否需要将结果输出到控制台窗口?如果是这样,那么您需要创建一个函数来将二进制数转换为字符串以显示字符串。我不知道x86-16汇编如何比斐波那契x86-16汇编更好。它们都没有描述你遇到的实际问题,只是描述了你遇到的环境,但是如果有什么问题的话,你应该让标题更具体,而不是更少。