Команды работы с адресами и указателями памяти
При написании программ на ассемблере производится интенсивная работа с адресами операндов, находящимися в памяти. Для поддержки такого рода операций есть специальная группа команд, в которую входят следующие команды:
назначение,источник — загрузка эффективного адреса;
назначение,источник — загрузка указателя в регистр сегмента данных ds;
назначение,источник — загрузка указателя в регистр дополнительного сегмента данных es;
назначение,источник — загрузка указателя в регистр дополнительного сегмента данных gs;
назначение,источник — загрузка указателя в регистр дополнительного сегмента данных fs;
назначение,источник — загрузка указателя в регистр сегмента стека ss.
Команда lea похожа на команду mov тем, что она также производит пересылку. Однако, обратите внимание, команда lea
производит пересылку не данных, а эффективного адреса данных (то есть смещения данных относительно начала сегмента данных) в регистр, указанный операндом назначение.
Часто для выполнения некоторых действий в программе недостаточно знать значение одного лишь эффективного адреса данных, а необходимо иметь полный указатель на данные. Вы помните, что полный указатель на данные состоит из сегментной составляющей и смещения.
Все остальные команды этой группы позволяют получить в паре регистров такой полный указатель на операнд в памяти. При этом имя сегментного регистра, в который помещается сегментная составляющая адреса, определяется кодом операции. Соответственно, смещение помещается в регистр общего назначения, указанный операндом назначение.
Но не все так просто с операндом источник. На самом деле, в команде в качестве источника нельзя указывать непосредственно имя операнда в памяти, на который мы бы хотели получить указатель.
Предварительно необходимо получить само значение полного указателя в некоторой области памяти и указать в команде получения полного адреса имя этой области. Для выполнения этого действия необходимо вспомнить директивы резервирования и инициализации памяти.
При написании программ на ассемблере производится интенсивная работа с адресами операндов, находящимися в памяти. Для поддержки такого рода операций есть специальная группа команд, в которую входят следующие команды:
назначение,источник — загрузка эффективного адреса;
назначение,источник — загрузка указателя в регистр сегмента данных ds;
назначение,источник — загрузка указателя в регистр дополнительного сегмента данных es;
назначение,источник — загрузка указателя в регистр дополнительного сегмента данных gs;
назначение,источник — загрузка указателя в регистр дополнительного сегмента данных fs;
назначение,источник — загрузка указателя в регистр сегмента стека ss.
Команда lea похожа на команду mov тем, что она также производит пересылку. Однако, обратите внимание, команда lea
производит пересылку не данных, а эффективного адреса данных (то есть смещения данных относительно начала сегмента данных) в регистр, указанный операндом назначение.
Часто для выполнения некоторых действий в программе недостаточно знать значение одного лишь эффективного адреса данных, а необходимо иметь полный указатель на данные. Вы помните, что полный указатель на данные состоит из сегментной составляющей и смещения.
Все остальные команды этой группы позволяют получить в паре регистров такой полный указатель на операнд в памяти. При этом имя сегментного регистра, в который помещается сегментная составляющая адреса, определяется кодом операции. Соответственно, смещение помещается в регистр общего назначения, указанный операндом назначение.
Но не все так просто с операндом источник. На самом деле, в команде в качестве источника нельзя указывать непосредственно имя операнда в памяти, на который мы бы хотели получить указатель.
Предварительно необходимо получить само значение полного указателя в некоторой области памяти и указать в команде получения полного адреса имя этой области. Для выполнения этого действия необходимо вспомнить директивы резервирования и инициализации памяти.
При применении этих директив возможен частный случай, когда в поле операндов указывается имя другой директивы определения данных (фактически, имя переменной). В этом случае в памяти формируется адрес этой переменной. Какой адрес будет сформирован (эффективный или полный), зависит от применяемой директивы. Если это dw, то в памяти формируется только 16-битное значение эффективного адреса, если же dd — в память записывается полный адрес. Размещение этого адреса в памяти следующее: в младшем слове находится смещение, в старшем — 16-битная сегментная составляющая адреса.
Например, при организации работы с цепочкой символов удобно поместить ее начальный адрес в некоторый регистр и далее в цикле модифицировать это значение для последовательного доступа к элементам цепочки. В листинге 1 производится копирование строки байт str_1 в строку байт str_2.
В строках 12 и 13 в регистры si и di загружаются значения эффективных адресов переменных str_1 и str_2.
В строках 16 и 17 производится пересылка очередного байта из одной строки в другую. Указатели на позиции байтов в строках определяются содержимым регистров si и di. Для пересылки очередного байта необходимо увеличить на единицу регистры si и di, что и делается командами сложения inc (строки 18, 19). После этого программу необходимо зациклить до обработки всех символов строки.
Листинг 1. Копирование строки <1>;---------Prg_7_2.asm--------------- <2> masm <3> model small <4> .data <5> ... <6> str_1 db ‘Ассемблер — базовый язык компьютера’ <7> str_2 db 50 dup (‘ ‘) <8> full_pnt dd str_1 <9> ... <10> .code <11> start: <12> ... <13> lea si,str_1 <14> lea di,str_2 <15> les bx,full_pnt ;полный указатель на str1 в пару es:bx <16> m1: <17> mov al,[si] <18> mov [di],al <19> inc si <20> inc di <21> ;цикл на метку m1 до пересылки всех символов <22> ... <23> end start |
В строке 14 листинга 1 в двойном слове full_pnt формируются сегментная часть адреса и смещение для переменной str_1. При этом 2 байта смещения занимают младшее слово full_pnt, а значение сегментной составляющей адреса — старшее слово full_pnt. В строке 14 командой les эти компоненты адреса помещаются в регистры bx и es.
При применении этих директив возможен частный случай, когда в поле операндов указывается имя другой директивы определения данных (фактически, имя переменной). В этом случае в памяти формируется адрес этой переменной. Какой адрес будет сформирован (эффективный или полный), зависит от применяемой директивы. Если это dw, то в памяти формируется только 16-битное значение эффективного адреса, если же dd — в память записывается полный адрес. Размещение этого адреса в памяти следующее: в младшем слове находится смещение, в старшем — 16-битная сегментная составляющая адреса.
Например, при организации работы с цепочкой символов удобно поместить ее начальный адрес в некоторый регистр и далее в цикле модифицировать это значение для последовательного доступа к элементам цепочки. В листинге 1 производится копирование строки байт str_1 в строку байт str_2.
В строках 12 и 13 в регистры si и di загружаются значения эффективных адресов переменных str_1 и str_2.
В строках 16 и 17 производится пересылка очередного байта из одной строки в другую. Указатели на позиции байтов в строках определяются содержимым регистров si и di. Для пересылки очередного байта необходимо увеличить на единицу регистры si и di, что и делается командами сложения inc (строки 18, 19). После этого программу необходимо зациклить до обработки всех символов строки.
Листинг 1. Копирование строки <1>;---------Prg_7_2.asm--------------- <2> masm <3> model small <4> .data <5> ... <6> str_1 db ‘Ассемблер — базовый язык компьютера’ <7> str_2 db 50 dup (‘ ‘) <8> full_pnt dd str_1 <9> ... <10> .code <11> start: <12> ... <13> lea si,str_1 <14> lea di,str_2 <15> les bx,full_pnt ;полный указатель на str1 в пару es:bx <16> m1: <17> mov al,[si] <18> mov [di],al <19> inc si <20> inc di <21> ;цикл на метку m1 до пересылки всех символов <22> ... <23> end start |
В строке 14 листинга 1 в двойном слове full_pnt формируются сегментная часть адреса и смещение для переменной str_1. При этом 2 байта смещения занимают младшее слово full_pnt, а значение сегментной составляющей адреса — старшее слово full_pnt. В строке 14 командой les эти компоненты адреса помещаются в регистры bx и es.