[TASM] Магический квадрат (3х3) - Assembler
Формулировка задачи:
Здравствуйте! Надеюсь на вашу помощь. Недавно начал изучать Ассемблер и решил написать программу "Магический квадрат", которая должна вывести все 8 квадратов.
Написал несколько строк, но не могу понять где ошибся. Программа входит в вечный цикл...
Листинг программы
- .model medium
- .stack 100h
- .386
- .data
- first dw 0
- second dw 0
- third dw 0
- fourth dw 0
- a1 dw 0
- a2 dw 0
- a3 dw 0
- b1 dw 0
- b2 dw 5
- b3 dw 0
- c1 dw 0
- c2 dw 0
- c3 dw 0
- n15 dw 15
- n10 dw 10
- n9 dw 9
- n8 dw 8
- n7 dw 7
- n6 dw 6
- .code
- mov ax, @data
- mov ds, ax
- ;-----------------------------------------------
- magic_square:
- mov bx, n9
- F:
- mov a1, bx
- mov first, bx
- cmp bx, b2
- JNE Intersect4
- JMP Fall_F
- Intersect4:
- mov cx, n9
- S:
- mov a2, cx
- mov second, cx
- cmp cx, b2
- JNE Intersect3
- JMP Fall_S
- Intersect3:
- mov dx, n9
- Th:
- mov a3, dx
- mov third, dx
- cmp dx, b2
- JNE Intersect2
- JMP Fall_Th
- Intersect2:
- mov ax, n9
- Fh:
- mov b1, ax
- mov fourth, ax
- ; mov ax, b1
- cmp ax, b2
- JNE Intersect
- JMP Fall_Fh
- Intersect:
- cmp ax, a1
- JNE Step1
- JE Prijok1
- Step1:
- cmp ax, a2
- JNE Step2
- JE Prijok1
- Step2:
- cmp ax, a3
- ;JE Fall_Fh
- JNE Next1
- Prijok1: JMP Fall_Fh
- Next1:
- mov ax, a3
- cmp ax, a1
- JNE Step3
- JE Prijok2
- Step3:
- cmp ax, a2
- ; JE Fall_Th
- JNE Next2
- Prijok2: JMP Fall_Th
- Next2:
- mov ax, a2
- cmp ax, a1
- ;JE Fall_S
- JNE Next3
- JMP Fall_S
- Next3:
- mov ax, n10
- sub ax, a1
- mov c3, ax
- mov ax, n10
- sub ax, a2
- mov c2, ax
- mov ax, n10
- sub ax, a3
- mov c1, ax
- mov ax, n10
- sub ax, b1
- mov b3, ax
- mov ax, a1
- add ax, b1
- add ax, c1
- cmp ax, n15
- JE Go
- JMP Fall_Fh
- Go:
- mov ax, a1
- add ax, a2
- add ax, a3
- cmp ax, n15
- JE Goo
- JMP Fall_Fh
- Goo:
- mov ax, a3
- add ax, b3
- add ax, c3
- cmp ax, n15
- JE Gooo
- JMP Fall_Fh
- Gooo:
- mov ax, a1
- add ax, b2
- add ax, c3
- cmp ax, n15
- JE Goooo
- JMP Fall_Fh
- Goooo:
- mov ax, a3
- add ax, b2
- add ax, c1
- cmp ax, n15
- JE Print_square
- JMP Fall_Fh
- mov ax, fourth
- Fall_Fh: dec ax
- cmp ax, 0
- JNE Jumper
- JMP Fall_Th
- Jumper:
- JMP Fh
- mov dx, third
- Fall_Th: dec dx
- cmp dx, 0
- JNE Jumper2
- JMP Fall_S
- Jumper2:
- JMP Th
- mov cx, second
- Fall_S: dec cx
- cmp cx, 0
- JNE Jumper3
- JMP Fall_F
- Jumper3:
- JMP S
- mov bx, first
- Fall_F: dec bx
- cmp bx, 0
- JNE Jumper4
- JMP Konec
- Jumper4:
- JMP F
- ;------------------------------------------------------------
- draw_number:
- push ax
- mov dl,0BAh ;Вертикальная линия
- int 21h
- mov dx,a1 ; Первое число
- int 21h
- mov dl,0BAh ;Вертикальная линия
- int 21h
- mov dx,a2 ; Второе число
- int 21h
- mov dl,0BAh ;Вертикальная линия
- int 21h
- mov dx,a3 ; Третье число
- int 21h
- mov dl,0BAh ;Вертикальная линия
- int 21h
- call print_endline ;Вызов процедуры вывода конца строки
- call print_msg2
- mov dl,0BAh ;Вертикальная линия
- int 21h
- mov dx,b1 ; Первое число
- int 21h
- mov dl,0BAh ;Вертикальная линия
- int 21h
- mov dx,b2 ; Второе число
- ADD dx, 30h ;------------------------------------------------------------------
- int 21h
- mov dl,0BAh ;Вертикальная линия
- int 21h
- mov dx,b3 ; Третье число
- int 21h
- mov dl,0BAh ;Вертикальная линия
- int 21h
- call print_endline ;Вызов процедуры вывода конца строки
- call print_msg2
- mov dl,0BAh ;Вертикальная линия
- int 21h
- mov dx,c1 ; Первое число
- int 21h
- mov dl,0BAh ;Вертикальная линия
- int 21h
- mov dx,c2 ; Второе число
- int 21h
- mov dl,0BAh ;Вертикальная линия
- int 21h
- mov dx,c3 ; Третье число
- int 21h
- mov dl,0BAh ;Вертикальная линия
- int 21h
- call print_endline ;Вызов процедуры вывода конца строки
- pop ax
- ret
- ;--------------------------------------------------------------------
- print_msg1:
- push ax ;Сохранение регистров
- push cx
- push dx
- mov ax, 3
- mov cx,ax ;Копируем длину строки в CX
- mov ah,2 ;Функция DOS 02h - вывод символа
- mov dl,0DAh ;Левый верхний угол
- int 21h
- mov ah,2 ;Функция DOS 02h - вывод символа
- mov dl,0C4h ;Горизонтальная линия
- int 21h
- mov ah,2 ;Функция DOS 02h - вывод символа
- mov dl,0CBh ;203
- int 21h
- mov ah,2 ;Функция DOS 02h - вывод символа
- mov dl,0C4h ;Горизонтальная линия
- int 21h
- mov ah,2 ;Функция DOS 02h - вывод символа
- mov dl,0CBh ;203
- int 21h
- mov ah,2 ;Функция DOS 02h - вывод символа
- mov dl,0C4h ;Горизонтальная линия
- int 21h
- mov ah,2 ;Функция DOS 02h - вывод символа
- mov dl,0BFh ;Правый верхний угол
- int 21h
- call print_endline ;Вызов процедуры вывода конца строки
- ;------------------------------------------------------------------------
- print_msg2:
- push ax ;Сохранение регистров
- push cx
- push dx
- mov ax, 3
- mov cx,ax ;Копируем длину строки в CX
- mov ah,2
- mov dl,0CCh ;left cross
- int 21h
- mov ah,2
- mov dl,0C4h ;Горизонтальная линия
- int 21h
- mov ah,2
- mov dl,0CEh ;cross
- int 21h
- mov ah,2
- mov dl,0C4h ;Горизонтальная линия
- int 21h
- mov ah,2
- mov dl,0CEh ;cross
- int 21h
- mov ah,2
- mov dl,0C4h ;Горизонтальная линия
- int 21h
- mov ah,2
- mov dl,0B9h ;right cross
- int 21h
- call print_endline ;Вызов процедуры вывода конца строки
- pop dx ;Восстановление регистров
- pop cx
- pop ax
- ret ;Возврат из процедуры
- ;-------------------------------------------------------
- print_msg3:
- push ax ;Сохранение регистров
- push cx
- push dx
- mov ax, 3
- mov cx,ax ;Копируем длину строки в CX
- mov ah,2 ;Функция DOS 02h - вывод символа
- mov dl,0C8h ;Левый нижний угол
- int 21h
- mov ah,2 ;Функция DOS 02h - вывод символа
- mov dl,0C4h ;Горизонтальная линия
- int 21h
- mov ah,2 ;Функция DOS 02h - вывод символа
- mov dl,0CAh ;cross up
- int 21h
- mov ah,2 ;Функция DOS 02h - вывод символа
- mov dl,0C4h ;Горизонтальная линия
- int 21h
- mov ah,2 ;Функция DOS 02h - вывод символа
- mov dl,0CAh ;cross up
- int 21h
- mov ah,2 ;Функция DOS 02h - вывод символа
- mov dl,0C4h ;Горизонтальная линия
- int 21h
- mov ah,2 ;Функция DOS 02h - вывод символа
- mov dl,06Ch ; sub right cross
- int 21h
- call print_endline ;Вызов процедуры вывода конца строки
- pop dx ;Восстановление регистров
- pop cx
- pop ax
- ret ;Возврат из процедуры
- ;----------------------------------------------------------------------
- print_endline:
- push ax ;Сохранение регистров
- push dx
- mov ah,2 ;Функция DOS 02h - вывод символа
- mov dl,13 ;Символ CR
- int 21h
- mov dl,10 ;Символ LF
- int 21h
- pop dx ;Восстановление регистров
- pop ax
- ret ;Возврат из процедуры
- Konec:
- Print_square:
- call print_msg1
- call draw_number
- call print_msg3
- mov ax, 4c00h
- int 21h
- end
Решение задачи: «[TASM] Магический квадрат (3х3)»
textual
Листинг программы
- .model small
- .stack 100h
- .data
- Mas db 1,2,3,4,5,6,7,8,9 ; инициализация
- .code
- start:
- mov ax,@data
- mov ds,ax
- call PrintMas ; вывод исходного массива
- xor ah,ah
- int 16h
- M: ; цикл перестановок
- call Change ; перестановка
- call PrintMas ; вывод
- xor ah,ah ; ожидание нажатия клавиши
- int 16h
- jnc M ; все перестановки завершены - выход
- mov ax, 4c00h
- int 21h
- ; подпрограмма перестановки
- Change:
- std
- lea si,Mas[7]
- mov cx,8
- xor dx,dx ; поиск нарушения порядка элементов
- Scan:
- lodsw
- inc dx
- cmp al,ah
- jb NewMas
- inc si
- loop Scan
- stc ; все элементы по убыванию - выход с флагом
- ret
- NewMas:
- mov di,si
- add di,2
- lea si,Mas[8]
- mov cx,dx
- FindMin: ; поиск второго элемента для обмена
- lodsb
- cmp al,[di]
- ja Exchange
- loop FindMin
- Exchange: ; обмен элементов
- xchg al,[di]
- mov [si+1],al
- lea si,Mas[8]
- inc di
- Reverse: ; реверсирование элементов после обмена
- cmp di,si
- jae FinChange
- lodsb
- xchg al,[di]
- mov [si+1],al
- inc di
- loop Reverse
- FinChange:
- clc ; выход без флага
- ret
- ; процедура вывода массива
- PrintMas:
- lea si,Mas
- mov cx,9
- mov ah,2
- Digit:
- mov dl,[si]
- add dl,30h
- int 21h
- inc si
- loop Digit
- mov dl,13
- int 21h
- mov dl,10
- int 21h
- ret
- end
Объяснение кода листинга программы
- Объявляются секции модели и стека программы.
- Объявляется секция данных, где инициализируется массив
Mas
со значениями 1, 2, 3, 4, 5, 6, 7, 8, 9. - Объявляется секция кода, где начинается программа с метки
start
. - Загружается адрес сегмента данных в регистр
ax
, который затем с помощьюmov
помещается в регистрds
. - Вызывается подпрограмма
PrintMas
для вывода исходного массива. - Устанавливается значение
ah
в 0 с помощью операцииxor
. - Совершается прерывание
int 16h
для ожидания нажатия клавиши. - Выполняется цикл
M
для перестановок. - Вызывается подпрограмма
Change
для выполнения перестановки. - Вызывается подпрограмма
PrintMas
для вывода переставленного массива. - Ожидается нажатие клавиши с помощью прерывания
int 16h
. - Если флаг не установлен (клавиша нажата), переходим к метке
M
для продолжения цикла перестановок. - Если все перестановки завершены, выполняется инструкция
mov ax, 4c00h
для завершения программы с помощью прерыванияint 21h
. - Следует подпрограмма
Change
для выполнения перестановки. - Устанавливается флаг
stc
. - Загружается адрес элемента Mas[7] в регистр
si
. - Загружается количество элементов в регистр
cx
. - Инициализируется регистр
dx
с помощьюxor
для поиска нарушения порядка элементов. - Идет сканирование элементов массива.
- Загружается очередной элемент в
al
. - Увеличивается значение
dx
. - Сравниваются значения
al
иah
. - Если
al
меньшеah
, переходим к меткеNewMas
. - Иначе увеличивается значение
si
и выполняется проверка оставшихся элементов циклаScan
. - Если все элементы упорядочены по убыванию, устанавливается флаг
stc
и происходит возврат из подпрограммы. - В противном случае, ищется второй элемент для обмена.
- Загружается следующий элемент массива в
al
. - Сравнивается значение
al
с текущим элементомMas[di]
. - Если
al
больше, переходим к меткеExchange
. - Если необходимо, продолжается поиск второго элемента для обмена.
- Выполняется обмен элементов
al
иMas[di]
. - Сохраняется значение
al
вMas[si+1]
. - Обновляется адрес элемента
si
для поиска следующего элемента. - Увеличивается значение
di
для поиска следующего элемента. - Выполняется реверсирование элементов после обмена.
- Сравнивается значение регистра
di
сsi
. - Если
di
большеsi
, выполняется обратный обмен элементов и обновляются значения регистров. - Продолжается реверсирование элементов до тех пор, пока не все элементы не будут обработаны.
- Выполняется завершающая часть подпрограммы с очисткой флага
clc
и возвратом из подпрограммы. - Происходит подпрограмма
PrintMas
для вывода массива. - Загружается адрес массива
Mas
в регистрsi
. - Загружается количество элементов массива в регистр
cx
. - Устанавливается значение
ah
в 2 для выполнения прерыванияint 21h
. - Выводится значение текущего элемента массива, увеличивается значение
si
и продолжается циклDigit
до вывода всех элементов. - Выводится символ перевода строки и возврата каретки.
- Происходит возврат из подпрограммы.
- Программа завершается.
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д