Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Программирование и базы данных (http://forum.oszone.net/forumdisplay.php?f=21)
-   -   [решено] реализовать вычисление массива: |S(Ai + Bi)| * X + X^2 , i = 0...3 (http://forum.oszone.net/showthread.php?t=206516)

Gooch 09-05-2011 19:49 1673234

[решено] реализовать вычисление массива: |S(Ai + Bi)| * X + X^2 , i = 0...3
 
Всем привет, есть задание реализовать вычисление массива: |S(Ai + Bi)| * X + X^2 , i = 0...3

У меня есть решение, объясните пожалуйста часть кода.

Код:

int a[3];
int b[3];

int my_c(int x)
{
int pos,i;
pos=0;
int sum=0;
for(i=0;i<3;i++)
{
    pos=i;
    {
      sum= sum+(a[pos]+ b[i]);
      pos++;
    }
}
sum=(abs(sum));
sum=(sum*x);
int pow=0;
    pow=x*x;

    sum= sum+pow;
return sum;
}


lxa85 09-05-2011 23:10 1673348

Gooch, у тебя код и реализует формулу. Прям линейно по действиям. Сначала находит сумму, затем ее умножает на x, затем x квадрат заменяется через обычное умножение и плюсуется к текущей сумме.

Gooch 10-05-2011 15:55 1673754

до меня не доходит заполнение массива :(

int pos,i; \\ ввели целочисленные переменные
pos=0; \\ сказали что pos будет 0
int sum=0; \\ почему так? я так понимаю выше мы тоже самое могли сделать? типа int i; int pos=0; или всё таки есть разница?

ну вот че то понять не могу заполнение массива:

for(i=0;i<3;i++) \\ заполняем массив 3 числами, что означает i++? ну и дальше вообще не доходит :(
{
pos=i;
{
sum= sum+(a[pos]+ b[i]);
pos++;
}
}

Hector 10-05-2011 16:17 1673765

Цитата:

Цитата Gooch
int sum=0; \\ почему так? я так понимаю выше мы тоже самое могли сделать? типа int i; int pos=0; или всё таки есть разница? »

так решил автор спроси, где брал исходник почему разницы нет
Цитата:

Цитата Gooch
что означает i++? »

увеличение переменной i на 1, т. е. i+1

Gooch 10-05-2011 16:23 1673773

Цитата:

Цитата Hector
увеличение переменной i на 1, т. е. i+1 »

то есть он будет прибавлять 1 пока i не станет равна 3?

а что насчет дальше? зачем pos прировняли к i? (a[pos]+ b[i]) что означает данное вырожение?

Hector 10-05-2011 16:28 1673775

в данном случае, оно будет прибавлять пока i будет строго меньше 3
Цитата:

Цитата Gooch
что насчет дальше? зачем pos прировняли к i? (a[pos]+ b[i]) что означает данное вырожение? »

откровенно говоря, здесь мне логика не понятна, думаю можно было бы обойтись так
Код:

for(i=0;i<3;i++)
      sum= sum+(a[pos]+ b[i]);

потому что в теле цикла pos=i, а зачем его увеличивать в конце, если потом все равно pos получает значение i непонятною
здесь реализуется вычисление S(Ai + Bi)

Gooch 10-05-2011 17:02 1673803

Цитата:

Цитата Hector
потому что в теле цикла pos=i, а зачем его увеличивать в конце, если потом все равно pos получает значение i непонятною »

то есть pos=i оставляем,а pos++ убираем?

Цитата:

Цитата Hector
здесь реализуется вычисление S(Ai + Bi) »

щас мозг взорвется...я хочу понять принцип работы этой формулы. Дальше есть следующий код:

Код:

int my_assembler(int x)
{
          int sum=0;

          __asm
          {
          MOV esi,0
          MOV ecx,0

          //вычисление суммы массивов
          cycle_i:

          MOV eax,a[esi]
          MOV edx,b[esi]
          ADD esi,4

          //сумма массивов
          ADD sum, eax
          ADD sum, edx
          INC ecx //увеличивает
          CMP ecx, 3 //сравнивает
          JB cycle_i //для беззнаковых чисел
         
          //модуль
          abso: neg sum
          JS abso //переход, если установлен бит знака
          //умножаем sum на x
          MOV eax,sum
          MOV ecx,x
          IMUL ecx
          MOV sum,eax
                   
          //вычисляем квадрат x
          MOV eax,x
          MOV ecx,x
          IMUL ecx

          //складываем с суммой квадрат x
          ADD sum,eax
}

return sum;
}
void main()
{
    int  i;
    system("title Вычисление значения выражения");
        for(int i=0; i<3; i++)
    {
          printf("Vvedite element A: ");
          scanf("%d",&a[i]);
    }
    for(int i=0; i<3; i++)
    {
          printf("Vvedite element B: ");
          scanf("%d",&b[i]);
    }
    int x=0;
          printf("Vvedite chislo X: ");
          scanf("%d",&x);
         
          //printf("C++=%i\n",my_c(x));
          printf("Otvet=%i\n",my_assembler(x));
system("pause");
}

задание впринципе решить формулу ассемблерной вставкой, но как я щас понял в этом примере всё решено на С? или что делает код на С? не понимаю :(

Beyound 10-05-2011 19:12 1673884

Цитата:

Цитата Gooch
__asm
{
MOV esi,0
MOV ecx,0
//вычисление суммы массивов
cycle_i:
MOV eax,a[esi]
MOV edx,b[esi]
ADD esi,4
//сумма массивов
ADD sum, eax
ADD sum, edx
INC ecx //увеличивает
CMP ecx, 3 //сравнивает
JB cycle_i //для беззнаковых чисел
//модуль
abso: neg sum
JS abso //переход, если установлен бит знака
//умножаем sum на x
MOV eax,sum
MOV ecx,x
IMUL ecx
MOV sum,eax
//вычисляем квадрат x
MOV eax,x
MOV ecx,x
IMUL ecx
//складываем с суммой квадрат x
ADD sum,eax
} »

вот это называется ассемблеровской вставкой. она так называется потому что язык программы си, но автор решил что часть кода будет написана на другом допустимом языке - "asm"-е, т.е. ассемблере, о чем явно указывает первая строчка кода в цитате. Компилятор си это допускает.
начнем с того что если ты не знаешь ассемблера смысла объяснять каждую строчку особого нет, описание команд ты можешь посмотреть и в инете, тут никакого секрета нет, коментари в коде подробные.
а вот все что не попало в цитату - это уже чистый си. почему это возможно? все очень просто.
любой компьютер ни коем образом не знает что такое си, бэйсики, и даже ассемблер. он знает только машинный код (готовый exe если понятнее). для того чтобы из языка программирования сделать машинный код (компилировать программу) придумали специальные программы - компиляторы. Они то как раз и знают как из строчек кода на языке сделать машинный код. Естественно компилятор понимает только свой конкретный язык программирования, но ассемблер (любой) настолько приближен к машинному коду что все компиляторы тем или иным образом его знают и могут компилировать вместе со своим родным языком.

Gooch 10-05-2011 19:24 1673890

вообщем си меня не интересует, что такое компилятор и что такое вставка асемблереная я вкурсе. моя задача решить задание по предмету ассемблер при помощи языка высшего уровня. данная задача это пример решения моего личного задания. хочу понять её решение для того чтоб написать решение своей. в коде сверху, как я уже разобрался, первое решение на языке С, второе на Ассемблере. На данный момент читаю как организовывать массивы в асм.

Beyound 10-05-2011 20:02 1673917

в данной примере массив не организован на ассемблере, я правда в теле мейна не вижу объявления этих массивов но оно там быть должно.
работа с массивом такова что а и b это начальные адреса (ты это знаешь), и они смещаются на регистр esi как и в си - a[esi] и в цикле этот регистр увеличивается на 4 потому что int обычно занимает 4 байта (но ты же это знаешь).
цикл организован ссылкой которая в ассемблере пишется так - some_name: . Цикл первый до тех пор пока ecx не станет больше (JB) 3 , в теле цикла каждый раз идет INC ecx. Вот и вся работа с массивами, которой собственно и нет.

а вообще в ассемблере массив выделяется так (как пример) - mas db 10 dup (?), где mas - имя массива, db - размер элемента массива, 10 - количество элементов, 0 - чем заполнить.

Gooch 10-05-2011 20:45 1673932

Цитата:

Цитата Beyound
в данной примере массив не организован на ассемблере »

действительно, по заданию его обозначали на С и вводятся значения с клавиатуры. Кусок кода int my_c(int x)
можно выкинуть.

Цитата:

Цитата Beyound
а вообще в ассемблере массив выделяется так (как пример) - mas db 10 dup (?), где mas - имя массива, db - размер элемента массива, 10 - количество элементов, 0 - чем заполнить. »

вот только такие примеры к сожалению я и нахожу в различных учебниках :(

Beyound огромное спасибо, немного помог мне, до меня что то доходить начало. Был бы очень рад если бы дальше мне помог :)

Цитата:

Цитата Beyound
цикл организован ссылкой которая в ассемблере пишется так - some_name: . Цикл первый до тех пор пока ecx не станет больше (JB) 3 , в теле цикла каждый раз идет INC ecx. »

вот что я понял:
Код:

          cycle_i:              \\ : поставили метку начала цикла
          MOV eax,a[esi]  \\адрес первого элемента массива а
          MOV edx,b[esi]  \\адрес первого элемента массива b
          ADD esi,4          \\следующий элемент с шагом 4 (т.к. регистр esi имеет размер 4 байта)

          ADD sum, eax    \\ прибаляем к sum содержимое eax
          ADD sum, edx    \\ прибавляем к sum содержимое edx
          INC ecx              \\ увиличение ecx на 1
          CMP ecx, 3          \\ проверяет равен ли ecx 3
          JB cycle_i            \\если ecx < 3 то перейти в начало цикла

Beyound огромнейшее спасибо! очень помог. как заполнять массив я наконец то понял. Щас буду пробывать в своём задании!

Beyound 10-05-2011 21:13 1673942

у тебя есть пару недочетов

1. CMP ecx, 3 \\ сравниваем ecx 3, итог сравнения эта коменда нам не показывает а хранит его в регистре
2. JB cycle_i \\ команда раскладывается так J - "если сравнение выдало результат" B (bigger) "больше" то переходм по ссылке cycle_i
3.ADD esi,4 \\прибавляем к текущему значению региста esi число 4. 4 потому что все считается в байтах, а нам нужно сместиться на int который занимает 4 байта (32 бита) - это стандартно.

Gooch 10-05-2011 21:23 1673949

Beyound, а вот моё задание: |S(Ai)*X+S(Bi)*Y|

Код:

int sum1=0;
int sum2=0;

___asm
{
mov esi,0
mov ecx,0

cycle_AB:
MOV eax,A[esi]
MOV edx,B[esi]
ADD esi,4
ADD sum1,eax
ADD sum2,edx
INC ecx
CMP ecx,3
JB cycle_AB
MOV eax,sum1
MOV ecx,X
iMUL ecx
MOV sum1,eax
MOV eax,sum2
MOV ecx,Y
iMUL ecx
ADD sum,eax

modyl:
NEG sum
JS modul
}

Правильно ли я его сделал?

Beyound 10-05-2011 21:37 1673958

если чесно я немного непонимаю как тут операция с массивом идет, не хватает впереди выражения математического знака... или даже двух) вполне возможно что твой вариант верен) по крайней мере ошибок в нем нет

Gooch 10-05-2011 21:56 1673969

Цитата:

Цитата Beyound
давай так - я тебе напишу логику, а ты сбацаешь на ассемблере. »

ошибку понял :) Я сначала так и хотел сделать, но потом почему то подумал, а почему бы не сделать подругому...

Код:

int sum1=0;
int sum2=0;

___asm
{
mov esi,0
mov ecx,0

cycle_A:
MOV eax,A[esi]
ADD esi,4
ADD sum1,eax
INC ecx
CMP ecx,3
JB cycle_A
MOV eax,sum1
MOV ecx,X
iMUL ecx
MOV sum1,eax

mov esi,0
mov ecx,0
cycle_B:
MOV eax,B[esi]
ADD esi,4
ADD sum2,eax
INC ecx
CMP ecx,3
JB cycle_B
MOV eax,sum2
MOV ecx,Y
iMUL ecx
ADD sum1,eax
modul:
NEG sum1
JS modul
}

Цитата:

Цитата Beyound
если чесно я немного непонимаю как тут операция с массивом идет, не хватает впереди выражения математического знака... или даже двух) вполне возможно что твой вариант верен) по крайней мере ошибок в нем нет »

ну вот теперь 2 варианта :) я в первом варианте просто в одном цикле заполнил оба массива без сложения их с друг другом. А так по-моему тоже самое.
Объясни пожалуйста а когда я закончил асемблерную вставку и пишу

return

к чему возврат мне надо указывать? к переменной в которой содержится ответ?

Beyound 10-05-2011 22:10 1673982

ага

Gooch 10-05-2011 22:20 1673986

щас проверил и всё замечательно работает! Огромное спасибо!


Время: 01:42.

Время: 01:42.
© OSzone.net 2001-