Пример. Циклическая адресация

Пример. Работа с целыми числами

Пример. Управление памятью

typedef struct tagABC typedef struct tagABC

{ {

int a; long b;

long b; int a;

int c; int c;

} ABC; } ABC;

 

extern int Xflag; extern int Xflag;

 

int function(void) int function(void)

{ {

x = Xflag ? Xflag & 0xFFFE : Lflag; int Lflag = Xflag;

return x; x = Lflag ? Lflag & 0xFFFE : lflag;

} /* длинный код */ return x;

} /* короткий код */

Пояснение.

В данном примере мы сравнили два варианта, которые показывают: как правильно управлять памятью. Основной момент заключается в том, что необходимо выравнивать по двойному слову, иначе за один цикл тип long не сможет быть прочитан. Изначально размещается long, а затем два целых числа. Поэтому в первом случае распределение памяти неправильное. Второй пример: мы имеем переменную на внешнем уровне. Но если ее интенсивно использовать – это приведет к очень длинному коду, потому что будет использован метод адресации через регистры. А если сначала определить внутреннюю переменную и присвоить ей внешнее значение, то дальше доступ к внутренней переменной будет происходить через SP(stack pointer). Что занимает гораздо меньше времени и места. Вывод - лучше работать с локальными, а не с глобальными переменными.

long mult(int sw, int a, int b, long* res)

{

long result;

switch(sw)

{

case 0: /* не корректно */

result = a * b; *res = a + b;

break;

case 1: /* не корректно */

result = (long)(a * b); *res = (long)(a + b);

break;

case 2: /* корректно */

result = (long)a * b; *res = (long)a + b;

break;

default: /* корректно */

result = (long)a * (long)b; *res = (long)a + (long)b;

}

return result;

}

Пояснение.

Рассмотрим первую часть программы (case 0, case 1), которая некорректно производит вычисления. Предположим, что необходимо получить результат типа long (32-битный). В данном примере, вследствие перемножения и сложения двух целый чисел, результат преобразуется к 16-битному, возможно с сатурацией (насыщением). А потом только расширяется до длинного. Поэтому такая реализация будет ошибочна, в связи с тем, что происходит потеря диапазона чисел.

Теперь рассмотрим вторую часть программы(case 2, default). В данном случае, мы изначально один из аргументов преобразуем в long, поэтому дальнейшие операции выполняются с длинными операндами. И результат вычисляется без потерь. Это объясняется тем, что компилятор преобразует второй аргумент к типу первого.

Циклическая адресация представляет метод адресации, при котором происходит циклическое обращение к ячейкам некоторой области памяти (к ячейкам буфера), т.е. адресация осуществляется на основе циклического буфера b[x]. Этот буфер представляет собой набор ячеек в памяти данных, где за последней ячейкой буфера как бы находится первая ячейка буфера, а перед первой ячейкой — как бы находится последняя ячейка. Таким образом, не зависимо от значения смещения, исполнительный адрес всегда будет находиться внутри этой области.

long circ(const int *a, const int *b, int n, int m)

{

int i, x=0;

long sum=0;

for(i=0; i<n; i++)

{

sum += (long)a[i] * b[x % m];

x++;

}

return sum;

}

Компилятор не поддерживает аппаратурные механизмы циклической адресации микропроцессора.