Учебник по ассемблеру (ASM)
 

Ассемблер в примерах - что такое ptr

Вопрос:
раскажите поподробнее что означает команда
call dword ptr cs:[Int_21h_vect]
что такое ptr
ну call это вызов функции, но в переменную Int_21h_vect помещается адрес сегмента и смещение, а мы почему-то дописываем еще спереди cs:

Ответ:
PTR - модификатор типа, который показывает как нужно трактовать данные по заданному адресу.
Допустим у нас описано двойное слово
test_dword DD 01020304h
В памяти последовательность байт будет такой:
04h,03h,02h,01h
К этому двойному слову можно обратиться как к слову, используя модификатор типа:
mov ax,WORD PTR test_dword ;ax = 0304h
вторую половину поместим в DX:
mov dx,WORD PTR test_dword+2 ;dx = 0102h
Если не использовать модификатор и попытаться читать из памяти двойное слово, то получим ошибку неравенства типов:
mov ax,test_dword ;ошибка - поместить двойное слово в регистр размером в одинарное слово(поместить 4 байта в 2 байта, все равно что пытаться запихнуть 60 патронов в один рожок)
А теперь прочтем первый байт test_dword:
mov al,BYTE PTR test_dword ;al = 04h

Есть несколько вариантов команды call.
Данный формат команды call имеет вид:
call m16:16
операнд m16:16 - это дальний адрес дальнего адреса перехода, иными словами полный адрес памяти, по которому хранится полный адрес перехода. Пример:
осуществить дальний переход на процедуру My_Proc, которая находится в текущем сегменте кода.

Опишем в сегменте данных указатель(вектор), который будет содержать полный адрес
процедуры My_Proc

my_data SEGMENT

...
My_Proc_vect DD ?
...

my_data ENDS

и присвоим ему значение:

ASSUME cs:my_code, ds:my_data

mov WORD PTR ds:My_Proc_vect,OFFSET My_Proc
mov WORD PTR ds:My_Proc_vect+2,cs ;предполагаем, что My_Proc находится в сегменте кода, на который сейчас указывает cs

Теперь My_Proc_vect содержит вектор процедуры My_Proc - (смещение процедуры My_Proc):(сегментный адрес кодового сегмента процедуры My_Proc)
Делаем переход на процедуру My_Proc:
call ds:[My_Proc_vect] ;из My_Proc_vect считывается полный адрес процедуры My_Proc и по нему осуществляется переход.

Этот вектор можно также описать в кодовом сегменте, принципиальных различий между данными и кодом нет - и данные и код являются байтами двоичной информации, поэтому часто описывают переменные в сегментах кода, следя за тем, чтобы эти перменные не начали выполняться как код.
Опишем в кодовом сегменте:

my_code SEGMENT
My_Proc_vect DD ?
...
start:
...
my_code ENDS

start - точка входа в данный сегмент кода
Теперь вектор находится в сегменте кода и для чтения его нам нужно указать префикс переопределения сегмента:
mov ax,cs:WORD PTR My_Proc_vect
mov dx,cs:WORD PTR My_Proc_vect+2
При обращении к ячейке памяти в реальном режиме линейный адрес получается комбинацией сегментного адреса и смещения.
Когда мы ставим впереди cs, то переопределяем сегментный регистр, используемый для построения линейного адреса. Если его не указывать, то по умолчанию автоматически принимается ds:
mov ax,my_var аналогично такому варианту записи - mov ax,ds:my_var


   Вперёд
   Содержание