Консультация № 180414
22.10.2010, 18:49
0.00 руб.
0 10 1
Дорогие эксперты, помогите.

Определить, есть ли в массиве L[1..N] значение, равное половине суммы минимального и максимального чисел (т.е. (min +max) / 2) и вывести номер первого значения, если такое число есть, иначе сообщить, что таких значений не найдено.

Приложение:
uses crt;
const n=10;
var a:array[1..n] of integer;
i,p:integer;
begin
clrscr;
randomize;
writeln('ishodnii');
for i:=1 to n do
begin
a[i]:=random(20)-10;
write(a[i],' ');
end;
asm
@1:lea si,H
mov cx, n-1
mov bx,si
mov di,si
mov ax,[si]
mov dx,[si]
@2:add si,2
cmp ax,[si]
jge @3
mov ax,[si]
mov bx,[si]
@3:cmp dx,[si]
jle @4
mov dx,[si]
mov di,si
@4:loop @2
mov max,ax
mov min,dx






end;
writeln;
for i:=1 to n do
writeln('min',min);
writeln('max',max);
writeln('sum/2' );
writeln('nomer );
readkey;
end.

Обсуждение

давно
Старший Модератор
31795
6196
22.10.2010, 22:40
общий
это ответ
Здравствуйте, Посетитель - 340752!

Смотрите приложение.
По программе:
1) из-за небольшого диапозона используемых значений: random(20)-10, в ассемблерном коде отсутствует работа с флагами CF , OF и SF;
2) использована команда целочисельного деления со знаком IDIV, делимое должно находится в регистрах DX:AX, т.к. до этого работали только с 16-ти битными регистрами, то значение регистра DX заполняется старшим знаковым битом регистра АХ (трюк №1);
3) индексация элементов массива в ассемблере идет с нуля, в ЯВУ может начинатся с любого номера. С массивом работаем с помощью адресации по базе с индексированием,а выводом значений занимается компилятор PASCAL. Поэтому корректируется значения SI(индекс) и BX(база). При вычислении адреса в памяти [ bx + si ], будет получено нужное значение адреса(трюк №2) текущего элемента и соответсвующий ему, порядковый номер. Если выводится ноль, то такого элемента нет в массиве.
вопросы по программе задавайте в мини-форум.
Удачи!

Приложение:
uses crt;
const n=10;
var l:array[1..n] of integer;
i,num,max,min,sum,s2m:integer;
begin
clrscr;
randomize;
{выводим нумерацию}
write('number:');
for i:=1 to n do write(i:4);
writeln;
{создаем и выводим массив}
write('matrix:');
for i:=1 to n do
begin
l[i]:=random(20)-10;
write(l[i]:4);
end;
writeln;
{задание на ассемблере начинаем}
asm
{настраиваемся на массив}
lea si,l
mov cx, n
mov di,si
mov bx,si
{загружаем преверяемое значение}
@@01:
mov ax,[si]
{проверяем с минимальным, если да то запоминаем его индекс}
cmp ax,[di]
jge @@02
mov di,si
{проверяем с максимальным, если да то запоминаем его индекс}
@@02:
cmp ax,[bx]
jle @@03
mov bx,si
{в цикле переходим к следующему значению}
@@03:
add si,2
loop @@01
{запоминаем значения максимального и минимального элемента}
mov ax,[bx]
mov max,ax
mov bx,[di]
mov min,bx
{суммируем и запоминаем}
add ax,bx
mov sum,ax
{трюк №1}
push ax
shl ax,1
pop ax
rcr dx,1
mov cl,16
sar dx,cl
{делим на два, запоминаем результат}
mov bx,2
idiv bx
mov s2m,ax
{готовимся к поиску совпадения}
mov cx,n
lea bx,l
{трюк №2}
mov si,2
sub bx,2
{поиск совпадения в цикле, нашли выходим из цикла}
@@04: cmp ax,[bx+si]
jz @@05
add si,2
loop @@04
{есди попали сюда, то совпадений нет}
xor si,si
@@05:
shr si,1
mov num,si
end;
{задание на ассемблере закончено}
{выводим результат}
writeln('min',min:5);
writeln('max',max:5);
writeln('sum',sum:5);
writeln('div',s2m:5);
writeln('num',num:5);
readkey;
end.
5
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

давно
Старший Модератор
31795
6196
22.10.2010, 22:52
общий
Посетитель - 340752:
Забыл добавить, оформление выводимых значений:
writeln('min',min:5);
writeln('max',max:5);
writeln('sum',sum:5);
writeln('div',s2m:5);
writeln('num',num:5);

за Вами, сделаете как Вам будет нужно.

Удачи!
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

Неизвестный
23.10.2010, 16:15
общий
Зенченко Константин Николаевич:
Спасибо огромнейшее.
а можно еще спросить, сумма, деленная на 2, выводится только как натуральное число, но она же не всегда натуральное число, бывают же и целые числа.
давно
Старший Модератор
31795
6196
23.10.2010, 19:31
общий
Посетитель - 340752:
см. пункт №2 ответа.
Цитата: Зенченко Константин Николаевич
2) использована команда целочисельного деления со знаком IDIV, делимое должно находится в регистрах DX:AX, т.к. до этого работали только с 16-ти битными регистрами, то значение регистра DX заполняется старшим знаковым битом регистра АХ (трюк №1);

Результат целый, находится в АХ, отстаток в DX, это число не может быть натуральным, см. определение:
Цитата: википедия
Отрицательные и нецелые числа натуральными числами не являются.

т.к. генерируется числа в районе 0..19, от которых отнимается 10:random(20)-10. Минимальным может быть самое отрицательное число, а максимальным, к примеру "-1". О каком натурализме тут можно говорить?

Выводится целая часть от деления, строка mov s2m,ax именно её и выводит компилятор.

Теперь почему именно так:
Цитата: 340752
a:array[1..n] of integer

т.е. работа происходит с целыми числами. Сумма двух целых чисел может быть четной или нечетной. Другими словами, если остаток от деления в DX не равен нулю, то всегда можно добавить в код if DX<>0 then write('.5');
Но сам массив есть массивом целых чисел и остаток нужно округлять, либо не учитывать, я неучитывал.
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

Неизвестный
23.10.2010, 21:53
общий


и как мне теперь поступить, чтоб 5-ка в конце была, если число нечетное будет.
давно
Старший Модератор
31795
6196
25.10.2010, 15:05
общий
Посетитель - 340752:
Уточните, что именно Вам нужно.
Учитывать нечетное число деленное попалам, т.е. остаток от деления, но тогда пропадает сам смысл вопроса, т.к. в вопросе: array of integer и проверять с целыми числами вещественные( х.5) нельзя, т.к. это различные типы.
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

Неизвестный
25.10.2010, 21:58
общий
Зенченко Константин Николаевич:
а если тогда массив задать real?
давно
Старший Модератор
31795
6196
26.10.2010, 18:35
общий
Посетитель - 340752:
Цитата: 340752
а если тогда массив задать real?

Почему бы и нет? Для начала попробуйте сами прокомментировать код между метками @@100 и @@103(сорри, код слизал у компилятора ТР , он остался без изменений):
Код:
uses crt;
const n=10;
var l:array[1..n] of real;
i_max,i_min:integer;
i:integer;
begin
clrscr;
randomize;
{выводим нумерацию}
write('number:');
for i:=1 to n do write(i:7);
writeln;
{создаем и выводим массив}
write('matrix:');
for i:=1 to n do
begin
l[i]:=20*random-10;
write(l[i]:7:3);
end;
writeln;
{задание на ассемблере начинаем}
asm
{настраиваемся на массив}
lea si,l
mov i_max,si
mov i_min,si
mov cx, n
{Цикл поиска максимального и минимальныго значений}
@@01:
{проверяем с максимальным если да то запоминаем его индекс}
push cx
push si
mov di,i_max
call @@100
pop si
pop cx
jbe @@02
mov i_max,si
jmp @@03
{процедура сравнения двух чисел REAL в PASCAL}
@@100:
{загрузка значений}
mov ax,[si]
mov bx,[si+2]
mov dx,[si+4]
mov cx,[di]
mov si,[di+2]
mov di,[di+4]
{код проверки}
push dx
xor dx,di
pop dx
jns @@101
push dx
rcl dx,1
pop dx
retn
@@101:
test dh, 80h
jz @@102
call @@102
jz @@103
cmc
retn
@@102:
cmp al,cl
jnz @@103
or al,al
jz @@103
cmp dx,di
jnz @@103
cmp bx,si
jnz @@103
cmp ah,ch
@@103:
retn
{продолжение основного цикла в паскале}
@@02:
{проверяем с минимальным, если да то запоминаем его индекс}
push cx
push si
mov di,i_min
call @@100
pop si
pop cx
jnb @@03
mov i_min,si
{в цикле переходим к следующему значению}
@@03: add si,6
loop @@01
{запоминаем i_max=максимального и
i_min=минимального элемента}
{}
lea si,l
mov bx,6
mov ax,i_max
sub ax,si
xor dx,dx
div bx
inc ax
mov i_max,ax
{}
mov ax,i_min
sub ax,si
xor dx,dx
div bx
inc ax
mov i_min,ax
end;
{задание на ассемблере закончено}
{выводим результат}
writeln('min:',l[i_min]:7:3);
writeln('max:',l[i_max]:7:3);
readkey;
end.

С двумя вещественными числами будут производится оперрации сравнения, сложения и деления. Паскаль числа типа REAL размещает в регистрах, к примеру так: Real(AX:BX:DX)+=Real(CX:SI:DI). Чтобы выполнить нужные действия в код Вашего примера нужно ещё добавить приблизительно 600 байт кода, эквивалентов следующих функций:
seg001:0584 ; [ 000001C6 BYTES: FUNCTION __RealAdd.]
seg001:074A ; [ 00000077 BYTES: FUNCTION __RealDiv.]
seg001:07C1 ; [ 00000017 BYTES: FUNCTION __RealCmp.]


Вот собственно сам вопрос, а оно Вам нужно, усложнять код настолько, чтобы потом "плавать" перед преподом?
Только ради перехода на вещественные числа. Проще обеспечить генерацию четных целых чисел.
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

Неизвестный
26.10.2010, 19:41
общий
Зенченко Константин Николаевич:
действительно, с типом real код гораздо сложней.
попробую ваш совет с генерацией четных целых чисел.
спасибо за помошь с задачей, за ваше время, потраченное на меня.
давно
Старший Модератор
31795
6196
26.10.2010, 19:46
общий
Посетитель - 340752:
2*(random(20)-10)
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

Форма ответа