Консультация № 147111
13.10.2008, 22:10
0.00 руб.
0 10 1
Здравствуйте! Нужно написать программу на ассемблере через Паскаль. Т.е ввод и вывод данных осуществить на Паскале, а код программы на ассемблере, с комментариями.

В массиве Z[1..n] определить сумму нечетных чисел от последнего нулевого значения до Z[n] и среднее арифметическое четных чисел до последнего нуля. Заменить этот последний нуль на среднее арифметическое.

Заранее благодарен вам!

Обсуждение

Неизвестный
15.10.2008, 11:16
общий
А элементами массива что является? Целые числа? Тогда среднее арифметическое округлять?
Проблема в своеобразном представлении чисел REAL у Паскаля. Легче взять EXTENDED или DOUBLE - и все выполнять в сопроцессоре. В том числе и определение нуля. У Вас с объяснением такой работы проблем не возникнет?
Неизвестный
15.10.2008, 12:05
общий
uses crt;
const n=10;
type tm=array[1..n] of integer;

var
a:tm;
i,n1,summa,sredn:integer;

Begin
clrscr;
randomize;
n1:=n;
for i:=1 to n1 do
begin
a[i]:=-5+random(10);
write(a[i]:4);
end;
writeln;

asm

<код ассемблера>

end;

if (summa=0) and (sredn=0) then writeln('Нуля нет или он является последним элементом массива') else
writeln(' сумма равна ',summa,' среднее арифметическое ',sredn);
writeln;
for i:=1 to n1 do
write(a[i]:4);
readkey;
END.


Примерно так должно быть..
Неизвестный
15.10.2008, 12:06
общий
это ответ
Здравствуйте, Denton87!
Не отвечаете, поэтому в приложении вариант с целыми числами
(переставил местами ответы, но это, видимо не важно )
Ежели что - пишите в минифоруме

Приложение:
CONST
n = 15;
m1 = 4;
m2 = n div 2;
VAR
Z: array[1..n] of Integer;
last_zerou, i: Integer;
summ1, summ2: Integer;
BEGIN
WriteLn('Заполнение массива');
last_zerou:=0;
for i := 1 to n do
{Write('Введите элемент ',i,: ;); ReadLn(Z[i];}
Z[i] := (i - m2)*(i - m2) - m1;
for i:=1 to n do Write(Z[i]:4); WriteLn;
WriteLn('Поиск последнего нулевого значения');
asm
lea si, Z
cld
mov cx, n
@@1:
lodsw
or ax, ax
jnz @@2
mov ax, n
sub ax, cx
inc ax
mov last_zerou, ax
@@2:
LOOP @@1
end;
if last_zerou = 0 then
WriteLn('В массиве нет нулевых значений')
else
begin
WriteLn('Индекс последнего нулевого элемента: ',last_zerou);
asm
xor ax, ax
mov summ1, ax
lea si, Z
mov dx, last_zerou
mov cx, 1
cld
@@1:
lodsw
test ax, 1
jnz @@2 {не установлен нулевой бит - четное}
add summ1, ax
@@2:
inc cx
cmp cx, dx
jb @@1
@@3:
end;
WriteLn('Сумма четных "до": ', summ1);
asm
mov bx, last_zerou
cmp bx, 1
jbe @@1 {один элемент "до" - он и есть среднее}
dec bx {сам последний в счет не входит}
mov ax, summ1
xor dx, dx
idiv bx
mov summ1, ax
@@1:
end;
WriteLn('Среднее арифметическое элементов "до": ', summ1);
asm
xor ax, ax
mov summ2, ax

lea si, Z
mov ax, last_zerou
shl ax, 1 {*2 т.к. каждый элемент занимает 2 байта}
add si, ax {теперь DS:SI указывает на последний нуль}
mov dx, last_zerou
mov cx, n
  cld
@@1:
cmp dx, cx
jae @@3
lodsw
test ax, 1
jz @@2
add summ2, ax
@@2:
inc dx
jmp @@1
@@3:
end;
WriteLn('Сумма нечетных элементов "после": ', summ2);
end;
END.
Неизвестный
15.10.2008, 12:09
общий
Прочитал Ваш ответ после отправки (почему-то мой браузер не обновил сообщение, хотя просил его об этом) - посмотрите мой вариант
Взял неслучайные числа для того, чтобы обязательно было два нуля
Неизвестный
15.10.2008, 12:53
общий
Всё же лучше рандом, т.к требуют рандом. Команды же loadsw на данном этапе лучше не использовать. И можно, плиз, комментарии к логическим операциям or, test, xor
Неизвестный
17.10.2008, 10:25
общий
Вот изменённое с комментариями:
Код:
 CONST
n = 15;
m1 = 4; {Беру маленькое число, чтобы была высокая вероятность появления нулей}
m2 = m1 div 2;
VAR
Z: array[1..n] of Integer;
last_zerou, i: Integer;
summ1, summ2: Integer;
BEGIN
WriteLn('Заполнение массива');
last_zerou:=0;
Randomize;
for i := 1 to n do
{Write('Введите элемент ',i,: ;); ReadLn(Z[i];}
Z[i] := random(m1) - m2; {(i - m2)*(i - m2) - m1;}
for i:=1 to n do Write(Z[i]:4); WriteLn;
WriteLn('Поиск последнего нулевого значения');
asm
lea si, Z
cld
mov cx, n
@@1:
mov ax, [si] {эти две строчки делаю то же, что и LODSW}
add si, 2
or ax, ax {Число не изменяется, только устанавливаются флаги
нас интересуют два
ZF - флаг нуля, SF - флаг знака}
jnz @@2 {переход, если не ноль}
mov ax, n
sub ax, cx
inc ax
mov last_zerou, ax
@@2:
LOOP @@1
end;
if last_zerou = 0 then
WriteLn('В массиве нет нулевых значений')
else
begin
WriteLn('Индекс последнего нулевого элемента: ',last_zerou);
asm
xor ax, ax {побитовая инструкция:
сравниваются биты приемника (первый операнд)
и источника (второй операнд).
Если биты равны, то соответствующий
бит приемника устанавливаются в ноль.
Самый быстрый способ обнулить регистр}
mov summ1, ax
lea si, Z
mov dx, last_zerou
mov cx, 1
@@1:
mov ax, [si]
add si, 2
test ax, 1 {Логическое сравнение. Вычисляется побитовое "И"
Результат нигде не сохраняется, только устанавливаются
флаги
В данном случае источник = 1. Установлен только
нулевой бит (младший, счет с нуля)
Так что результат не равен нулю только в том
случае, когда в применике установлен этот
младший бит. Поскольку "цена" всех остальных бит
четная, то число нечетное, если установлен младший бит}
jnz @@2 {Переход, если не установлен нулевой бит - четное}
add summ1, ax
@@2:
inc cx
cmp cx, dx
jb @@1
@@3:
end;
WriteLn('Сумма четных "до": ', summ1);
asm
mov bx, last_zerou
cmp bx, 1
jbe @@2 {один элемент "до" - он и есть среднее}
dec bx {сам последний в счет не входит}
mov ax, summ1
xor dx, dx
or ax, ax
jns @@1
mov dx, 0FFFFh {Выполняем знаковое деление DX:AX на BX.
если число отрицательное, то DX = FFFF
Легче всего убедиться в этом, если пропустите
эту операцию, а сумма будет отрицательной}
@@1:
idiv bx
mov summ1, ax
@@2:
end;
WriteLn('Среднее арифметическое элементов "до": ', summ1);
asm
xor ax, ax
mov summ2, ax

lea si, Z
mov ax, last_zerou
shl ax, 1 {*2 т.к. каждый элемент занимает 2 байта}
add si, ax {теперь DS:SI указывает на последний нуль}
mov dx, last_zerou
mov cx, n
  cld
@@1:
cmp dx, cx
jae @@3
mov ax, [si]
add si, 2
test ax, 1
jz @@2
add summ2, ax
@@2:
inc dx
jmp @@1
@@3:
end;
WriteLn('Сумма нечетных элементов "после": ', summ2);
end;
END.
Неизвестный
17.10.2008, 14:26
общий
Спасибо) тока замену последнего нуля на среднее арифметическое не нашел)))) ну эт мелочи впрочем=)) Всё равно, большое СПАСИБО!
Неизвестный
17.10.2008, 14:54
общий
Забыл!!! Через 5 минут пришлю
Неизвестный
17.10.2008, 15:04
общий
Вот кусочек, вставь перед предпоследним end, то есть последним " end; "
Код:
     {Замена последнего нуля средним}
asm
lea si, Z
mov ax, last_zerou
dec ax
shl ax, 1
add si, ax
mov ax, summ1
mov [si], ax
end;
for i:=1 to n do Write(Z[i]:4); WriteLn;
Неизвестный
17.10.2008, 19:51
общий
аха, спасибо=)
Форма ответа