我首先用C ++创建了一个类似的程序,然后我决定尝试用x86汇编语言编写它(我在大学里教授的程序集类型)。我已经完成了C ++版本,我的程序集版本已基本完成。
我对两个版本进行了一些桌面检查,首先使用(2400,3750)。我在两个版本中得到了相同的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
答案 0 :(得分:3)
问题出在calc_lcm
程序:
mov BX, [gcd] div BX mov SI, AX mov [lcm], SI
当num1
为19200且num2
为8200时,gcd
变为200.此处您尝试通过除以num1
的乘积来计算lcm(19200,8200)和num2
(19200 * 8200 = 157440000)gcd
(200):
157440000 / 200 = 787200
编辑:修正了拼写错误。
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