![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Работа с большой областью оперативки из Ассемблера
Yury Yakhno © (2002-08-07 23:46:00)Здравствуйте, уважаемые мастера.
Знает ли кто-нибудь решение этой проблемы:
Есть неразрывная область оперативной памяти размером до нескольких десятков мегабайт. На неё указывает Pointer. В ассемблерном коде нужно получить каждый байт по очереди. Проблема в том, что если написать:
var
M:Pointer;
N:Cardinal;
.
.
.
GetMem(M, N);
asm
.
.
.
mov ESI,M
.
.
.
inc ESI
mov AL,[ESI]
.
.
.
end;
то это работает на маленьких областях оперативной памяти, но если области большие, то надо ещё переходить через границу сегмента данных.
Кто-нибудь сталкивался с этой проблемой? Не подскажет ли кто-нибудь, например, как узнать какой сегментный регистр используется для моих данных (ds, es, gs, fs), или какая модель адресации используется?
Digitman (2002-08-08 15:11:00) [21]Добавлю только к выступлению уважаемого Слесаря, что обращение по смещению в любом текущем сегменте за пределы 64к совершенно необязательно требует работу в защищенном режиме. На современных машинах это вполне успешно реализуемо и в реальном режиме DOS, выполняемой CPU не ниже i80386. При этом, установив единожды нужные сегментные регистры и имея достаточно памяти (при окрытой 20-й адресной линии) можно запросто обращаться к любому участку физ.памяти, не заботясь более о содержимом сегментных регистров
Слесарь Матерящийся (2002-08-08 14:46:00) [22]>>>Насколько я знаю, Pointer - 32 битное смещение относительно сегмента данных программы.
В принципе так. Но видимо, вы путаете две модели памяти -- "традиционную" сегментированную для DOS и flat (protected mode).
В режиме адресации flat вы (в принципе) можете обращаться к любому адресу в рамках 0..4 Гб. Для этого вы можете использовать индексные регистры или ebx.
Модель flat подразумевает перекрытие сегментов адреса и данных в одном адресном пространстве.
Так, например (например!), если по адресу 0x04567870 в сегменте кода записан байт 0x45, то он будет виден в сегменте данных по тому же (0x04567870) адресу.
Разумеется, сейчас мы не учитывали принципы работы виртуальной памяти и т.п. Речь шла только об адресации.
--------
>>>Так вот если выделить себе мегов сто и зациклить ESI на inc, не достигнет ли он своего максимального значения, а потом обнулится
В реальном режиме DOS-программ такое могло быть. Но в protected mode работает механизм защиты памяти.
Вы можете обращаться т_о_л_ь_к_о к заранее выделенной области памяти.
Если вы обратились "мимо", сработает механизм защиты и вы получите msg "Access violation".
Просто контролируйте, чтобы указатель не переходил границы выделенной области.
Так, к примеру, если выделенный фрагмент расположен по адресу
0x00770000 и имеет длину 0x00004000 байт, то диапазон памяти, к которому можно обращаться -- 0x00770000..0x00773FFF
//
Digitman (2002-08-08 14:04:00) [23]DS = ES = CS = SS
размер "сегмента", о коем ты так беспокоишься, формально может достигать 4GB - это предостаточно для того , чтобы надолго забыть обо всем касаемом "сегментов"
Yury Yakhno (2002-08-08 13:53:00) [24]> Anatoly Podgoretsky © (07.08.02 23:49)
> Какая версия Дельфи?
Delphi 6
> Слесарь Матерящийся (08.08.02 00:25)
> Модель flat. [Местами stdcall. Ой. Шютка :)]
> 32 бита. плоский мир. про сегментные регистры просто необходимо забыть.
> и что означает:
> "работает на маленьких областях оперативной памяти, но если области
> большие, то надо ещё переходить через границу сегмента данных."
> -- совершенно непонятно. Поясните, pls.
Насколько я знаю, Pointer - 32 битное смещение относительно сегмента данных программы. Когда я заношу указатель в ESI, он уже имеет какое-то значение. Так вот если выделить себе мегов сто и зациклить ESI на inc, не достигнет ли он своего максимального значения, а потом обнулится?
Скорее всего, я просто чего-то не догоняю, но регулярно получаю Access Violtation при обращении к [ESI] через некоторое время после начала работы.
> Юрий Зотов © (08.08.02 08:56)
> Не только сегментые регистры - даже ассемблер не нужен.
> Простое приведение Pointer к DWORD решает проблему
> адресной арифметики.
Разумеется, но я с каждым байтом ещё определённые действия произвожу. Ассемблер мне для этого нужен. А про DWORD я выше писал.
Юрий Зотов (2002-08-08 08:56:00) [25]Не только сегментые регистры - даже ассемблер не нужен. Простое приведение Pointer к DWORD решает проблему адресной арифметики.
Слесарь Матерящийся (2002-08-08 00:25:00) [26]Модель flat. [Местами stdcall. Ой. Шютка :)]
32 бита. плоский мир. про сегментные регистры просто необходимо забыть.
и что означает:
"работает на маленьких областях оперативной памяти, но если области большие, то надо ещё переходить через границу сегмента данных."
-- совершенно непонятно. Поясните, pls.
Anatoly Podgoretsky (2002-08-07 23:49:00) [27]Какая версия Дельфи?