Помощь - Поиск - Пользователи - Календарь
Полная версия: Заполнение матрицы случайными числами
Форум «Всё о Паскале» > Современный Паскаль и другие языки > Ассемблер
18192123
Объясните пожалуйста, как можно инициализировать матрицу случайными числами??
18192123
вот что у меня получилось...только матрица инициализируется совершенно различными символами, а хотелось бы, чтобы только числами..Объясните пожалуста, как это сделать?

assume CS: code, DS: data
code segment
begin:

mov AX, data
mov DS, AX

;xor ax,ax
mov cx,3
mov si,0
mov bx,0
external:
push cx
mov cx,3
mov si,0
iternal:
xor ax,ax
out 43h,al
in al,40h
;mov bh,i
mov array[bx][si],al
;inc i
inc si
loop iternal
pop cx
inc bx
loop external


mov cx,3
mov si,0
mov bx,0

exshow:
push cx
mov cx,3
mov si,0
ishow:
mov ah,02h
mov dl,array[bx][si]
;add dl,30h у меня символы!
int 21h
inc si
loop ishow
lea dx,nl ;переход на новую строку
pop cx
inc bx
loop exshow

exit:
mov ah,08h
int 21h
mov ax,4c00h
int 21h


code ends

data segment
array db 3 dup(3 dup(?))
i db 0
nl db 13,10,'$'
data ends

stk segment stack
dw 128 dup (0)
stk ends

end begin


и ещё не срабатывает переход на следующую строку при выводе матрицы..
andriano
1. Я уже навскидку не помню, 40/43 - это порты таймера? Если "да", то алгоритм получения случайного числа принципиально неверный. Он подходит либо для получения ОДНОГО случайного числа, либо инициализации ДПСЧ, но никак не для получения серии случайных чисел.
2. Что хранится у тебя в массиве: числа или символы? Если числа, то это одно - тогда у тебя в массиве то, что надо, но при выводе на экран их надо преобразовывать в числа от 0 до 255. Если же - символы, причем требуется, чтобы символы были цифрами (не числами), то необходимо дополнительное преобразование для приведения символов к нужному диапазону, т.е. к 30h-39h.
18192123
Цитата(andriano @ 13.05.2008 19:42) *

1. Я уже навскидку не помню, 40/43 - это порты таймера? Если "да", то алгоритм получения случайного числа принципиально неверный. Он подходит либо для получения ОДНОГО случайного числа, либо инициализации ДПСЧ, но никак не для получения серии случайных чисел.
2. Что хранится у тебя в массиве: числа или символы? Если числа, то это одно - тогда у тебя в массиве то, что надо, но при выводе на экран их надо преобразовывать в числа от 0 до 255. Если же - символы, причем требуется, чтобы символы были цифрами (не числами), то необходимо дополнительное преобразование для приведения символов к нужному диапазону, т.е. к 30h-39h.

1. насколько я поняла, да - это порты таймера..
2.
array db 3 dup(3 dup(?))

в матрице символы.. а как вообще нужно преобразовывать к нужному диапазону?
andriano
1. Тогда у тебя последовательность явно не случайных чисел.
2. Например, делением на 26 (частное) или на 10 (остаток) с последующим прибавлением 30h, т.е. кода символа "0".
18192123
Цитата(andriano @ 13.05.2008 20:20) *

1. Тогда у тебя последовательность явно не случайных чисел.

т.е мне нужно использовать другие порты?
andriano
Нет. В IBM PC нет встроенного датчиа случайных чисел, поэтому пытаться извлечь их откуда-то - задача не из простых.
Обычно вместо случайных чисел используют псевдослучайные - т.е. вполне конкретную циклическую последовательность чисел, формируемых по определенному алгоритму, которая по статистическим характеристикам близка к последовательности случайных чисел.
Но т.к. числа формируются алгоритмически, последовательность их жестко предопределена. Чтобы избавиться от этой предопределенности вводят дополнительную процедуру инициализации алгоритма, при которой та же самая циклическая последовательность уже будет начинаться не с первого члена, а с какого-то другого. Т.е. при разных запусках программы последовательность не будет повторяться, а будет каждый раз другая. Для инициализации обычно берут текущее время.
Т.е. порядок работы такой (примеры, извини, в Паскаль - оболочке):
пишем сам генератор ПСЧ (простой и быстрый, но не уверен, что пройдет все статистические тесты):
var iax,ibx:word;

function random:word;{ »poµeñπpa óδñaτ¿ äBôX 16-í¿Γ¡δx »ceóño-c½πτa¡δx τ¿ce½:}
var q:word;
begin
asm
mov ax,iax
mov bx,ibx
xor ax,bx
shl ax,1
adc bx,0
xor bx,ax
xchg bl,bh
mov iax,ax
mov ibx,bx
end;
random := ibx;
end;
где в переменных хранится текущее состояние ДПСЧ.
Эти переменные надо инициализировать. Вот это можно сделать при помощи таймера:
procedure randomize;
begin
asm
Mov AL,00000000b
Out 43h,AL
In AL,40h
Mov AH,AL
In AL,40h
XChg AL,AH
mov iax,ax
end;
ibx := 9821;
end;

Теперь перед первым использованием мы вызываем randomize, а затем используем random
18192123
Вот к чему я пришла..генерацию вставила, но программа зацикливается..(вообще программа выводит 10 раз матрицу, заполненную случайными числами и ждёт нажатия клавиши)


dely macro time; (1)
local zd,c1,cikl,ii,ii1; (2) описываем все метки, используемые вмакроопределении
push cx; (3)помещаем в стек используемые в макроопределении регистры
push bx; (4)
push bp; (5)
push ax; (6)
push dx; (7)
mov cx,time; (8) задаём количество повторений цикла задержки zd – задержка в цикле 18.2 секунды
zd: push cx; (9)
mov bp,0;(10)
mov bx,1;(11)

cikl:
inc BP;(12)
mov ah,00h;(13)
int 1Ah;(14)
cmp BP,1;(15)
je ii;(16) переходим на метку ii на первой итерации цикла
jmp ii1;(17) на следующих итерациях переходим на метку ii1
ii: add bx,dx;(18) формируем значение на единицу больше, чем в регистре dx
ii1: ; (19)
cmp bx,dx;(20) если значение в регистре dx изменилось(сравниваем значение в dx с сформированным в строке 18 значением в регистре bx, которое на единицу больше, на единицу больше значение в dx станет через 18.2 сек)
jne cikl;(21) если нет, то новая итерация цикла
pop cx;(22) если да, конец макрокоманды задержки
loop zd;(23)
pop cx;(24)
pop bx;(25)
pop bp;(26)
pop ax;(27)
pop dx;(28)
endm;(29)

assume CS: code, DS: data
code segment
randomize proc
Mov AL,00000000b
Out 43h,AL
In AL,40h
Mov AH,AL
In AL,40h
XChg AL,AH
mov iax,ax

randomize endp

matr proc
mov cx,3
mov si,0
mov bx,0
call randomize
external:
push cx
mov cx,3
mov si,0
iternal:

mov ax,iax
mov bx,ibx
xor ax,bx
shl ax,1
adc bx,0
xor bx,ax
xchg bl,bh
mov iax,ax
mov ibx,bx

mov array[bx][si],ax
add si,2
loop iternal
pop cx
add bx,4
loop external


mov cx,3
mov si,0
mov bx,0
exshow:
push cx
mov cx,3
mov si,0
ishow:
mov ah,02h
mov dx,array[bx][si]
add dl,30h
int 21h
add si,2
loop ishow
;lea dx,nl ;переход на новую строку
pop cx
add bx,4
loop exshow
ret
matr endp

begin:

mov AX, data
mov DS, AX
mov cx,10
miganie:
push cx
call matr
dely 18
mov ah,02h ;сдвижка курсора обратно в начало строки
mov bh,00
mov dh,15
mov dl,0
int 10h
pop cx
loop miganie

exit:
mov ah,08h
int 21h
mov ax,4c00h
int 21h


code ends

data segment
array dw 3 dup(3 dup(0))
i db 0
nl db 13,10,'$'
iax dw 0
ibx dw 9821
data ends

stk segment stack
dw 128 dup (1)
stk ends

end begin



andriano
Ты пытаешься использовать регистр bx сразу для двух целей: участие в генерации ПСЧ и для адресации в массиве. Естественно, его содержимое при этом портится. Ты уж либо сохраняй его содержимое в стеке (кстати, посмотри, нельзя ли вместно него использовать dx), либо, что лучше, вынеси генерацию ПСЧ в отдельную процедуру с сохранением регистров.
18192123
Я вынесла генерацию ПСЧ в отдельную процедуру (значение регистра bx сохраняется в стеке перед её вызовом)..Но программа по-прежнему не работает..Объясните пожалуста, в чём дело?


dely macro time; (1)
local zd,c1,cikl,ii,ii1; (2) описываем все метки, используемые вмакроопределении
push cx; (3)помещаем в стек используемые в макроопределении регистры
push bx; (4)
push bp; (5)
push ax; (6)
push dx; (7)
mov cx,time; (8) задаём количество повторений цикла задержки zd – задержка в цикле 18.2 секунды
zd: push cx; (9)
mov bp,0;(10)
mov bx,1;(11)

cikl:
inc BP;(12)
mov ah,00h;(13)
int 1Ah;(14)
cmp BP,1;(15)
je ii;(16) переходим на метку ii на первой итерации цикла
jmp ii1;(17) на следующих итерациях переходим на метку ii1
ii: add bx,dx;(18) формируем значение на единицу больше, чем в регистре dx
ii1: ; (19)
cmp bx,dx;(20) если значение в регистре dx изменилось(сравниваем значение в dx с сформированным в строке 18 значением в регистре bx, которое на единицу больше, на единицу больше значение в dx станет через 18.2 сек)
jne cikl;(21) если нет, то новая итерация цикла
pop cx;(22) если да, конец макрокоманды задержки
loop zd;(23)
pop cx;(24)
pop bx;(25)
pop bp;(26)
pop ax;(27)
pop dx;(28)
endm;(29)

assume CS: code, DS: data
code segment
randomize proc
Mov AL,00000000b
Out 43h,AL
In AL,40h
Mov AH,AL
In AL,40h
XChg AL,AH
mov iax,ax
randomize endp

random proc
mov ax,iax
mov bx,ibx
xor ax,bx
shl ax,1
adc bx,0
xor bx,ax
xchg bl,bh
mov iax,ax
mov ibx,bx
random endp

matr proc
mov cx,3
mov si,0
mov bx,0

call randomize

external:
push cx
mov cx,3
mov si,0

iternal:
push bx
call random
pop bx
mov array[bx][si],ax
add si,2
loop iternal
pop cx
add bx,4
loop external

mov cx,3
mov si,0
mov bx,0
exshow:
push cx
mov cx,3
mov si,0
ishow:
mov ah,02h
mov dx,array[bx][si]
add dl,30h
int 21h
add si,2
loop ishow
;lea dx,nl ;переход на новую строку
pop cx
add bx,4
loop exshow
ret
matr endp

begin:

mov AX, data
mov DS, AX
mov cx,10
miganie:
push cx
call matr
dely 18
mov ah,02h ;сдвижка курсора обратно в начало строки
mov bh,00
mov dh,15
mov dl,0
int 10h
pop cx
loop miganie

exit:
mov ah,08h
int 21h
mov ax,4c00h
int 21h


code ends

data segment
array dw 3 dup(3 dup(0))
i db 0
nl db 13,10,'$'
iax dw 0
ibx dw 9821
data ends

stk segment stack
dw 128 dup (1)
stk ends

end begin


andriano
1. Вместо "не работает" хотелось бы узнать конкретные симптомы, по которым ты определяешь отсутствие работоспособности. Тем более, что у меня сейчас нет ни одного установленного Ассемблера, следовательно, проверить никак не могу - могу лишь полагаться на твои слова.

2. push/pop принято помещать внутри процедуры. Т.е. те регистры, которые процедура портит, она и должна сохранять, а вызывающая программа об этом ничего знать не обязана.

3. si ты увеличиваешь 3 раза по 2, после чего si возвращаешь в 0, а bx увеличиваешь лишь на 4. Т.е. пишешь в то место, которое было заполнено на предыдущем проходе. У тебя какие размеры массива? Обычно их указывают как именованную константу в дальнейшем уже прибавляют к регистру константу по имени, а не конкретное число. Так проще и отлаживать и изменять программу, если в дальнейшем потребуется.
18192123
Цитата(andriano @ 17.05.2008 18:30) *

1. Вместо "не работает" хотелось бы узнать конкретные симптомы, по которым ты определяешь отсутствие работоспособности. Тем более, что у меня сейчас нет ни одного установленного Ассемблера, следовательно, проверить никак не могу - могу лишь полагаться на твои слова.

2. push/pop принято помещать внутри процедуры. Т.е. те регистры, которые процедура портит, она и должна сохранять, а вызывающая программа об этом ничего знать не обязана.

3. si ты увеличиваешь 3 раза по 2, после чего si возвращаешь в 0, а bx увеличиваешь лишь на 4. Т.е. пишешь в то место, которое было заполнено на предыдущем проходе. У тебя какие размеры массива? Обычно их указывают как именованную константу в дальнейшем уже прибавляют к регистру константу по имени, а не конкретное число. Так проще и отлаживать и изменять программу, если в дальнейшем потребуется.

1. курсорчик мигает на одном и том же месте (начало 15-й строчки), ничего не выводится, предусмотренный выход по нажатию кнопки не работает
2. спасибо, учту
3. у меня матрица 3 на 3, соответственно 2 цикла, но bx действительно изменяется на 4 (типа переход на следующую строку.. ) и кажется с 4-кой я ошиблась..
andriano
Программы целиком на ассемблере писал лет 10-15 назад, так что сейчас уже не вспомню, что какое прерывание делает.
Кроме того, непривычный синтаксис самого ассемблера. В свое время пользовался MASM.
У тебя программа начинатся с begin?
Как она знает, что начинать надо именно отсюда? Эо где-то прописывается?
Что делает первый цикл в 10 повторений? 10 раз подряд заполняет матрицу?
18192123
Цитата(andriano @ 17.05.2008 21:07) *

У тебя программа начинатся с begin?
Как она знает, что начинать надо именно отсюда? Эо где-то прописывается?
Что делает первый цикл в 10 повторений? 10 раз подряд заполняет матрицу?

Да, выполнение программы начинается с begin. А узнаёт, т.к в самом конце прописываем end begin.
Да, 10 раз производится заполнение и вывод матрицы, потом вызывается макрокоманда задержки dely, далее курсор переводится в начало строки.
andriano
Ты располагаешь какими-либо средствами трассировки программы?
Если "да", попытайся выполнить пошагово, если "нет", то замени перевод курсора в начало строки его переводом на следующую строку. В общем, ошибку надо как-то локализовывать, а просмотр текста глазками - не самый эффективный путь.
18192123
Цитата(andriano @ 17.05.2008 23:30) *

если "нет", то замени перевод курсора в начало строки его переводом на следующую строку.

так и сделала..курсор ни разу не попал на следующую строку..думаю, ошибка где-то в процедуре matr (даже до вывода сформированной матрицы)..
18192123
Появился ещё один вариант генерации..но снова неудачный..Объясните мне пожалуста, как организовать генерацию чисел?!


dely macro time; (1)
local zd,c1,cikl,ii,ii1
push cx
push bx; (4)
push bp; (5)
push ax; (6)
push dx; (7)
mov cx,time
zd: push cx; (9)
mov bp,0;(10)
mov bx,1;(11)

cikl:
inc BP;(12)
mov ah,00h;(13)
int 1Ah;(14)
cmp BP,1;(15)
je ii
jmp ii1
ii: add bx,dx
ii1: ; (19)
cmp bx,dx
jne cikl
pop cx
loop zd;(23)
pop cx;(24)
pop bx;(25)
pop bp;(26)
pop ax;(27)
pop dx;(28)
endm;(29)

assume CS: code, DS: data
code segment
randomize proc
mov ah,2Ch
int 21h
mov Rand1,ax
mov Rand2,dx

randomize endp

random proc
mov ax,Rand1
mov bx,Rand2
mov cx,ax
mul RandA ; RandA - любое число
shl cx,1
shl cx,1
shl cx,1
add ch,cl
add dx,cx
add dx,bx
shl bx,1
shl bx,1
add dx,bx
add dh,bl
mov cl,5
shl bx,cl
add dh,bl
add ax,1
adc dx,0
mov Rand1,ax
mov Rand2,dx
mov bx,sp
mov cx,dx
mul word ptr ss:[bx+4]
mov ax,cx
mov cx,dx
mul word ptr ss:[bx+4]
add ax,cx
adc dx,0
mov ax,dx

random endp

matr proc
mov cx,3
mov si,0
mov bx,0

call randomize

external:
push cx
mov cx,3
mov si,0

iternal:

push cx
push bx
rand:
call random
;call randomize
cmp ax,30h ; число не менее
jl rand
cmp ax,39h ; число не более
jg rand

pop bx
pop cx


mov array[bx][si],ax
add si,2
loop iternal
pop cx
add bx,6
loop external

mov cx,3
mov si,0
mov bx,0
exshow:
push cx
mov cx,3
mov si,0
ishow:
mov ah,02h
mov dx,array[bx][si]
add dl,30h
int 21h
add si,2
loop ishow
lea dx,nl ;переход на новую строку
pop cx
add bx,6
loop exshow
ret
matr endp

begin:

mov AX, data
mov DS, AX

miganie:
push cx
call matr
dely 18
mov ah,02h ;сдвижка курсора обратно в начало строки
mov bh,00
mov dh,15
mov dl,0
int 10h
mov ah,06h
mov dl,0ffh
int 21h
cmp al,44h
jne miganie
;mov AH,2Ch
;int 21h
;mov AH,02h
; CH - час, CL - мин, DH - сек, DL - 1/100 сек
;int 21h
exit:
mov ax,4c00h
int 21h

code ends

data segment
array dw 3 dup(3 dup(0))
i db 0
nl db 13,10,'$'
Rand1 dw 20
Rand2 dw 10
RandA dw 38
;line db 15
data ends

stk segment stack
dw 128
stk ends

end begin



viagra versus levitra versus cia
Urologia Priligy
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.