#1A Продолжаем познавать память

Вступление

Здравтвуйте!
Мы потихоньку, как это ни прискорбно, возвращаемся к еженедельным выпускам. Хотя я и буду пытаться делать выпуски по чаще, но увы не всё в моих силах.

Новости сайта

[01.02.03] Пополнен раздел Документация. Теперь там можно найти книги не только на русском.

А именно:
  • Jon Shemitz. Простенький FAQ для начинающих (14kb) [Скачать]
  • Timo Salmi. FAQ Pascal (83kb) [Скачать]
    Prof. Timo Salmi's answers to Frequently Asked Questions about common Turbo Pascal programming.
  • Ed Mitchell. Turbo Pascal Reference (291kb) [Скачать]
  • William L. Peavy. Inside Turbo Pascal Unit Files (137kb)[Скачать]

Теория

Сегодня у нас будет очень короткий выпуск. Он посвящён использованию такой штуки, как Mem. Mem - это массив памяти. Т.е. с помощью указания номера элемента вы получаете доступ к определенной ячейке. существует 3 вида массива Mem:

  • сам Mem - каждый компонент такого массива типа byte.
  • MemW - каждый компонент типа word.
  • MemL - каждый компонент типа longint.
Теперь рассмотрим примеры. Условно обозначим Seg - сегмент, Ofs - смещение в сегменте, b, w, l - переменные соответственно типов byte, word и longint.
  • b := Mem [Seg:Ofs];    - в b байт с указанного адреса.
  • w := MemW[Seg:Ofs]; - в w 2 байта с адреса
  • l := MemL[Seg:Ofs];    - в l 4 байта
это мы читали из памяти. Для записи же в память надо присвоить элементу массива нужное число:
  • Mem[Seg:Ofs] := b;  - запишет 1 байт по адресу
  • MemW[Seg:Ofs] := w; - запишет 2 байта по адресу
  • MemL[Seg:Ofs] := l; - запишет 4 байта по адресу
Еще одна тонкость. Число ABCDEF12h будет записано в памяти в следующем виде: 12EFCDABh, т.е. наоборот.

Вот и всё :) Теперь я рассмотрю несколько примеров для закрепления материала. Например помните, как мы с помощью указателя изменяли первый символ на экране? Давайте провернём тот же фокус с использованием Mem.

begin
 Mem[$B800:0] := 1;
 Mem[$B800:1] := $84
end.
-рисует вместо первого символа красную мигающую рожицу на чёрном фоне. Если вы забыли, как устроена видеопамять в текстовом режиме или не читали об этом, то вам лучше вернуться к выпуску #16 Путешествие по памяти. Продолжим и сделаем тоже самое, но с использованием MemW:
begin
 MemW[$B800:0] := $8401
end.
вот тут обратите внимание на тут тонкость о которой я говорил - запись идёт в обратном порядке.
Если бы мы написали MemW[$B800:0] := $0184 - т.е. сначала символ, а потом аттрибут. То мы бы увидели синюю букву Д, а не красную рожицу. Давайте теперь изменим 4 байта в видеопамяти, т.е. 2 первых символа на экране с помощью MemL:
begin
 MemL[$B800:0] := $24028401
end.
Опять таки обратите внимание на обратный порядок записи - сначала идёт байт-аттрибут 2-го символа, потом второй символ, потом байт-аттрибут 1-ог символа и наконец сам 1-й символ. Теперь давайте считывать из памяти. Напомня, что слово по адресу 0:413 содержит информацию BIOS'a о наличной памяти в килобайтах. Давайте распечатаем это число.
begin
   writeLn (MemW[0:$413])
end.
в общем и целом тут нет ничего сложного. Поэтому думаю, что эту тему можно считать закрытой.

Задание

В прошлый раз я не дал объяснения как найти предыдущий элемент в списке с одной связью (list на входе указывает на текущий элемент списка, start на его начало). Ниже приводится текст процедуры с комментариями.

procedure findPrior;
var
  l : plist;
begin
  if  (start = list)  or (list = nil)then
     exit; { предыдущего нет }

  l := list; { сохраняем текущий в переменной l }
  list := start;

{ перематываем список с начала }
  while list <> nil do
  begin
    if list^.next = l then
      exit; {  нашли элемент, next которого указывает на  текущий элемент, на выход }
    list := list^.next
  end
end;
если мы не смогли найти предыдущий элемент (например в случае если list принял ошибочное значение и вылез куда-то за границу списка), то при выходе list = nil. В случае удачного выполнения в list и окажется предыдущий элемент.

[Назад] [Содержание] [Дальше]
Hosted by uCoz