Я должен найти gcd из 3 беззнаковых 16-битных чисел. Он работает, но не дает правильного вывода. Что может быть не так в моем коде? - PullRequest
1 голос
/ 04 апреля 2019

Это программа на языке ассемблера 8086, которая находит gcd из трех 16-разрядных чисел без знака.

Я несколько раз проверил код и чувствую, что это должно быть правильно.

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

Я не могу понять, что делать дальше.

.model small
.stack 100h
.data
        arr DW 4800h,1600h,3200h
        gcd DW ?

.code
        main proc
                mov ax,@data
                mov ds,ax

                mov cx,0
                mov si,offset arr
                mov bx,[si]
                jmp L1

        L1:

                inc si
                inc cx
                mov ax,[si]

                jmp compare

       compare:

                cmp ax,bx
                jg up1
                jb excg
        up1:


                aad
                div bx
                cmp dx,0000h
                je exit
                jmp up2


       excg:
               xchg ax,bx
               jmp up1
       up2:

                mov ax,bx
                mov bx,dx
                mov dx,0
                jmp up1
       exit:
                mov gcd,bx
                cmp cx,2
                jne L1
        je display

      display:         


                mov dx,bx
                mov ah,2
                int 21h

                mov ax,4c00h
                int 21h

                main endp

     end main

1 Ответ

2 голосов
/ 05 апреля 2019

Это программа на языке ассемблера 8086, которая находит gcd из трех беззнаковых 16-битных чисел.

Вы пытаетесь реализовать алгоритм Евклида , но ваш кодоказалось грязным и неисправным.

.Указатель SI должен увеличиваться на 2, поскольку вы работаете со словами.
.Инструкция aad действительно должна быть инструкцией cwd.
.Инструкции jmp compare и je display полностью избыточны (*).
.Одной символьной функции вывода недостаточно для отображения 16-битного числа.Отметьте «Отображение чисел в DOS» , чтобы узнать, как отобразить ваш результат.

Это моя версия вашей программы.Вы узнаете большую часть того, что написали, но в лучшем и правильном порядке ...

  mov   ax, @data
  mov   ds, ax
  mov   cx, 2
  mov   si, offset arr
  lodsw
  mov   bx, ax
next:
  lodsw
  cmp   bx, ax      ;We want to divide the bigger number by the smaller one
  jb    divide
  xchg  bx, ax
  jmp   divide
repeat:
  mov   ax, bx
  mov   bx, dx
divide:
  xor   dx, dx      ;Zero DX
  div   bx
  test  dx, dx      ;Test if DX is zero
  jnz   repeat
  dec   cx
  jnz   next
  ; the GCD is in BX at this point
  ; use the above link to "Displaying numbers with DOS" to show the result.

За счет дополнительного 1 деления можно заранее упорядочить числа.Это 1-е подразделение установит правильный порядок для вас.Более того, это 1-е деление составляет всего дополнительно в половину времени (в среднем).
Это, в свою очередь, упрощает переход в коде.Меньше прыгать - это всегда хорошо (*).
Более того, я не использовал CX, так как я мог бы просто повторить, основываясь на SI.Зачем тратить хороший регистр?

  mov   ax, @data
  mov   ds, ax
  mov   si, offset arr
  mov   dx, [si]
next:
  add   si, 2
  mov   bx, [si]
repeat:
  mov   ax, bx
  mov   bx, dx
  xor   dx, dx
  div   bx
  test  dx, dx
  jnz   repeat
  mov   dx, bx
  cmp   si, offset arr+4    ;End of the array minus 2
  jb    next
  ; the GCD is in BX (and also in DX) at this point
  ; use the above link to "Displaying numbers with DOS" (it's really good!) to show the result.
...