Консультация № 159117
29.01.2009, 19:22
0.00 руб.
0 5 2
Здравствуйте

Пишу программу на ассемблере - заполнение массива данными

A = {ai} (i = 1..20)

a[i] = (i/5 + i/3) +50

По идее, в результате должны выдаваться значения:

50 51 51 52 52 53 53 54 54 55 55 56 56 57 58 58 59 59 60 60

Программа же выдает другие значения

0 50 50 51 51 52 53 53 53 54 55 55 56 56 56 58 58 58 59 59 61

Помогите, пожалуйста, разобраться.

Откуда взялся 0, ведь я начал с i = 1, и почему остальные значения другие?


Приложение:
MODEL small
STACK 256
.286
.data
mes db 0ah,0dh,'Massiv: ','$'
mas db 20 dup (?) ;исходный массив
i db 1
s3 db 3
ii db '1'
s4 db 5
s50 db 50
.code




main:
xor ax,ax
mov ax,@data
mov ds,ax
xor ax,ax ;обнуление ax
mov cx,20 ;значение счетчика цикла в cx
mov si,1 ;индекс начального элемента в cx
mov dl, 1 ;номер элемента (это наша i)
go:

xor ax,ax ;цикл инициализации
mov al, dl ;i в al

div s4 ;делим i на 5

mov mas[si],al ;запись в массив i

xor ax,ax


mov al, dl

div s3

add al, mas[si]

add al, s50

mov mas[si],al



inc i ;инкремент i
inc dl
inc si ;продвижение к следующему

loop go



;вывод на экран получившегося массива
mov cx,20
mov si,1
mov ah,09h
lea dx,mes
int 21h
mov cx,21
mov si,offset mas

show:
lodsb
call outNumber


loop show
exit:
mov ax,4c00h ;стандартный выход
int 21h

outNumber: pusha
and ax,0ffh

;десятичная система
mov bx,10

;счетчик цифр в числе
xor cx,cx

;делим число на 10
isDiv: xor dx,dx
div bx

;запоминаем в стеке остаток от деления
push dx
;считаем количество запоминаемых символов
inc cx
;продолжаем пока АХ не равно 0
or ax,ax
jnz isDiv
;выводим из стека цифры в нужном порядке
isOutNum: pop ax
;перводим в цифру в символ
or al,30h
;выводим в режиме телетайпа
;эта функция аналогична mov ah,02 - int 21h
;только места меньше занимает
int 29h
;повторяем вывод в цикле
loop isOutNum
mov al,20h
int 29h
popa
ret



end main ;конец программы


Обсуждение

Неизвестный
29.01.2009, 21:42
общий
это ответ
Здравствуйте, Койбаев Олег Артурович!
массив нумеруется с 0
mov si,1 ;индекс начального элемента в cx
div это целочисленное деление
Неизвестный
29.01.2009, 22:42
общий
Я понимаю, что div - это целочисленное деление. В al записывается целое частное, а в ah - остаток. Потом я al перекидываю в массив. Вот только частное записывается почему-то неправильно.

Например, при i = 2 результат должен быть 51,06666667. Соответственно программа должна выводить 51, а она выводит 50
давно
Посетитель
7438
7205
29.01.2009, 23:03
общий
это ответ
Здравствуйте, Койбаев Олег Артурович!
Как верно заметил Airyashov, массив нумеруется с 0, а не с 1.
Кроме того, Вы его заполняете с 1 элемента, а выводите с нулевого, вот этот непроинициализированный элемент равный 0,
мы и видим. Это первое.
Второе. "Другие значения" - это результат целочисленного деления с отбрасыванием остатка.
Но...нужный результат можно достичь! Только для этого надо немного изменить формулу (этим мы уменьшим погрешность!)
i/5 +i/3 = (8*i)/15 = (i<<3)/15 В последнем выражении умножение на 8 я заменил на сдвиг влево на 3 бита.
Программа в приложении, реализующая эту формулу, выводит нужные числа...

Приложение:
MODEL small
STACK 256
.286
.data
mes db 0ah,0dh,'Massiv: ','$'
mas db 20 dup (?) ;исходный массив
s15 db 15
s50 db 50
.code

main:
mov ax,@data
mov ds,ax
mov cx,20 ;значение счетчика цикла в cx
xor si,si ;индекс начального элемента,одновременно i-1
go:
lea ax,[si+1] ;ax=i
shl ax,3 ;ax=8*i
div s15 ;делим 8*i/15 = i/5 + i/3
add al,s50 ;al = i/5 + i/3 + 50
mov mas[si],al ;запись в массив

inc si ;продвижение к следующему
loop go



;вывод на экран получившегося массива
mov ah,09h
lea dx,mes
int 21h
mov cx,20
mov si,offset mas
show:
lodsb
call outNumber
loop show
exit:
mov ax,4c00h ;стандартный выход
int 21h

outNumber: pusha
and ax,0ffh

;десятичная система
mov bx,10

;счетчик цифр в числе
xor cx,cx

;делим число на 10
isDiv: xor dx,dx
div bx

;запоминаем в стеке остаток от деления
push dx
;считаем количество запоминаемых символов
inc cx
;продолжаем пока АХ не равно 0
or ax,ax
jnz isDiv
;выводим из стека цифры в нужном порядке
isOutNum: pop ax
;перводим в цифру в символ
or al,30h
;выводим в режиме телетайпа
;эта функция аналогична mov ah,02 - int 21h
;только места меньше занимает
int 29h
;повторяем вывод в цикле
loop isOutNum
mov al,20h
int 29h
popa
ret



end main ;конец программы

Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
Неизвестный
29.01.2009, 23:12
общий
вы отбрасывайте остаток и никак его не учитывайте
2/5=0
2/3=0
0+0+50=50
давно
Посетитель
7438
7205
29.01.2009, 23:27
общий
Добавлю:
А (2*(3+5))/(3*5) = (2*8)/15 = 16/15 даст 1 !!!
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
Форма ответа