Помощь - Поиск - Пользователи - Календарь
Полная версия: Изменение констант в процессе работы.
Форум «Всё о Паскале» > Pascal, Object Pascal > Задачи
Altair
Код
Uses CRT;
Const
n=2;
D:word=12;
var
a:array[1..n] of integer;
b:word absolute n:2;
i:word;
c:word absolute d;
begin
ClrScr;
readln(b);
for i:=1 to b do a[i]:=random(100);
for i:=1 to b do write(a[i],' ');
writeln; writeln('c=');
readln(c);
writeln(d);

end.

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

Значение свободной константы можно изменять свободно.

Почему значение констант индексирования нельзя менять в большую сторону при сохранении размера переменной в памяти?
ответ:
массив или строка увеличится, автоматически новая облать памяти попытается обнулиться, а там могут быть данные чужие, и получаем RUN-TIME ERROR. smile.gif

Если есть подобные примеры работы с директивой absolute, кидайте сюда, может получиться интересная статья в итоге...

ЗЫ: Странно, зачем вообще константы в Паскале .... :D
xds
Не понятна суть проблемы/недовольства.

Код
const
 n = 1;

- константа в классическом понимании: при компиляции все вхождения идентификатора n будут заменены на 2.

Отсюда
Код
var
 d: Word absolute n:2

эквивалентно
Код
var
 d: Word absolute 2:2;

Т. е. d располагается по адресу $0002:$0002 (физ. адрес $00022, в области $00000..$00400 (физ. адреса) расположена таблица векторов прерываний) и хранит сегментную часть вектора int 8. Недостаточно обдуманное изменение её значения приведет к плачевным последствиям (int 8 = IRQ0 - прерывание системного таймера).

Код
const
 d: Word = 12

- "типизированная константа" (typed constant, термин от Borland):
Цитата
Typed constant declarations are used to declare initialized variables.

К слову, Delphi допускает более "корректный" синтаксис:
Код

var
 d: Word = 12;
Altair
Цитата
Не понятна суть проблемы/недовольства.

Проблеммы нет. Вопрос в другом - зачем надо было вводить константы (т.е. постоянные), если их так просто обойти?

Зачем вводить огланичение, и сразу вводить способ его обхода?
Тем более в теме сказанно что проблеммы нет:
Цитата
мои наблюдения
xds
Что касается "типизированных констант", то теперь трудно судить, чем руководствовались разработчики Borland, когда решили в BP инициализированные переменные определять через ключевое слово const.

Польза "настоящих" ("нетипизированных") констант очевидна - под них не выделяется место в сегменте данных, и компилятор может использовать в генерируемом коде инструкции с непосредственной адресацией. К тому же, этот тип констант изначально присутствовал в Паскале как простейшее макросредство.
xds
Цитата(Oleg_Z @ 5.11.04 7:02)
Вопрос в другом - зачем надо было вводить константы (т.е. постоянные), если их так просто обойти?

"Нетипизированную" константу нельзя изменять на этапе выполнения по очевидной причине: она не присутствует в сгенерированном компилятором коде как единственный объект.

Из моих наблюдений: в некоторых реализациях BP 7.0

Код
...
const
 a = -0;
 b = a * -1;
...


или даже

Код
...
Writeln(-2 * Integer(-0))
...


вызывает ошибку компиляции 108: "Overflow in arithmetic operation".
Altair
xds, ты глубоко ошибаешся, посмотри - ка код внимательно, я изменяю нетипизированную константу!!!
xds
Ах, да где же? Не вижу - ткни меня носом...smile.gif
GoodWind
Цитата
Не вижу

и я ,кстати, тоже ... :p2:
Altair
Код

Const
n=2; { это константане имеющая типа - нетипизированная }
{...}
var
b:word absolute n:2; { а вот переменная B}
{...}
begin
readln(b); {Изменяем B, но еще и n автоматом}
{...}
end.
Флогримм
а для чего нужна деректива absolute?
Dark
При помощи прямого доступа к памяти можно обойти абсолютно все, даже в винде, а то не было бы например такой вещи как утилит для игрушек, которые В ПАМЯТИ изменяют значения, РАЗ - и у тебя вместо 20 войнов 200, ДВА и у тебя вместо 1 монеты 50000

А так, никто просто и не собирался предусматривать такой доступ =) а зачем? константа - это только для программиста! это сигнальная система компилятора!!! ну надо тебе - обманывай... но ради чего?
GoodWind
Oleg_Z, понял...

Флогримм, директива absolute нужна для задания адреса переменной в памяти...

например:

Код
var Grscr: array [1..320,1..200] of byte absolute $a000:000;


теперь все, что будет писаться в этот массив будет писаться в видеопамять...
(в режиме 13h видеопамять начинается с $a000)
Altair
Цитата
но ради чего?

согласен, с памятью шутки плохи smile.gif
просто любопытсво ...
xds
Конструкция absolute имеет две синтаксических формы:

1.
Код
var
 <идентификатор>: <тип> absolute <переменная>;

2.
Код
var
 <идентификатор>: <тип> absolute <сегмент>:<смещение>;


В первом виде она используется для размещения переменной с именем <идентификатор> типа <тип> по тому же адресу, что и <переменная>.

Пример:
Код
var
 a: Integer;
 c: Byte absolute a;

Переменная c размещается по тому жу адресу, что и a, т.е. представляет собой младший байт а. Следует отметить, что по absolute место в сегменте данных не выделяется, и следующий код является ошибочным:
Код
var
 c: Byte;
 a: LongInt absolute c;
 d: Integer;

a выходит за границы участка памяти, выделенного под c, и при записи в a мы в лучшем случае испортим значение d.

Во втором виде, она используется для размещения переменной с именем <идентификатор> типа <тип> в памяти по абсолютному (сегментному) адресу <сегмент>:<смещение> (её физический адрес будет равен <сегмент> * 16 + <смещение>, где "*" - операция арифметического умножения, "+" - операция арифметического сложения, а "16" - число в десятичной форме записи rolleyes.gif :P :D). GoodWind уже привел пример такого случая.
xds
Цитата(Oleg_Z @ 6.11.04 6:54)
Код

Const
n=2; { это константане имеющая типа - нетипизированная }
{...}
var
b:word absolute n:2; { а вот переменная B}
{...}
begin
readln(b); {Изменяем B, но еще и n автоматом}
{...}
end.

Ух, Олежка, вцени:
Код
program Code;

uses
 Dos;

const
 n = 2;

var
 x: Word absolute n:2;
 p: Pointer;

begin
 Writeln(x);
 GetIntVec(8, p);
 Writeln(LongInt(p) shr 16);
end.

:D
Флогримм
Я еще с памятью никогда не работал. Что такое сегмент и смещение и зачем они нужны? Зачем нужен прямой доступ к памяти? Что подразумевается под памятью(оперативная что ли?)?

xds
var
Код
a: Integer;
c: Byte absolute a;

т.е. если мы переменной а присвоим какое-то значение, оно автоматически присвоется с?
Altair
В последнем примере, две переменные расположенны по одному адресу, но размер разные, и переменная с является верхним разрядом переменной а.
Цитата
Ух, Олежка, вцени:

Вценил! Круто!
Цитата
Что подразумевается под памятью(

Конечно оперативка... ведь не сказанно что внешняя память... а какая по твоему еще есть? Ну ПЗУ мы не рассматриваем smile.gif rolleyes.gif :D :P
Цитата
Зачем нужен прямой доступ к памяти?

Для большинства прикладных программ, обходится без них... а вот для системных утилит иногда надо обратится к памяти напрямую...
Цитата
Что такое сегмент и смещение и зачем они нужны?

Сегментом и смещением характеризуется адрес в ОП.
ИМХО ответ на это есть в очень подробном виде на форум "Ассемблер" (где Dark модер) тебе туда... т.к. в основном всю эту бяку используют там... здесь это ненужно...
xds
Под "памятью" подразумеваются адресное пространство ЦП, в котором располагаются ОЗУ (оперативная память), основное ПЗУ (обычно содержит BIOS), видеобуфер и т. п.

Сегментные адреса были введены в семействе x86 по той простой причине, что первые модели (i8086/88, i80186, i80286) были 16-разрядными. Перед разработчиками Intel стояла проблема: с помощью 16-разрядного слова можно адресовать только 64 кб, что шло в разрез с уже достаточно высоким потенциалом возможностей системы команд x86. Поступили следующим образом: шину адреса сделали 20-разрядной, что позволило увеличить адресное пространство до 1 Мб. Поскольку процессор мог оперировать только словами длиной 8 и 16 бит, то ввели концепцию сегментных адресов. Сегментный адрес имеет длину 32 бита и состоит из 2 16-разрядных слов - сегмента и смещения. Сегментный адрес автоматически преобразуется процессором в физический следующим образом (повторюсь): <физический_адрес> := <сегмент> * 16 + <смещение>. Т. о. одной физической ячейке памяти соответствует 4096 различных сегментных адресов. Все указанное выше справедливо для любой модели x86, работающей в режиме real x86.
xds
Цитата
переменная с является верхним разрядом  переменной а.

Младшим байтом! (в Intel принят порядок little-endian) smile.gif

Цитата
Вценил! Круто!

Что круто-то? huh.gif
Altair
Цитата
Что круто-то? 

А ты про что? lol.gif lol.gif lol.gif
Цитата
Младшим байтом! (в Intel принят порядок little-endian)

Да, точно. Ошибся, действительно, они распологаются задом наперед ...
rolleyes.gif
Цитата
little-endian

reverse-byte sequence.
Младший байт в ячейке с меньшим адресом, а старший в ячейке с большим адресом.
xds
Я все про константы... smile.gif

Цитата
Код
readln(b); {Изменяем B, но еще и n автоматом}

мы изменяетм не n, а вектор int 8.

Термины "reverse-byte sequence" и "little-endian" (от "little end first") - синонимы.
Altair
угу...в твоем примере мы действтиетльно изменяем вектор перывания....
xds
Не припоминаю, чтобы в моем примере изменялся вектор int 8 (да и константы тоже ;)). Где же?
Altair
ты сам это сказал:
Цитата
мы изменяетм не n, а вектор int 8.

smile.gif
я тебе на слово поверил rolleyes.gif :D :P smile.gif
xds
Я сказал это по поводу строчки из твоего примера :P
Altair
стоп, стоп, у меня в примере мы не изменяем никаких векторов прерывания!
(пора это прекращать... smile.gif )
xds
Запись в b в твоем примере:
Код
readln(b)
изменяет вектор 8-го прерывания. Она это действительно делает! (за исключением того случая, когда введенное значение совпадает с сегментной частью вектора). Предлагаю почитать мои предыдущие сообщения в этой теме и немного пораздумать над этой информацией за кружкой чая smile.gif

Цитата
(пора это прекращать... )

Да уж, все становится как-то совсем не смешно rolleyes.gif.
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.