最初に C++ で同様のプログラムを作成し、次に x86 アセンブリ言語 (大学で教えられたアセンブリの種類) で記述してみることにしました。C++ バージョンは既に完成しており、アセンブリ バージョンもほぼ完成しています。
最初に(2400、3750)を使用して、両方のバージョンでデスクチェックを行いました。両方のバージョンで同じ LCM 結果が得られました。これは良いことです。ただし、より大きな数値 (19000、8200) を使用すると、アセンブリ プログラムがクラッシュし、C++ バージョンでは正しい結果が表示されました。アセンブリ変数のサイズや、LCM を計算するときの除算用のレジスタの使用に関係していると思われます。
被除数 (最初の数値に 2 番目の数値を掛けたもの) と除数 (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