Python на Assembler (Tasm)

Сьогодні напишемо в текстовому режимі з використанням переривань BIOS і DOS змійку на Assembler. Для цього потрібно знати основи, вміти ассемблировать (Tasm) і компонувати (Tlink) код.

Для початку напишемо основу — змійку, яка переміщається в одному напрямку по ігровому полю. Змійка буде складатися з символу "*", координати кожного символу зберігаються в пам'яті.



Подивитися код
model small

.data ;Сегмент даних. Зберігаємо координати тіла змійки
snake dw 0000h
dw 0001h
dw 0002h
dw 0003h
dw 0004h
dw 7CCh dup('?')

.stack 100h

.code
;Початок сегменту коду будемо розміщувати процедури
delay proc
push cx
mov ah,0
int 1Ah 
add dx,3
mov bx,dx
repeat: 
int 1Ah
cmp dx,bx
jl repeat
pop cx
ret
delay endp

start:
mov ax,@data
mov ds,ax
mov es,ax

mov ax,0003h
int 10h ;Очищаємо ігрове поле

mov cx,5
mov ax,0A2Ah
int 10h ;Виводимо змійку з 5 символів ".*"


mov si,8 ;Індекс координати символу голови
xor di,di ;Індекс координати символу хвоста
mov cx,0001h ;Регістр cx використовуємо для керування головою. При додаванні від значення cx буде змінюватися координата x або y

main: ;Основний цикл
call delay
xor bh,bh
mov ax,[snake+si] ;Беремо координату голови з пам'яті
add ax,cx ;Змінюємо координату x
inc si 
inc si
mov [snake+si],ax ;Заносимо в пам'ять нову координату голови змії
mov dx,ax 
mov ax,0200h
int 10h ;Викликаємо переривання. Переміщаємо курсор
mov ah,02h
mov dl,002Ah
int 21h ;Переривання виводить символ '*'

mov ax,0200h 
mov dx,[snake+di]
int 10h
mov ax,0200h
mov dl,0020h
int 21h ;Виведемо пробіл, тим самим видаляючи хвіст
inc di
inc di
jmp main
end start 


Додамо процедуру «key_press» обробки натиснення клавіші і присвоювання значення регістра CX, який відповідає за напрям голови.

Управління стрілками.


key_press
key_press proc
mov ax, 0100h
int 16h
jz en ;Без натискання виходимо
xor ah, ah
int 16h
cmp ah, 50h
jne up
cmp cx,0FF00h ;Порівнюємо щоб не піти на себе
je en
mov cx,0100h
jmp en
up: cmp ah,48h
jne left
cmp cx,0100h
je en
mov cx,0FF00h
jmp en
left: cmp ah,4Bh
jne right
cmp cx,0001h
je en
mov cx,0FFFFh
jmp en
right: cmp cx,0FFFFh
je en
mov cx,0001h
en:
ret
key_press endp


Викличемо її відразу після виклику процедури delay:

main:
call delay
call key_press


Нагодуємо змійку, створюємо процедуру «add_food». Ця процедура буде на ігровому полі розміщувати їжу, символи "$". В якості випадкових чисел будемо брати час.
add_food
add_food proc
sc: 
inc bl ;В регістрі BL рандомное число
cmp bx,50h ;Перевіряємо кордон числа
jng ex
shr bl,1 ;Якщо більше, ділимо на 2 логічним зсувом
jmp sc
ex:
mov dl,bl ;Запис координати
sc2: 
cmp bx,19h
jng ex2
shr bl,2
jmp sc2
ex2:
mov dh,bl ;Запис координати
mov ax,0200h
int 10h
mov ax,0800h
int 10h
cmp al,2Ah ;Перевіряємо порожнє місце
je sc
cmp al,40h 
je sc ;Якщо немає повторюємо
mov ax,0200h
mov dl,0024h
int 21h
ret
add_food endp



Викличемо 1 раз на початку.

mov bl,51h
call add_food
main:


Робимо перевірку, з'їла змія їжу чи ні. Якщо з'їла, викликаємо процедуру «add_food» і не видаляємо хвіст.

Перевірку додаємо код перед виведенням символу голови:

mov ah,02h
int 10h ;Викликаємо переривання. Переміщаємо курсор

mov ax,0800h
int 10h ;Читає символ 
mov dh,al

mov ah,02h
mov dl,002Ah
int 21h ;Переривання виводить символ '*'

cmp dh,24h
jne next
call add_food
jmp main
next: 


Ускладнимо гру. Після того, як пітон з'їсть 5 символів, у хвості буде з'являтися символ "@". Пишемо лічильник і виведення символу:


shit
;сегмент даних додамо рядок
.data
tick dw 0 ;Лічильник
--------------------------------------------------------------------

cmp dh,24h
jne next

push cx ;В стек регістр
mov cx,[tick]
inc cx
cmp cx,5
jne exl
xor cx,cx
mov ax,0200h 
mov dx,[snake+di-2]
int 10h
mov ax,0200h
mov dl,0040h
int 21h
exl:mov [tick],cx
pop cx

call add_food
jmp main
next: 


Яка гра без Game Over. Пишемо процедуру перевірки межі поля, а також врізання в себе і символ "@".
game_over
game_over proc
;Перевіряємо кордону
cmp dl,50h
je exit
cmp dl,0
jl exit
cmp dh,0
jl exit
cmp dh,19h
je exit
;Перевіряємо символи
cmp al,2Ah
je exit
cmp al,40h
je exit
jmp good
exit: 
mov ax,4c00h
int 21h
good:
ret
game_over endp


Викликаємо її після зчитування символу:

mov ax,0800h
int 10h ;Зчитуємо символ

call game_over

mov dh,al


Трохи магії додаємо після инкремента індексів.
magic
inc si 
inc si
cmp si,7CAh
jne nex
xor si,si
nex: 

---------------------------------------------------------------------

inc di
inc di
cmp di,7CCh
jne main
xor di,di



Ну ось і все, також можна додати меню з вибором рівня, паузу, заставку Game Over, рахунок очок.

посилання архів з вихідним кодом, exe'шником і DosBox для тих, у кого не запуститься.

З днем програміста!

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.