[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
до вывода всех элементов. - Выводится символ перевода строки и возврата каретки.
- Происходит возврат из подпрограммы.
- Программа завершается.
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д