[РЕДАКТИРОВАТЬ] Обновлено
Всякий раз, когда вы видите операнд памяти, похожий на ds:0x00923030
, это режим адресации относительно сегмента . Фактический адрес, на который ссылается tp, находится по линейному адресу 0x00923030 относительно базового адреса сегмента ds
.
Сегментация памяти в архитектуре x86 несколько сбивает с толку, и я думаю, что Wikipedia хорошо объясняет это.
В основном x86 имеет ряд специальных сегментов регистров: cs
( код сегмент), ds
( данные сегмент), es
, fs
, gs
и ss
( стек сегмент). Каждый доступ к памяти связан с определенным сегментным регистром. Обычно вы не указываете регистр сегмента, и в зависимости от того, как осуществляется доступ к памяти, используется регистр сегмента по умолчанию. Например, регистр cs
используется для чтения инструкций.
Каждый сегментный регистр имеет определенный базовый адрес и предел . Базовый адрес определяет физический адрес, которому соответствует линейный адрес 0x00000000, а предел определяет максимально допустимый линейный адрес для этого сегмента. Например, если базовый адрес был 0x00040000, а предел - 0x0000FFFF, то единственными действительными линейными адресами будут 0x00000000 до 0x0000FFFF, а соответствующие физические адреса будут от 0x00040000 до 0x0004FFFF.
Таким образом, физический адрес, по которому находится вызываемая подпрограмма, задается базовым адресом, хранящимся в регистре сегмента ds
, плюс 0x00923030. Но мы еще не закончили - в инструкции есть слово ptr
. Это добавляет дополнительный уровень косвенности, поэтому фактической целью подпрограммы является адрес , сохраненный в местоположении ds:0x00923030
.
В синтаксисе AT & T (принятом ассемблером GNU) инструкция будет записана следующим образом:
lcall *ds:0x00923030
Подробные сведения о том, что делает инструкция, см. В справочном руководстве 80386 . Этот конкретный вариант инструкции "CALL r/m16"
(вызов рядом с регистром косвенный / память косвенным).