Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/qt/7.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 GCD/LCM x86英特尔NASM汇编程序中的LCM计算错误 我首先在C++中创建了一个类似的程序,然后我决定尝试用x86汇编语言(我在大学里教的汇编程序)编写它。我已经完成了C++版本,我的汇编版本几乎完成了。_Assembly_Macros_X86_Nasm_Cpu Registers - Fatal编程技术网

Assembly GCD/LCM x86英特尔NASM汇编程序中的LCM计算错误 我首先在C++中创建了一个类似的程序,然后我决定尝试用x86汇编语言(我在大学里教的汇编程序)编写它。我已经完成了C++版本,我的汇编版本几乎完成了。

Assembly GCD/LCM x86英特尔NASM汇编程序中的LCM计算错误 我首先在C++中创建了一个类似的程序,然后我决定尝试用x86汇编语言(我在大学里教的汇编程序)编写它。我已经完成了C++版本,我的汇编版本几乎完成了。,assembly,macros,x86,nasm,cpu-registers,Assembly,Macros,X86,Nasm,Cpu Registers,我对这两个版本都做了一些桌面检查,首先使用了(24003750)。我在两个版本中都得到了相同的LCM结果,这很好。但是,当我使用更大的数字(19000, 8200)时,我的汇编程序崩溃了,而我的C++版本显示了正确的结果。我怀疑这与我的汇编变量大小和/或在计算LCM时用于除法的寄存器有关 我通过输出被除数(第一个数乘以第二个数)和除数(GCD结果)来测试我的LCM计算(减去除法运算)。我得到了正确的测试结果,所以我认为我的寄存器使用有问题。在此之前,我已经测试了我的GCD计算,所以这不应该是问题

我对这两个版本都做了一些桌面检查,首先使用了(24003750)。我在两个版本中都得到了相同的LCM结果,这很好。但是,当我使用更大的数字(19000, 8200)时,我的汇编程序崩溃了,而我的C++版本显示了正确的结果。我怀疑这与我的汇编变量大小和/或在计算LCM时用于除法的寄存器有关

我通过输出被除数(第一个数乘以第二个数)和除数(GCD结果)来测试我的LCM计算(减去除法运算)。我得到了正确的测试结果,所以我认为我的寄存器使用有问题。在此之前,我已经测试了我的GCD计算,所以这不应该是问题的一部分

%include "macros.s"

.DATA

num_lbl:   DB   "> Numbers (2): ", 0
gcd_lbl:   DB   "*** GCD: ", 0
lcm_lbl:   DB   "*** LCM: ", 0

num1:   DD   0
num2:   DD   0

num1_cpy:   DD   0
num2_cpy:   DD   0

gcd:   DD   0
lcm:   DD   0

.CODE
.STARTUP

xor       EAX, EAX
xor       EBX, EBX
xor       ECX, ECX
xor       EDX, EDX
xor       EDI, EDI
xor       ESI, ESI

main:
     nwln
     nwln
     PutStr   num_lbl
     nwln
     nwln
     GetLInt   [num1]
     GetLInt   [num2]

     mov   EAX, [num1]
     mov   [num1_cpy], EAX
     mov   EBX, [num2]
     mov   [num2_cpy], EBX

     call   calc_euclidean
     call   calc_lcm

     nwln
     PutStr   gcd_lbl
     PutLInt   [gcd]
     nwln
     PutStr   lcm_lbl
     PutLInt   [lcm]
     nwln

     .EXIT

calc_euclidean:
               mov   EAX, [num2]
               cmp   EAX, 0
               jne   chk_swap

               mov   EAX, [num1]
               mov   [gcd], EAX

               ret

calc_lcm:
         mov   EAX, [num1_cpy]
         mov   EDX, [num2_cpy]
         mul   EDX

         mov   EDI, EAX

         xor   EBX, EBX

         mov   EDX, EDI
         shr   EDX, 16
         mov   EAX, EDI
         mov   BX, [gcd]
         div   BX

         mov   SI, AX
         mov   [lcm], SI

         ret         

chk_swap:
         mov   EAX, [num1]
         mov   EBX, [num2]
         cmp   EAX, EBX
         jl    swap

after_check:
            jmp   loop

swap:
     mov   EAX, [num1]
     mov   EBX, [num2]

     ; temp
     mov   ECX, [num2]

     ; num2 = num1
     ; num1 = temp
     mov   EBX, EAX
     mov   EAX, ECX

     mov   [num1], EAX
     mov   [num2], EBX

     jmp   after_check

loop:
     mov   EDX, [num1]
     shr   EDX, 16
     mov   EAX, [num1]
     mov   BX, [num2]
     div   BX

     mov   EDI, [num1]
     mov   ESI, [num2]
     mov   EDI, ESI
     mov   [num1], EDI
     mov   [num2], EDX

     jmp   calc_euclidean

问题出在
计算lcm
程序中:

mov BX, [gcd] div BX mov SI, AX mov [lcm], SI 编辑:修复了打字错误

787200不适合16位。您需要将代码转换为使用32位
div
而不是16位
div
来处理比现在更大的数字

因此,这将是:

编辑:添加了代码

xor    ebx,ebx   ; this you have already.
mov    bx,[gcd]
xor    edx,edx   ; zero edx, as edx:eax gets divided by ebx...
div    ebx       ; ...now.

mov    [lcm],eax ; store the lcm into memory

你有没有用调试器单步执行代码?是的,我有。问题在于LCM计算,我确实得到了所有测试用例的正确的除数和除数。在使用较大的数字时,除法似乎有问题。我仍然认为变量初始化和寄存器使用有问题。我将其回滚到上一次编辑,因为根据收到的答案修复问题的错误是没有意义的。如果基本内容(问题中的bug)被修复,这个问题对未来的读者来说就变得毫无意义了。哦,是的,你说得对。我没有想到这一点。再次感谢!我用32位寄存器尝试了div,但程序仍然崩溃。要么我也必须在其他地方进行更改,要么我不能在32位模式下使用这些数字(因此我不能使用64位寄存器)。好的,明白了。即使使用32位除法,我仍在经历崩溃。问题出在其他地方了,还是我无法将一个32位数字除以另一个32位数字?您需要将
edx
归零,因为
edx:eax
被32位除法中的除数除以,就像
div ebx
一样。它现在可以工作了。谢谢你能告诉我这是怎么回事吗?我被教导(32位除法)将高位放入EDX,低位放入EAX,然后用不同的16位寄存器进行除法;ax/bl<代码>分区bx;dx:ax/bx<代码>div ebx;edx:eax/ebx<代码>div rbx;rdx:rax/rbx。我认为div reg16是16位除法或32/16除法,而不是32位除法,因为除数、商和余数都是16位值。在
div reg16
中,只有被除数可以是32位值。
xor    ebx,ebx   ; this you have already.
mov    bx,[gcd]
xor    edx,edx   ; zero edx, as edx:eax gets divided by ebx...
div    ebx       ; ...now.

mov    [lcm],eax ; store the lcm into memory