Доброго времени суток, уважаемые форумчане! Мне нужно написать программу, которая перед началом игры произвольно устанавливает невидимую на экране метку и видимый символ "*", который перемещается по экрану с помощью стрелок. При движении символа генерируются звуковые колебания, частота которых зависит от расстояния до невидимой метки. Если метка не найдена за 4 секунды, метка перемещается в другую точку.
Мне очень эта программа напоминает металлоискатель : )
Пока что я сделал только перемещение символа "*" с помощью букв w,s,a,d.
data segment
old_cs dw ?
old_ip dw ?
symbol db ?
Pressed db 1
x db ?
y db ?
sgn db '*'
atr db 10
data ends
code segment
assume cs: code, ds: data
new_1c proc far
push ax
push bx
push ds
push es
mov ax, data
mov ds, ax
mov ax, 40h
mov es, ax
mov ax, es:[1Ch]
mov bx, es:[1Ah]
cmp bx, ax
jne get_char
jmp go_out
get_char:
mov al, es:[bx]
mov es:[1Ch], bx
mov symbol, al
inc Pressed
go_out:
pop es
pop ds
pop bx
pop ax
iret
new_1c endp
start:
mov ax, data
mov ds, ax
mov ah, 35h
mov al, 1Ch
int 21h
mov old_ip, bx
mov old_cs, es
push ds
mov dx, offset new_1c
mov ax, seg new_1c
mov ds, ax
mov ah, 25h
mov al, 1Ch
int 21h
pop ds
mov ax, data
mov es, ax
mov x,14
mov y,40
main_loop:
cmp Pressed, 0
je m1
mov Pressed, 0
cmp symbol, 30h
je q
xor ax, ax
mov al, symbol
m1: cmp al, 'w'
jne m2
dec x
jmp met
m2: cmp al, 's'
jne m3
inc x
jmp met
m3: cmp al, 'a'
jne m4
dec y
jmp met
m4: cmp al, 'd'
jne main_loop
inc y
met: xor bh, bh
mov ah, 13h
mov al, 0d
mov dh, x
mov dl, y
lea bp, sgn
mov cx, 1
mov bl, atr
int 10h
jmp main_loop
q:
push ds
mov dx, old_ip
mov ax, old_cs
mov ds, ax
mov ah, 25h
mov al, 1Ch
int 21h
pop ds
mov ax, 4C00h
int 21h
code ends
end start
data segment
old_cs dw ?
old_ip dw ?
symbol db ?
Pressed db 1
x db ?
y db ?
sgn db '*'
atr db 10
data ends
code segment
assume cs: code, ds: data
clrscn proc
push ax
push bx
push ds
push es
mov cl, 0
mov ch, 0
mov dl, 80
mov dh, 25
xor ax,ax
mov al,0
xor bx, bx
mov bh, atr
int 10h
pop es
pop ds
pop bx
pop ax
ret
clrscn endp
new_1c proc far
push ax
push bx
push ds
push es
mov ax, data
mov ds, ax
mov ax, 40h
mov es, ax
mov ax, es:[1Ch]
mov bx, es:[1Ah]
cmp bx, ax
jne get_char
jmp go_out
get_char:
mov al, es:[bx]
mov es:[1Ch], bx
mov symbol, al
inc Pressed
go_out:
pop es
pop ds
pop bx
pop ax
iret
new_1c endp
start:
mov ax, data
mov ds, ax
mov ah, 35h
mov al, 1Ch
int 21h
mov old_ip, bx
mov old_cs, es
push ds
mov dx, offset new_1c
mov ax, seg new_1c
mov ds, ax
mov ah, 25h
mov al, 1Ch
int 21h
pop ds
mov ax, data
mov es, ax
mov x,14
mov y,40
main_loop:
;call clrscn
cmp Pressed, 0
je m1
mov Pressed, 0
cmp symbol, 30h
je q
xor ax, ax
mov al, symbol
m1: cmp al, 'w'
jne m2
dec x
jmp met
m2: cmp al, 's'
jne m3
inc x
jmp met
m3: cmp al, 'a'
jne m4
dec y
jmp met
m4: cmp al, 'd'
jne main_loop
inc y
met:
call clrscn
xor bh, bh
mov ah, 13h
mov al, 0d
mov dh, x
mov dl, y
lea bp, sgn
mov cx, 1
mov bl, atr
int 10h
jmp main_loop
q:
push ds
mov dx, old_ip
mov ax, old_cs
mov ds, ax
mov ah, 25h
mov al, 1Ch
int 21h
pop ds
mov ax, 4C00h
int 21h
code ends
end start
1. Звук генерится посредством 53 таймера, причем его прохождение на динамик еще надо разрешить. Конкретных номеров портов навскидку не помню - давно не программировал под DOS.
2. х86 процессор не имеет аппаратных средств для генерации случайных чисел. Это ответ на твой вопрос - есть ли в ассемблере рандом. Но можно сделать программно генератор псевдослучайных чисел. Например, конгруэнтный. А инициализировать его (аналог randomize) чем-то, связанным с текущим временем. Хотя бы содержимым ячейки 0040:006c.
procedure _RandInt;
asm
PUSH EBX
XOR EBX, EBX
IMUL EDX,[EBX].RandSeed,08088405H
INC EDX
MOV [EBX].RandSeed,EDX
MUL EDX
MOV EAX,EDX
POP EBX
end;
А турбо-паскальный рандом такой же. Я не нашёл менее порнушного способа перемножить два 32-битных числа на 16-битном асме, так что вот, процедура оформлена по-паскалевски, но оформите её по-асмовски сами.
function RAsm(w: word): word; assembler;
asm
mov dx, 8405h
mov ax, word ptr RS
mul dx
mov cx, ax
mov bx, dx
mov dx, 0808h
mov ax, word ptr RS
mul dx
add bx, ax
mov dx, 8405h
mov ax, word ptr RS+2
mul dx
add bx, ax
inc cx
jno @
inc(bx)
@:
mov word ptr RS, cx
mov word ptr RS+2, bx
mov dx, bx
mov ax, w
mul dx
mov ax, dx
end;
По поводу генерации звуков - когда-то 7in на одном из форумов приводил вот такие процедуры:
; Процедура Sound: генерация звука
; Вход: AX = частота звука (Гц)
Sound proc
xchg bx, ax ; Частота
mov dx, 12h ; (DX,AX)=1193181
cmp bx, dx ; Если Bx <= 18Гц, то выход
jbe Done ; Чтобы избежать переполнения
in al, 61h ; Порт РВ
or al, 3 ; Установить биты 0-1
out 61h, al
mov al, 10110110b ; Управляющее слово таймера:
; канал 2, режим 3, двоичное слово
out 43h, al ; Вывод в регистр режима
mov ax, 34DDh
div bx ; AX=(DX:AX)/BX
out 42h, al ; Младший байт счетчика
mov al, ah
out 42h, al ; Старший байт счетчика
Done:
ret
Sound endp
;-------------------------------------------------;
; Процедура NoSound: выключение звука
NoSound proc
in al, 61h ; Порт РВ
and al, not 3 ; Сброс битов 0-1
out 61h, al
ret
NoSound endp
После долго перерыва возвращаюсь к выполнению этого задания (с COM портами вроде разобрался )
Решил систематизировать эту задачку,т.к. довольно она для меня трудоёмкая, сложная и значимая. Так вот, что нужно:
1. Произвольно ставить невидимую точку;
2. Перемещать курсор (значок *);
3. Генерировать звук определённой частоты;
4. Каждые 4 сек менять положение невидимой точки.
План минимум, да и вообще основной - это первые три пункта... 2-ой я реализовал- вроде как перемещаю.
Начну с randoma. Уже была дана реализация:
function RAsm(w: word): word; assembler;
asm
mov dx, 8405h
mov ax, word ptr RS
mul dx
mov cx, ax
mov bx, dx
mov dx, 0808h
mov ax, word ptr RS
mul dx
add bx, ax
mov dx, 8405h
mov ax, word ptr RS+2
mul dx
add bx, ax
inc cx
jno @
inc(bx)
@:
mov word ptr RS, cx
mov word ptr RS+2, bx
mov dx, bx
mov ax, w
mul dx
mov ax, dx
end;
data segment
RS dw 0
w dw 80
r dw ?
data ends
code segment
assume cs: code, ds: data
writeDEC proc
push ax
push bx
push cx
push dx
xor cx, cx
mov bx, 10
next_digit:
xor dx, dx
div bx
push dx
inc cx
or ax, ax
jnz next_digit
next_char:
pop ax
add al, '0'
mov dx, ax
mov ah, 02h
int 21h
loop next_char
pop dx
pop cx
pop bx
pop ax
ret
writeDEC endp
Rand proc
push ax
push bx
push cx
push dx
mov dx, 8405h
mov ax, word ptr RS
mul dx
mov cx, ax
mov bx, dx
mov dx, 0808h
mov ax, word ptr RS
mul dx
add bx, ax
mov dx, 8405h
mov ax, word ptr RS+2
mul dx
add bx, ax
inc cx
jno @
inc(bx)
@:
mov word ptr RS, cx
mov word ptr RS+2, bx
mov dx, bx
mov ax, w
mul dx
mov ax, dx
mov r, ax
pop dx
pop cx
pop bx
pop ax
ret
Rand endp
start:
mov ax, data
mov ds, ax
call Rand
mov ax, r
call writeDEC
mov ax, 4C00h
int 21h
code ends
end start
В интернете как-то мало материала по этой теме, так что необходимо разобраться в данной реализации random'а на ассемблере... Что не правильно в реализации Rand в предыдущем сообщении? Пожалуйста подскажите.
Что-то вопрос о random'е намертво забуксовал... Перейду к другой части задачи: генерация звука определенной частоты. Вот программы, в которой я передвигаю курсор, а его движение сопровождается нотой до (я эту ноту могу часами держать(с) )
data segment
old_cs dw ?
old_ip dw ?
symbol db ?
Pressed db 1
x db ?
y db ?
sgn db '*'
atr db 10
data ends
code segment
assume cs: code, ds: data
clrscn proc
push ax
push bx
push ds
push es
mov cl, 0
mov ch, 0
mov dl, 80
mov dh, 25
xor ax,ax
mov al,0
xor bx, bx
mov bh, atr
int 10h
pop es
pop ds
pop bx
pop ax
ret
clrscn endp
Sound proc
push ax
push bx
push ds
push es
mov bx,ax
mov ax,word ptr cs:freq
mov dx,word ptr cs:freq+2
div bx
mov bx,ax
in al,61h
nop
nop
nop
or al,3
out 61h,al
nop
nop
nop
mov al,10110110b
out 43h,al
nop
nop
nop
mov al,bl
out 42h,al
nop
nop
nop
mov al,bh
out 42h,al
nop
nop
nop
pop es
pop ds
pop bx
pop ax
ret
freq dd 1193180
Sound endp
NoSound proc
push ax
push bx
push ds
push es
in al,61h
nop
nop
nop
and al,11111100b
out 61h,al
nop
nop
nop
pop es
pop ds
pop bx
pop ax
ret
NoSound endp
new_1c proc far
push ax
push bx
push ds
push es
mov ax, data
mov ds, ax
mov ax, 40h
mov es, ax
mov ax, es:[1Ch]
mov bx, es:[1Ah]
cmp bx, ax
jne get_char
jmp go_out
get_char:
mov al, es:[bx]
mov es:[1Ch], bx
mov symbol, al
inc Pressed
go_out:
pop es
pop ds
pop bx
pop ax
iret
new_1c endp
start:
mov ax, data
mov ds, ax
mov ah, 35h
mov al, 1Ch
int 21h
mov old_ip, bx
mov old_cs, es
push ds
mov dx, offset new_1c
mov ax, seg new_1c
mov ds, ax
mov ah, 25h
mov al, 1Ch
int 21h
pop ds
mov ax, data
mov es, ax
mov x,14
mov y,40
main_loop:
;call clrscn
cmp Pressed, 0
je m1
mov Pressed, 0
cmp symbol, 30h
je q
xor ax, ax
mov al, symbol
m1: cmp al, 'w'
jne m2
dec x
jmp met
m2: cmp al, 's'
jne m3
inc x
jmp met
m3: cmp al, 'a'
jne m4
dec y
jmp met
m4: cmp al, 'd'
jne main_loop
inc y
met:
push ax
xor ax,ax
mov ax, 262
call Sound
pop ax
call clrscn
xor bh, bh
mov ah, 13h
mov al, 0d
mov dh, x
mov dl, y
lea bp, sgn
mov cx, 1
mov bl, atr
int 10h
jmp main_loop
q:
push ds
mov dx, old_ip
mov ax, old_cs
mov ds, ax
mov ah, 25h
mov al, 1Ch
int 21h
pop ds
mov ax, 4C00h
int 21h
code ends
end start
start:
mov ax, data
mov ds, ax
mov es, ax
call RandomSeed
mov cx, 0
mov dx, 50
call RandomRange ; Random в интервале [0 .. 50]
call writeDEC
mov ax, 4C00h
int 21h
Очень просто... Вот тут есть пример практически того, что тебе надо:
http://www.fastgraph.com/makegames/sidescroller/chapt12.html#S17
Почему я? Кто привел тебе этот код, тот пускай и смотрит, почему код не работает. Все на самом деле гораздо проще делается. Я тебе уже привел ссылку на работающий код. Если тот код тебе не нравится - то (с учетом того, что координаты у тебя все равно однобайтовые, в пределах от 0 до 80) можешь попробовать вот эту процедуру:
RS dw 0Получи в одной программе несколько чисел:
range db 80
random proc
mov ax, RS
mov dx, 8405h
mul dx
inc ax
mov dx, ax
mov RS, ax
mov cl, range
sub cl, 2
inc cx
xor dx, dx
div cx
mov ax, dx ; в AX - случайное число...
ret
random endp
call random, и убедись, что они все разные, и ни одно не превышает 80. Но вот при разных запусках все последовательности будут одинаковыми, потому что RS не изменяется, он при старте программы всегда один и тот же. Чтобы получить разные последовательности - занеси в RS при старте значение системного таймера...
xor ah, ah
call writeDEC
lea dx, CR
mov ah, 9
int 21h
call random
xor ah, ah
call writeDEC
lea dx, CR
mov ah, 9
int 21h
call random
xor ah, ah
call writeDEC
lea dx, CR
mov ah, 9
int 21h
call random
xor ah, ah
call writeDEC
lea dx, CR
mov ah, 9
int 21h
data segment
RS dw ?
range db 80
CR db 13,10,"$"
data ends
code segment
assume cs: code, ds: data
writeDEC proc
push ax
push bx
push cx
push dx
xor cx, cx
mov bx, 10
next_digit:
xor dx, dx
div bx
push dx
inc cx
or ax, ax
jnz next_digit
next_char:
pop ax
add al, '0'
mov dx, ax
mov ah, 02h
int 21h
loop next_char
pop dx
pop cx
pop bx
pop ax
ret
writeDEC endp
GetTime proc
push ax
push cx
push dx
xor ax,ax
xor cx,cx
xor dx,dx
mov ah, 2ch
int 21h
mov al, dh
mov ah, dl
mov RS, ax
pop dx
pop cx
pop ax
ret
GetTime endp
random proc
push ax
push bx
push cx
push dx
mov ax, RS
mov dx, 8405h
mul dx
inc ax
mov dx, ax
mov RS, ax
mov cl, range
sub cl, 2
inc cx
xor dx, dx
div cx
mov ax, dx ; в AX - случайное число...
pop dx
pop cx
pop bx
pop ax
ret
random endp
start:
mov ax, data
mov ds, ax
call GetTime
mov ax, RS
call writeDEC
lea dx, CR
mov ah, 9
int 21h
call random
xor ah, ah
call writeDEC
lea dx, CR
mov ah, 9
int 21h
call random
xor ah, ah
call writeDEC
lea dx, CR
mov ah, 9
int 21h
call random
xor ah, ah
call writeDEC
lea dx, CR
mov ah, 9
int 21h
call random
xor ah, ah
call writeDEC
lea dx, CR
mov ah, 9
int 21h
mov ax, 4C00h
int 21h
code ends
end start
F:\Asm30>rand3
48
33
54
15
F:\Asm30>rand3
54
15
28
61
F:\Asm30>rand3
43
40
57
78
RS dw 0Получи в одной программе несколько чисел:
range db 80
random proc
mov ax, RS
mov dx, 8405h
mul dx
inc ax
mov dx, ax
mov RS, ax
mov cl, range
sub cl, 2
inc cx
xor dx, dx
div cx
mov ax, dx ; в AX - случайное число...
ret
random endp
call random, и убедись, что они все разные, и ни одно не превышает 80. Но вот при разных запусках все последовательности будут одинаковыми, потому что RS не изменяется, он при старте программы всегда один и тот же. Чтобы получить разные последовательности - занеси в RS при старте значение системного таймера...
xor ah, ah
call writeDEC
lea dx, CR
mov ah, 9
int 21h
call random
xor ah, ah
call writeDEC
lea dx, CR
mov ah, 9
int 21h
call random
xor ah, ah
call writeDEC
lea dx, CR
mov ah, 9
int 21h
call random
xor ah, ah
call writeDEC
lea dx, CR
mov ah, 9
int 21h