Работа с адресами и указателями

При написании программ на ассемблере производится интенсивная работа с адресами операндов, находящимися в памяти. Для поддержки такого рода операций есть специальная группа команд, в которую входят следующие команды.

lea <приемник>,<источник> — загрузка эффективного адреса;

Команда LEA похожа на команду MOV тем, что она также производит пересылку, однако команда LEA производит пересылку не данных, а эффективного адреса данных (то есть смещения данных относительно начала сегмента данных) в регистр, указанный операндом <приемник>.

lds <приемник>,<источник> — загрузка указателя в регистр сегмента данных ds;

les <приемник>,<источник> — загрузка указателя в регистр дополнительного сегмента данных es;

lss <приемник>,<источник> — загрузка указателя в регистр сегмента стека ss.

Данные команды позволяют получить в паре регистров полный указатель на операнд в памяти. При этом имя сегментного регистра, в который помещается сегментная составляющая адреса, определяется кодом операции. Соответственно, смещение помещается в регистр общего назначения, указанный операндом <приемник>.

Но в команде в качестве источника нельзя указывать непосредственно имя операнда в памяти, на который мы бы хотели получить указатель. Предварительно необходимо получить само значение полного указателя в некоторой области памяти и задать в команде получения полного адреса имя этой области. Например, в поле операндов указывается имя другой директивы определения данных (фактически, имя переменной). В этом случае в памяти формируется адрес этой переменной. Какой адрес будет сформирован (эффективный или полный), зависит от применяемой директивы. Если это DW, то в памяти формируется только 16-разрядное значение эффективного адреса, если же DD — в память записывается полный адрес. Размещение этого адреса в памяти следующее: в младшем слове находится смещение, в старшем — 16-разрядная сегментная составляющая адреса.

Например, в следующем фрагменте сегмента данных переменные adr и adr_full иллюстрируют наш случай получения частичного и полного указателей на данные в памяти.

perem dd 0f54d567ahadr dw peremadr_full dd perem

При организации работы с цепочкой символов удобно поместить ее начальный адрес в некоторый регистр и далее в цикле модифицировать это значение для последовательного доступа к элементам цепочки. В следующем примере производится копирование строки байтов str_l в строку байтов str_2.

masm

model small

.data

str_l db "Ассемблер - базовый язык компьютера"

str_2 db 35 dup ( " " )

full_pnt dd str_l ;получение полного указателя на str_l

.code

start:

lea si ,str_l ;загрузка эффективного адреса str_l в si

lea di ,str_2 ;загрузка эффективного адреса str_2 в di

les bx,full_pnt ;полный указатель на strl в пару es:bx

mov cx, 35 ;счетчик цикла для loop ml

ml:

mov al , [si ] ;пересылка очередного байта из одной

mov [di] ,al ;строки в другую

inc si ;увеличение адреса на 1

inc di

loop ml ;цикл на метку ml до пересылки всех символов

mov ax, 4c00h

int 21h

end start

В строке 6 листинга программы в двойном слове full_pnt формируются сегментная часть адреса и смещение для переменной str_l. При этом два байта смещения занимает младшее слово full_pnt, а значение сегментной составляющей адреса – старшее слово full_pnt. Затем командой LES эти компоненты адреса помещаются в регистры ВХ и ES.