GCD рекурсивный язык ассемблера X86 MASM

#assembly #recursion #masm #greatest-common-divisor #irvine32

#сборка #рекурсия #masm #наибольший общий делитель #irvine32

Вопрос:

Спасибо всем за помощь, я внес некоторые действительно хорошие изменения, но теперь он дает мне ответ 4198498 вместо 5 для первого набора значений, который, как я знаю, неверен. Я что-то не так нажал или неправильно ввел reg? Я правильно очистил стек, используя ret 8, который должен очистить стек для следующего вызова, верно?

Вот что у меня есть до сих пор:

 TITLE MASM GCD                      (GCD.asm)


; Description:GCD recursive
; 
; Revision date:

INCLUDE Irvine32.inc
.data
myMessage BYTE "Assignment 7 GCD Recursive style",0dh,0ah,0
myMess2   BYTE "GCD = " ,0dh,0ah,0


;first set of nums
val1 DWORD  5
val2 DWORD  20

;second set of nums
val3 DWORD  24
val4 DWORD  18

;3rd set
val5 DWORD  11
val6 DWORD  7

;4th set
val7 DWORD  432
val8 DWORD  226

;5th set
val9 DWORD  26
val10 DWORD  13

.code
main PROC
    call Clrscr  

    mov  edx,offset myMessage
    call WriteString        ;write message
    call Crlf               ;new line
    push val1
    push val2
    call GCD

    exit
main ENDP

;------------------------------------------------
GCD PROC,
; This finds GCD
; Gets values from stored values
;returns NA

;------------------------------------------------

        xor edx,edx
        mov eax,dword ptr[esp 8] ;dividend
        mov ebx,dword ptr[esp 4] ;divisor
        div ebx              ;eax/ebx
        cmp  edx,0           ;remainder in edx
        je   L1              ;yes: quit
        call GCD             ;no: call GCD agian
    L1:
        mov eax,ebx          ;move the divisor into eax for printing i.e GCD    
        mov  edx,offset myMess2
        call WriteString
        call WriteInt        ;Display GCD WriteInt uses EAX = qutent
        call crlf
        ret 8                ;clean up the stack
GCD ENDP

END main
  

Ответ №1:

Сначала я вижу несколько ошибок и вредных привычек:

 GCD PROC,
    dividend:DWORD,
    divisor:DWORD
  

Объявление локальных переменных для ваших процедур, на мой взгляд, является плохой привычкой. (результат из языков высокого уровня)

Вам нужно поместить это в свой сегмент данных. Кроме того, есть синтаксическая ошибка, dw-слова неинициализированы, поэтому вы должны объявить их следующим образом:

 .DATA ?
dividend  dword ?
divisor dword ?
  

У вас также есть проблема с регистрами для инструкции div:

 xor edx,edx
mov eax,xxx ;dividend
mov ebx,yyy ;divisor
div ebx     ;eax/ebx
cmp  edx,0  ;remainder in edx
  

Теперь, чтобы использовать ваши наборы значений и разделить их, у вас есть разные варианты:

1-переместите их вручную 1 на 1 в ваших регистрах

 mov eax,dword ptr[val01] ;dividend
mov ebx,dword ptr[val02] ;divisor
  

2- вы помещаете их непосредственно в стек (например, параметры функции)

 push val01
push val02
call GDC

;in GDC proc
mov eax,dword ptr[esp 8]
mov ebx,dword ptr[esp 4]
  

3-поместите их в «массив» и перебирайте их

 exercise for you
  

Ответ №2:

Несколько вещей, которые я вижу (игнорируя правильность вычисления):

     mov edx,dividend            ;this is value 1    
    mov ebx,divisor         ;this is the divider make sure its smaller number!    
    div ebx                  ;divide int1 by int2
  

DIV ebx делится EDX:EAX на EBX , поэтому вы должны переместить дивиденд в EAX и очистить EDX .

     cmp  edx,0               ;does remainder = 0 ?
    je   L1                  ;yes: quit

    call GCD             ;no: call GCD agian
  

Где вы настраиваете параметры для этого вызова?

   L1:
    mov eax,ebx          ;EAX = GCD
  

Здесь вы перезаписываете частное делителем, это намеренно?

     pop edx
    pop ebx
  

Я не вижу, куда вы нажимаете эти регистры. Это делается автоматически MASM? Если нет, вам нужно их нажать.