[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до вывода всех элементов. - Выводится символ перевода строки и возврата каретки.
- Происходит возврат из подпрограммы.
- Программа завершается.