Разное

Косвенная адресация ассемблер – Assembler: Косвенная адресация

Учебный курс. Часть 14. Режимы адресации

Режимы адресации — это различные способы указания местоположения операндов. До этой части в учебном курсе использовались только простые режимы адресации: операнды чаще всего находились в регистрах или в переменных в памяти. Но в процессоре Intel 8086 существуют также более сложные режимы, которые позволяют организовать работу с массивами, структурами, локальными переменными и указателями. В этой части я расскажу о всех возможных режимах адресации и приведу примеры их использования.

1. Неявная адресация

Местоположение операнда фиксировано и определяется кодом операции. Примеры:

Команда CBW всегда работает с регистрами AX и AL, а у команды MUL фиксировано положение первого множителя и результата. Такой режим адресации делает машинную команду короткой, так как в ней отсутствует указание одного или нескольких операндов.

2. Непосредственная адресация

При непосредственной адресации значение операнда является частью машинной команды. Понятно, что в этом случае операнд представляет собой константу. Примеры:

    mov al,5
    add bx,1234h
    mov dx,a

mov al,5 add bx,1234h mov dx,a

Обратите внимание, что в третьей строке в DX помещается адрес метки или переменной a, а вовсе не значение по этому адресу. Это особенность синтаксиса FASM. По сути адрес метки тоже является числовой константой.

3. Абсолютная прямая адресация

В машинной команде содержится адрес операнда, находящегося в памяти. Пример:

Вот тут уже в DX помещается значение из памяти по адресу a. Сравните с предыдущим пунктом. Квадратные скобки обозначают обращение по адресу, указанному внутри этих скобок.

4. Относительная прямая адресация

Этот режим используется в командах передачи управления. В машинной команде содержится смещение, которое прибавляется к значению указателя команд IP. То есть указывается не сам адрес перехода, а на сколько байтов вперёд или назад надо перейти. Пример:

У такого режима адресации два преимущества. Во-первых, машинная команда становится короче, так она содержит не полный адрес, а только смещение. Во-вторых, такой код не зависит от адреса, по которому он размещается в памяти.

5. Регистровая адресация

Операнд находится в регистре. Пример:

6. Косвенная регистровая (базовая) адресация

Адрес операнда находится в одном из регистров BX, SI или DI. Примеры:

Размер операнда в памяти здесь определяется размером первого операнда. Так как AX — 16-разрядный регистр, то из памяти берётся слово по адресу в BX. Так как DL — 8-разрядный регистр, то из памяти берётся байт по адресу в SI. Это правило верно и для других режимов адресации.

7. Косвенная регистровая (базовая) адресация со смещением

Адрес операнда вычисляется как сумма содержимого регистра BX, BP, SI или DI и 8- или 16-разрядного смещения. Примеры:

    add ax,[bx+2]
    mov dx,[array1+si]

add ax,[bx+2] mov dx,[array1+si]

В качестве смещения можно указать число или адрес метки. О размере смещения не беспокойтесь — компилятор сам его определяет и использует нужный формат машинной команды.

8. Косвенная базовая индексная адресация

Адрес операнда вычисляется как сумма содержимого одного из базовых регистров BX или BP и одного из индексных регистров SI или DI. Примеры:

    mov ax,[bp+si]
    add ax,[bx+di]

mov ax,[bp+si] add ax,[bx+di]

Например, в одном из регистров может находиться адрес начала массива в памяти, а в другом — смещение какого-то элемента относительно начала. А вообще, всё зависит от вашей фантазии 🙂

9. Косвенная базовая индексная адресация со смещением

Адрес операнда вычисляется как сумма содержимого одного из базовых регистров BX или BP, одного из индексных регистров SI или DI и 8- или 16-разрядного смещения. Примеры:

    mov al,[bp+di+5]
    mov bl,[array2+bx+si]

mov al,[bp+di+5] mov bl,[array2+bx+si]

Пример программы

Допустим, имеется массив 32-битных целых чисел со знаком. Количество элементов массива хранится в 16-битной переменной без знака. Требуется вычислить среднее арифметическое элементов массива и сохранить его в 32-битной переменной со знаком. Я намеренно использовал разные режимы адресации, хотя тоже самое можно написать проще.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
use16                   ;Генерировать 16-битный код
org 100h                ;Программа начинается с адреса 100h
 
      sub ax,ax         ;AX = 0
      cwd               ;DX = 0
      mov si,ax         ;SI = 0 - смещение элемента от начала массива
      mov bx,array      ;Помещаем в BX адрес начала массива
      mov di,n          ;Помещаем в DI адрес n
      mov cx,[di]       ;CX = n
lp1:
      add ax,[bx+si]    ;Прибавление младшего слова
      adc dx,[bx+si+2]  ;Прибавление старшего слова
      add si,4          ;Увеличиваем смещение в SI на 4
      loop lp1          ;Команда цикла
 
      idiv word[di]     ;Делим сумму на количество элемнтов
      cwd               ;DX:AX = AX
      mov word[m],ax    ;\ Сохраняем
      mov word[m+2],dx  ;/ результат
 
      mov ax,4C00h      ;\
      int 21h           ;/ Завершение программы
;-------------------------------------------------------
n     dw 10
array dd 10500,-7500,-15000,10000,-8000
      dd 6500,11500,-5000,10500,-20000
m     dd ?

use16 ;Генерировать 16-битный код org 100h ;Программа начинается с адреса 100h sub ax,ax ;AX = 0 cwd ;DX = 0 mov si,ax ;SI = 0 — смещение элемента от начала массива mov bx,array ;Помещаем в BX адрес начала массива mov di,n ;Помещаем в DI адрес n mov cx,[di] ;CX = n lp1: add ax,[bx+si] ;Прибавление младшего слова adc dx,[bx+si+2] ;Прибавление старшего слова add si,4 ;Увеличиваем смещение в SI на 4 loop lp1 ;Команда цикла idiv word[di] ;Делим сумму на количество элемнтов cwd ;DX:AX = AX mov word[m],ax ;\ Сохраняем mov word[m+2],dx ;/ результат mov ax,4C00h ;\ int 21h ;/ Завершение программы ;——————————————————- n dw 10 array dd 10500,-7500,-15000,10000,-8000 dd 6500,11500,-5000,10500,-20000 m dd ?

Упражнение

Объявите в программе два массива 16-битных целых со знаком. Количество элементов массивов должно быть одинаковым и храниться в 8-битной переменной без знака. Требуется из последнего элемента второго массива вычесть первый элемент первого, из предпоследнего — вычесть второй элемент и т.д. Результаты можете выкладывать в комментариях.

Следующая часть »

asmworld.ru

3. Виды адресация ассемблера

Прямая адресация — это простейший вид адресации операнда в памяти, так как эффективный адрес содержится в самой команде и для его формирования не используется никаких дополнительных источников или регистров. Эффективный адрес берется непосредственно из поля смещения машинной команды, которое может иметь размер 8, 16, 32 бита. Это значение однозначно определяет байт, слово или двойное слово в сегменте данных. Прямая адресация может быть двух типов:

относительная прямая адресация используется в командах условных переходов для указания относительного адреса перехода. Относительность такого перехода заключается в том, что в поле смещения машинной команды содержится 8-, 16- или 32-разрядное значение, которое в результате работы команды будет складываться с содержимым регистра указателя команд IP/EIP. В результате такого сложения получается адрес, по которому и осуществляется переход;

абсолютная прямая адресация — в этом случае эффективный адрес является частью машинной команды, но формируется этот адрес только из значения поля смещения в команде. Для формирования физического адреса операнда в памяти процессор складывает это поле со сдвинутым на четыре бита значением сегментного регистра. В команде ассемблера можно использовать несколько форм такой адресации.

Однако такая адресация применяется редко — обычно ячейкам в программе присваиваются символические имена. В процессе трансляции ассемблер вычисляет и подставляет значения смещений этих имен в поле смещения формируемой им машинной команды. В итоге получается, что машинная команда прямо адресует свой операнд, имея, фактически, в одном из своих полей значение эффективного адреса.

Остальные виды адресации относятся к косвенным. Слово «косвенный» в названии этих видов адресации означает, что в самой команде может находиться лишь Часть эффективного адреса, а остальные его компоненты находятся в регистрах, на которые указывают своим содержимым байт mod r/m и, возможно, байт sib.

Косвенная адресация имеет следующие разновидности:

косвенная базовая, или регистровая, адресация;

косвенная базовая адресация со смещением;

косвенная индексная адресация со смещением;

косвенная базовая индексная адресация;

косвенная базовая индексная адресация со смещением.

При косвенной базовой (регистровой) адресации эффективный адрес операнда может находиться в любом из регистров общего назначения, кроме SP/ESP и ВР/ЕВР (это специальные регистры для работы с сегментом стека).

Синтаксически в команде этот режим адресации выражается заключением имени регистра в квадратные скобки. К примеру, команда mov ax,[ecx] помещает в регистр АХ содержимое слова по адресу сегмента данных со смещением, хранящимся в регистре ЕСХ. Так как содержимое регистра легко изменить в ходе работы программы, данный способ адресации позволяет динамически назначить адрес операнда для некоторой машинной команды. Это очень полезно, например, для организации циклических вычислений и для работы с различными структурами данных типа таблиц или массивов.

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

К примеру, команда mov ax,[edx+3h] пересылает в регистр АХ слово из области памяти по адресу, определяемому содержимым EDX + 3h. Команда mov ax,mas[dx] пересылает в регистр АХ слово по адресу, определяемому содержимым DX плюс значение идентификатора mas (причем транслятор присваивает каждому идентификатору значение, равное смещению этого идентификатора относительно начала сегмента данных).

Косвенная индексная адресация со смещением очень похожа на косвенную базовую адресацию со смещением. Здесь также для формирования эффективного адреса используется один из регистров общего назначения. Но индексная адресация обладает одной интересной особенностью, которая очень удобна для работы с массивами. Она связана с возможностью так называемого масштабирования содержимого индексного регистра, а именно байта sib. При описании структуры этого байта отмечалось, что он состоит из трех полей. Одно; из этих полей — поле масштаба (ss), на значение которого умножается содержимое индексного регистра. К примеру, в команде mov ax,mas[esi*2] значение эффективного адреса второго операнда определяется выражением mas+(esi)*2. В связи с тем, что в ассемблере нет средств индексации массивов, программисту приходится организовывать ее своими силами. Наличие возможности масштабирования существенно помогает в решении этой проблемы, но при условии, что размер элементов массива составляет 1, 2, 4 или 8 байт.

При косвенной базовой индексной адресации эффективный адрес формируется как сумма содержимого двух регистров общего назначения: базового и индексного В качестве этих регистров могут применяться любые регистры общего назначения, при этом часто содержимое индексного регистра масштабируется. Например: mov еах, [esi][edx]

В данном примере эффективный адрес второго операнда формируется из двух компонентов, (ESI) + (EDX).

Косвенная базовая индексная адресация со смещением является дополнением косвенной индексной адресации. Эффективный адрес формируется как сумма трех составляющих: содержимого базового регистра, содержимого индексного регистра и значения поля смещения в команде. К примеру, команда mov eax,[esi+5][edx] пересылает в регистр ЕАХ двойное слово по адресу: (ESI) + 5 + (EDX). Команда add ax,array[esi][ebx] складывает содержимое регистра АХ с содержимым слова по адресу, образованному значением идентификатора array + (ESI) + (ЕВХ).

studfiles.net

Assembler: 9. Режимы адресации. Ограничения на использование режимов адресации.

Режим адресации – это форма записи операнда в команде.

Режимы адресации:

  • Непосредственный (5, 0Аh).
  • Регистровый (AX, BX).
  • Память :
    • Прямой (mas (- имя переменной))
    • Косвенный ([BX] (- взять значение хранящееся по адресу записанному в регистр BX))

Ограничения

  • Оба операнда должны иметь одинаковую длину.
  • Оба операнда не могут одновременно быть памятью.
  • Получатель не может быть регистром CS, IP, EIP.
  • Нельзя в сегментный регистр пересылать непосредственное значение.
  • Приемником не может быть непосредственный режим адресации.

Примеры использования режимов адресации:

Непосредственный.

Регистровый.

Прямой.

MAS DB ‘HELLO’
MOV AL, MAS	;AL=’H’

Эффективный адрес = база + смещение + индекс.
Физический адрес = сегмент*16 + Эффективный адрес.

Косвенный режим адресации также делится еще на 5 видов:

  • Базовая адресация
    В 32-х разрядном ассемблере можно использовать все регистры общего назначения кроме ESP, EBP.
    В 16-х разрядном ассемблере можно использовать только BX, BP.
    Пример: ARR DB 1, 2, 3
    LEA BX, ARR
    MOV AL, [BX]		;AL=1
    
  • Базовый адрес со смещением
    Пример: ARR DB 1, 2, 3
    LEA BX, ARR
    MOV AL, [BX+2]		;AL=3
  • Индексная адресация со смещением
    В 16-х разрядном ассемблере можно использовать только SI, DI для формирования эффективного адреса.
    Пример: ARR DB 1, 2, 3
          MOV SI, 0
    MOV AL, ARR[SI]		;AL=1
    
  • Базовая индексная адресация.
    Эффективный адрес формируется как сумма содержимого двух регистров: базового и индексного.
    Пример: ARR DB 1, 2, 3
    LEA BX, ARR
    MOV SI, 0
    MOV AL, [BX][SI]		;AL=1
    
  • Базовая индексная адресация со смещением.
    Пример: MOV AL, ARR[BX][SI]
    

indigobits.com

Лабораторная работа №2

Лабораторная работа №1

«Ознакомление с программой разработки и отладки программ на языке

Ассемблера — DEBUG»

Цель работы: изучить команды программы DEBUG при разработке и отладки программ на языке Ассемблера.

Оборудование: IBM — совместимый персональный компьютер, работающий под управлением операционной системы, совместимой с MS-DOS®.

Программное обеспечение: Программа DEBUG.

Краткие теоретические сведения.

  1. Средства разработки программ на языке Ассемблера

  2. Этапы разработки программы на языке Ассемблера

  3. Применение команд программы DEBUG для создания и отладки прикладного программного обеспечения на языке Ассемблера.

Вопросы к защите лабораторной работы.

  1. Ввод программы.

  2. Отладка программы

  3. выполнение программы

  4. Ввод программы.

  5. Вывод программы

  6. Перемещение данных

  7. Сравнение данных

  8. Модификация памяти

  9. Работа с регистрами микропроцессора

«Изучение команд пересылки данных»

Цель работы: изучить способы адресации данных микропроцессором i8x86 и применение этих методов при пересылке данных.

Оборудование: IBM — совместимый персональный компьютер, работающий под управлением операционной системы, совместимой с MS-DOS®.

Программное обеспечение: Программа DEBUG

Краткие теоретические сведения.

  1. Методы адресации данных

  2. Команды пересылки данных

Режимы адресации данных

Микропроцессор 8×86 предоставляет Вам множество способов доступа к операндам, с которыми должна работать Ваша программа. Операнды могут содержаться в регистрах, в самих командах, в памяти или в портах ввода-вывода. В рекламных проспектах производителей оборудования утверждается, что микро­процессор 8×86 имеет 24 режима адресации операндов. Пожалуй, так оно и есть, если рассматривать все возможные комбинации. Здесь мы разделяем режимы адресации на семь групп:

1. Регистровая адресация.

2. Непосредственная адресация.

3. Прямая адресация.

4. Косвенная регистровая адресация.

5. Адресация по базе.

6. Прямая адресация с индексированием.

7. Адресация по базе с индексированием.

Микропроцессор выбирает один из семи режимов адресации по значению поля режима команды. Ассемблер присваивает то или иное значение полю режима в зависимости от того, какой вид имеют операнды в исходной программе. Напри­мер, если вы написали

MOV АХ,ВХ

то Ассемблер закодирует оба операнда (АХ и ВХ) для регистровой адресации. Однако если Вы заключили операнд-источник в квадратные скобки:

MOV AХ,[ВХ]

то Ассемблер закодирует операнд-источник для косвенной регистровой адреса­ции.

В табл. 1 приведены форматы операндов языка ассемблера для всех семи режимов адресации, реализуемых микропроцессором 8×86, и для каждого форма­та указано, какой из регистров сегмента используется для вычисления физическо­го адреса. Обратите внимание, что во всех режимах предполагается доступ к сегменту данных (т. е. регистром сегмента служит регистр DS), и только в тех случаях, когда используется регистр ВР, предполагается доступ к сегменту стека (т. е. регистром сегмента служит регистр SS).

Важное замечание: при исполнении команд микропроцессора 8×86, манипулирующих строками, предполагается, что регистр DI указывает на ячейку дополнительного сегмента, а не сегмента данных. Таким образом, в качестве регистра сегмента эти команды используют регистр ES. Все другие команды исполняются по правилам, описанным в табл.1.

Таблица 1. Режимы адресации микропро цессора 8×86

Режим адресации

Формат операнда

Регистр сегмента

Регистровый

регистр

Не используется

Непосредственный

данное

Не используется

Прямой

сдвиг

метка

DS

DS

Косвенный регистровый

[ВХ]

[ВР]

[DI]

[SI]

DS

SS

DS

DS

По базе

[ВХ] + сдвиг

[ВР] + сдвиг

DS

CS

Прямой с индексированием

[DI] + сдвиг

[SS] + сдвиг

DS

DS

По базе с индексированием

[BX][SI] + сдвиг

[ВХ] [DI] + сдвиг

[ВР] |S1] + сдвиг

[ВР] [DI] + сдвиг

DS

DS

SS

SS

Примечания к таблице:

1. Компонент сдвиг при адресации по базе с индексированием необязателен.

2. Операнд регистр может быть любым 8-ми 16-и битовым регистром, кроме регистра IP.

3. Операнд данное может быть 8- или 16-битовым значением константы.

4. Компонент сдвиг может быть 8- или 16-битовым значением смещения со знаком.

Из семи режимов адресации самыми быстрыми являются регистровая и непос­редственная адресации операндов, поскольку в этом случае операционный блок микропроцессора 8×86 извлекает их либо из регистров (при регистровой адреса­ции), либо из конвейера команд (при непосредственной адресации). В других режимах адресация выполняется дольше, потому что интерфейс шины вначале должен вычислить адрес ячейки памяти, извлечь операнд и только после этого передать его операционному блоку.

Каждое описание режима адресации, приведенное в данном разделе, сопровож­дается примерами его применения. В большинстве случаев для этого использует­ся команда MOV микропроцессора 8×86.

Регистровая и непосредственная адресация

При регистровой адресации микропроцессор 8×86 извлекает операнд из регистра (или загружает его в регистр). Например, команда

MOV AХ,СХ

копирует 16-битовое содержимое регистра счетчика СХ в аккумулятор АХ. Содер­жимое регистра СХ не изменяется. В данном примере микропроцессор 8×86 ис­пользует регистровую адресацию для извлечения операнда-источника из регистра СХ и загрузки его в регистр-приемник АХ.

Непосредственная адресация позволяет Вам указывать 8- или 16-битовое значение константы в качестве операнда-источника. Эта константа содержится в команде (куда она помещается Ассемблером), а не в регистре или в ячейке памя­ти. Например, команда

MOV СХ,500

загружает значение 500 в регистр СХ, а команда

MOV CL,-30

загружает значение — 30 в регистр CL.

Чтобы избежать трудностей, помните, что допустимые значения для 8-битовых чисел со знаком ограничены диапазоном от -128 (80Н) до 127 (7FH), а допустимые значения 16-битовых чисел со знаком — диапазоном от —32768 (8000Н) до 32767 (7FFFH). Максимальные значения 8-битовых чисел без знака равны соответствен­но 255 (OFFH) и 65535 (OFFFFH).

Расширение знакового бита непосредственных значений

Ассемблер всегда расширяет знак при пересылке непосредственных значений в операнд-приемник. Это означает, что он дублирует старший значащий бит значения источника до тех пор, пока не будут заполнены все 8 или 16 битов операнда-приемника.

Например, операнд-источник нашего первого примера, десятичное число 500, может быть записано в виде 10-битового двоичного значения 0 111 110 100. Когда Ассемблер устанавливает, что Вы требуете загрузить это значение в 16-битовый регистр СХ, то он расширяет его до 16-битового, записав перед ним шесть копий «знакового» бита (со значением 0). Поэтому в регистр СХ попадает двоичное значение 0 000 000 111 110 100. Во втором примере микропроцессор 8×86 загружает в регистр CL 8-битовое двоичное представление 11 100 010 десятичного числа –30.

Режимы адресации памяти

Доступ к ячейкам памяти обеспечивает­ся взаимодействием операционного блока и интерфейса шины микропроцессора 8×86. Когда операционному блоку требуется прочитать или записать значение операнда, находящегося в памяти, он передает значение смещения адреса интер­фейсу шины. Последний добавляет это смещение к содержимому регистра сегмен­та (предварительно дополненному четырьмя нулями) и тем самым получает 20-битовый физический адрес, который и используется для доступа к операнду.

Исполнительный адрес

Смещение, которое вычисляется операционным блоком для доступа к находящемуся в памяти операнду, называется исполнительным адресом операн­да. Исполнительный адрес показывает, на каком расстоянии (в байтах) располага­ется операнд от начала сегмента, в котором он находится. Будучи 16-битовым числом без знака, исполнительный адрес позволяет получить доступ к операндам, находящимся выше начала сегмента на расстоянии до 65535 (или 64К) байтов.

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

Прямая адресация

При прямой адресации исполнительный адрес является составной частью команды (так же, как значения при непосредственной адресации). Микро­процессор 8×86 добавляет этот исполнительный адрес к сдвинутому содержимому регистра сегмента данных DS и получает 20-битовый физический адрес операнда.

Обычно прямая адресация применяется, если операндом служит метка. Напри­мер, команда

MOV AX,TABLE

загружает содержимое ячейки памяти TABLE в регистр АХ. На рис. 1 показана схема исполнения этой команды. Обратите внимание на то, что против ожидания микропроцессор 8×86 заполняет данные в памяти в обратном порядке. Старший байт слова следует за младшим байтом, а не предшествует ему. Чтобы усвоить это, запомните, что старшая часть (старшие биты) данных располагается в ячейках памяти со старшими адресами.

Рис. 1. Прямая адресация Рис. 2. Косвенная регистровая адресация

Косвенная регистровая адресация

При косвенной регистровой адресации исполнительный адрес операн­да содержится в базовом регистре ВХ, регистре указателя базы ВР или индексном регистре (SI или DI). Косвенные регистровые операнды надо заключать в квадрат­ные скобки, чтобы отличить их от регистровых операндов. Например, команда

MOV AХ,[ВХ]

загружает в регистр АХ содержимое ячейки памяти, адресуемой значением регистра ВХ (рис. 2).

Как поместить смещение адреса в регистр ВХ? Один из методов состоит в применении команды LEA (Загрузить исполнительный адрес). Например, для загрузки слова из ячейки TABLE в регистр АХ можно воспользоваться последова­тельностью команд

LEA BX, TABLE

MOV AХ,[ВХ]

Эти две команды выполняют те же действия, что и одна команда

MOV AX,TABLE

с той лишь разницей, что в первом случае предыдущее содержимое регистра ВХ уничтожается. Если Вам нужен доступ лишь к одной ячейке памяти (в данном случае TABLE), то разумнее воспользоваться одной командой. Однако для досту­па к нескольким ячейкам, начиная с данного базового адреса, гораздо лучше иметь исполнительный адрес в регистре. Почему? Потому что содержимым регист­ра можно манипулировать, не извлекая каждый раз новый адрес.

Адресация по базе

При адресации по базе Ассемблер вычисляет исполнительный адрес с помощью сложения значения сдвига с содержимым регистров ВХ или ВР.

Регистр ВХ удобно использовать при доступе к структурированным записям данных, расположенным в разных областях памяти. В этом случае базовый адрес записи помещается в базовый регистр ВХ и доступ к ее отдельным элементам осуществляется по их сдвигу относительно базы. А для доступа к разным записям одной и той же структуры достаточно соответствующим образом изменить содер­жимое базового регистра.

Предположим, например, что требуется прочитать с диска учетные записи для ряда работников. При этом каждая запись содержит табельный номер работника, номер отдела, номер группы, возраст, тарифную ставку и т.д. Если номер отдела хранится в пятом и шестом бантах записи, а начальный адрес записи содержится в регистре ВХ, то команда

MOV AХ,[ВХ]+4

загрузит в регистр АХ номер отдела, в котором служит данный работник (рис. 3). (Сдвиг равен 4, а не 5, потому что первый байт записи имеет номер 0.)

Ассемблер позволяет указывать адресуемые по базе операнды тремя разными способами. Следующие команды эквивалентны:

MOV AХ,[ВР]+4 ;3то стандартная форма записи,

MOV AХ,4[ВР] ; но сдвиг можно указать на первом месте

MOV AХ,[ВР+4] ; или внутри скобок

Рис. 3. Адресация по базе Рис. 4. Прямая адресация с индексированием

Прямая адресация с индексированием

При прямой адресации с индексированием исполнительный адрес вычисляется как сумма значений сдвига и индексного регистра (DI или SI). Этот тип адресации удобен для доступа к элементам таблицы, когда сдвиг указывает на начало таблицы, а индексный регистр – на ее элемент.

Например, если B_TABLE — таблица байтов, то последовательность команд

MOV DI,2

MOV AL,В_TABLE[DI]

загрузит третий элемент таблицы в регистр AL.

В таблице слов соседние элементы отстоят друг от друга на два байта, поэтому при работе с ней надо удваивать номер элемента при вычислении значения индек­са. Если TABLE — таблица слов, то для загрузки в регистр АХ ее третьего элемента надо использовать последовательность команд

MOV DI,4

MOV AХ,TABLE[DI]

(рис. 4).

Адресация по базе с индексированием

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

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

Предположим, например, что Ваша ЭВМ следит за шестью предохранительными клапанами на химическом предприятии. Она считывает их состояния каждые полчаса и запоминает в ячейках памяти. За неделю эти считывания образуют массив, состоящий из 336 блоков (48 считываний в течение семи дней) по шесть элементов в каждом, а всего — 2016 значений.

Если начальный адрес массива загружен в регистр ВХ, сдвиг блока (номер считывания, умноженный на 12) — в регистре DI, а номер клапана задан в перемен­ной VALVE, то команда

MOV AX ,VALVE[BX][DI ]

загрузит требуемое считывание состояния клапана в регистр АХ. На рис. 5 изображен процесс извлечения результата третьего считывания (с номером 2) для клапана 4 из массива, у которого смещение в сегменте данных равно 100Н.

Приведем несколько допустимых форматов операндов, адресуемых по базе с индексированием:

MOVE AX,[BX+2+DI]

MOVE AX,[DI+BX+2]

MOVE AX,[BX+2][DI]

MOVE AX,[BX][DI+2]

КОМАНДЫ ПЕРЕСЫЛКИ ДАННЫХ

Команды пересылки данных осуществляют обмен данными и адреса­ми между регистрами и ячейками памяти или портами ввода-вывода. Эти команды разделены на четыре подгруппы: команды общего назначения, команды ввода-вывода, команды пересылки адреса и команды пересылки флагов.

Команды общего назначения

Основная команда общего назначения MOV (move — переслать) может пересылать байт или слово между регистром и ячейкой памяти или между двумя регистрами. Она может также пересылать непосредственно адресуемое значение в регистр или в ячейку памяти.

Команда MOV имеет следующий формат:

MOV приемник, источник

В ней допустимо большинство из возможных сочетаний операндов.

Приведем несколько примеров:

MOV AX,TABLE ; Пересылка иэ памяти в регистр

MOV TABLE,AX ; и наоборот

MOV ES:[BX],АХ ; Можно заменить используемый регистр сегмента

MOV DS,AХ ; Пересылка между 16-битовыми регистрами

MOV BL.AL ; Пересылка между 8-битовыми регистрами

MOV CL,-30 ; Пересылка константы в регистр

MOV DE5T,25H ; или в память

В команде MOV исключаются следующие сочетания операндов:

1. Вы не можете осуществить непосредственную пересылку данных из одной ячейки памяти в другую. Чтобы выполнить такую пересылку, данные источника надо загрузить в регистр общего назначения, а затем запомнить содержимое этого регистра в приемнике. Например, если POUNDS и WEIGHT — переменные, находя­щиеся в памяти, то для пересылки значения из одной переменной в другую можно воспользоваться командами

MOV AX,POUNDS

MOV WEIGHT,AX

2. Вы не можете загрузить непосредственно адресуемый операнд в регистр сегмента. Как и в случае 1, сначала надо загрузить его в регистр общего назначе­ния. Например, следующие команды загружают номер блока сегмента данных (DATA_SEG) в регистр DS:

MOV HX,DATA_SEG

MOV DS,AX

Подобные команды обычно сопутствуют оператору ASSUME в сегменте команд. Они указывают Ассемблеру, где размещен сегмент данных.

3. Вы не можете непосредственно переслать значение одного регистра сегмента в другой. Делайте подобные пересылки через регистр общего назначения. Напри­мер, чтобы регистр DS указывал на тот же сегмент, что и регистр ES, воспользуй­тесь командами

MOV AX,ES

MOV DS,AX

(Для выполнения этой операции можно воспользоваться командами PUSH и POP, которые будут описаны в следующем разделе.)

4. Вы не можете использовать регистр CS в качестве приемника в команде пересылки.

Команда обмена XCHG

Команда обмена XCHG (exchange — обменять) меняет между собой значения двух регистров или регистра и ячейки памяти. Однако она не может выполнить обмен значений регистров сегмента.

Приведем несколько примеров команд XCHG:

XCHG AX,BX ;Обменять значения двух регистров (слова

XCHG AL,BH ; или байты

XCHG WRD_LOC,DX ;Обменять значения ячейки памяти

ХСНG DL,BYTE_LOC ; и регистра

Команды ввода-вывода

Команды ввода-вывода используются для взаимодействия с перифе­рийными устройствами системы. Они имеют формат

IN аккумулятор, порт

OUT порт, аккумулятор

где аккумулятор – регистр AL при обмене байтами или регистр АХ при обмене словами. Операндом порт может быть десятичное значение от 0 до 255, что позво­ляет адресоваться к 256 устройствам.

В качестве операнда порт можно использовать регистр DX, что позволяет легко изменять номер порта, например при необходимости пересылать одни и те же данные в несколько различных портов.

Приведем несколько примеров команд IN и OUT:

IN AL,200 ;Ввести байт из порта 200

IN AL,PORT_VAL ; или из порта, указанного константой

OUT ЗОН,AХ ; Вывести слово в порт ЗОН

OUT DX,AX ; или в порт, указанный в ОХ

Команды пересылки адреса

Команды пересылки адреса передают не содержимое перемен­ных, а их адреса.

Команда загрузки исполнительного адреса

Команда LEA (load effective address — загрузить исполнительный адрес) пересылает смещение ячейки памяти в любой 16-битовый регистр общего назначе­ния, регистр указателя или индексный регистр. Она имеет формат

LEA регистр16,память16

где операнд память16 должен иметь атрибут типа WORD.

Операнд память16 в команде LEA может быть индексирован, что дает возможность осуществить гибкую адреса­цию. Например, если регистр DI содержит 5, то команда

LEA BX,TABLE[DI]

загрузит смещение адреса TABLE+5 в регистр ВХ.

Команда загрузки указателя и регистра сегмента данных LDS

Команда LDS (load pointer using DS — загрузить указатель с использо­ванием регистра DS) считывает из памяти 32-битовое двойное слово и. загружает первые 16 битов в заданный регистр, а следующие 16 битов — в регистр сегмента данных DS. Она имеет формат

LDS регистр16,память32

где регистр 16 — любой 16-битовый регистр общего назначения, а память32 — ячейка памяти с атрибутом типа DOUBLEWORD.

Команда загрузки указателя и регистра дополнительного сегмента LES

Команда LES (load pointer using ES — загрузить указатель с использова­нием регистра ES) идентична команде LDS, но загружает номер блока в регистр ES, а не в DS.

Команды помещения флагов в стек PUSHF и извлечения флагов из стека POPF

Эти команды пересылают содержимое регистра флагов в стек и обрат­но. Они в сущности идентичны командам PUSH и POP, но в них не требуется указывать операнд, так как под ним подразумевается регистр флагов.

Как и в случае команд PUSH и POP, команды PUSHF и POPF всегда используют­ся парами. Другими словами, каждой команде PUSHF должна соответствовать исполняемая позже команда POP.

studfiles.net

Презентация на тему: Адресация в Ассемблере

4. Косвенная адресация — адрес операнда в памяти можно не указывать непосредственно, а хранить в любом регистре

mov ax, [bx]

5. Адресация по базе со сдвигом — комбинация двух предыдущих методов адресации

mov ax, [bx+2] mov ax, [bp]+2

Адресация в Ассемблере

6. Косвенная адресация с масштабированием

mov ax,[esi*2]+2 — этот метод адресации полностью идентичен предыдущему, за исключением того, что с его помощью можно прочитать элемент массива слов, двойных слов или учетверенных слов, просто поместив номер элемента в регистр множитель, может быть равен 1, 2, 4 или 8 — соответствует

размеру элемента массива — байту, слову, двойному слову, учетверенному слову соответственно

Адресация в Ассемблере

7.Адресация по базе с индексированием — в этом методе адресации смещение операнда в памяти вычисляется как сумма чисел, содержащихся в двух регистрах, и смещения, если оно указано Все следующие команды — это разные формы записи одного и того же действия:

mov ax,[bx+si+2] mov ax,[bx][si]+2 mov ax,[bx+2][si] mov ax,[bx][si+2] mov ax,2[bx][si]

8.Адресация по базе с индексированием и масштабированием — это самая полная возможная схема адресации, в которую входят все случаи, рассмотренные ранее, как частные

mov eax, ds:[eax+ebx*2+2]

Адресация

• Прямая (адрес задан непосредственно)

MOV al,var1

MOV al,[var1]

MOV al,[arrayB+1] MOV al,[arrayD+4]

• Косвенная

MOV al,[esi]

INC BYTE PTR [esi]

Безусловный переход и цикл

JMP метка_перехода

– безусловный переход

LOOP метка_перехода

–ECX/CX уменьшается на единицу

–если ECX/CX не ноль, то переход по метке

–иначе следующая команда

LOOPD всегда ECX

LOOPW всегда CX

TITLE Add and Subtract, Version 2 (AddSub2.asm)

;Сложение и вычитание 32-битных целых переменных

;результат – в переменной.

INCLUDE Irvine32.inc

.data

 

 

 

val1

dword

10000h

Ещё пример

val2

dword

40000h

 

val3

dword

20000h

 

finalVal dword

?

 

.code main PROC

mov eax,val1

;

Загрузить 10000h

add eax,val2

;

добавить

40000h

sub

eax,val3

;

вычесть 20000h

mov

finalVal,eax

;

записать

результат (30000h)

call DumpRegs

;

отобразить регистры

exit

 

main ENDP

 

END main

16

Стек

•Понятие стека

–LIFO (Last-In, FIst-Out)

•Стековая адресация памяти

–SS ESP

–«рост» в сторону меньших адресов

•PUSH/POP r/m16|r/m32|imm32|imm16

•PUSHFD/POPFD – флаги 32 бита

•PUHSF/POPF — флаги 16 бит

•PUSHAD/POPAD – регистры по 32 бита

EAX,ECX,EBX,ESP,EBP,ESI,EDI

• PUHSA/POPA — регистры по 16 бит

AX, CX, BX, SP, BP, SI, DI

studfiles.net

Стек и косвенная адресация Assembler

В этой статье мы с вами познакомимся с основными понятиями, которые связаны со стеком в Assembler, напишем небольшую программу, изучим несколько новых команд.

Общая информация

Итак, что же такое стек: если коротко, то стек — область памяти на ядре процессора, там хранятся адреса. По своей сути, это абстрактный тип данных. В понимании он довольно прост и следующая иллюстрация отображает принцип работы стека:

Принцип работы можно выразить простыми словами: первым пришел — последним вышел, и наоборот: последним пришел — первым вышел. Это полностью описывает работу стека в Assembler.

Часто этот принцип сравнивают с обоймой в пистолете, когда вы заряжаете обойму, то тот патрон который был первым, выстрелит самым последним.

Стек в Assembler

Для основ, нам необходимо знать 2 новые команды:

  • push — поместить в стек
  • pop — вытащить из стека

Также нам понадобится такая конструкция :
[esp] — это указатель на вершину стека, как раз с ней мы и будем работать.

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

.386
.model flat,stdcall
.data
.code

Уже знакомые строки, которые необходимо прописывать.
Перейдем к разделу кода:

start:
mov ax, 2211h
mov ecx, 66554433h
push ax
push ecx
pop ax
pop ecx

Сначала в регистры ax и ecx помещаем значения(h означает шестнадцатеричную систему исчисления,и по сути никак не относится к числу). Заметьте, что в регистр ax, содержащий максимум 2 байта, можно поместить только 4 цифры, а в регистр ecx, содержащий 4 байта, только 8.

Затем с помощью команды push, помещаем в стек значения регистров ax и ecx соответственно, то есть сначала мы положили 2 байта, а затем еще 4 байта. Таким образом сейчас на вершине стека лежит то число из 8 знаков.

Далее, с помощью команды pop, вынимаем значения в регистры ax и ecx соответственно. Только заметьте, так как регистр ax, как мы уже сказали, может содержать 4 цифры(или правильнее сказать 2 байта), то в него запишется только 2 байта. Это означает что, то значение из 8 цифр, которое лежит на вершине, будет разделено пополам, а последняя половинка запишется в регистр ax(по принципу последним пришел — первым вышел). То есть в регистр ax запишется 4433h. И после этого в регистр ecx запишется 4 байта, а именно, то что останется: ecx = 22116655h.
Итак, поменяли значения регистра, а теперь изучим косвенную адресацию:

Косвенная адресация

mov ecx,[esp-6]
mov ax,[esp-2]
ret
end start

Для понимания нужна полная сосредоточенность: итак, после выполнения команд pop(которая вытаскивает значения, но не удаляет его), вершина стека сместилась относительно наших значений сначала на 2 байта, а затем еще на 4, в общем на 6 байт. Так вот, с помощью косвенной адресации [esp-2] и [esp-6] мы можем обратится как раз к тем значениям: в итоге мы в ecx поместим значение, которое было в самом начале: 66554433h, в регистр ax: 2211h(просто вернули первоначальные значения).

Для того, чтобы лучше понять этот материал, советую воспользоваться отладчиком, и посмотреть как будут меняться значения регистров и значение, которое хранится на вершине стека(оно находится в правом нижнем окне и подсвечено серым цветом).

На этом мы закончим с изучением темы стек в Assembler, если у вас остались вопросы, то пишите в комментариях.

Скачать исходники

Поделиться ссылкой:

Похожее

codetown.ru

Assembler: Способы адресации

Большинство команд процессора вызывается с аргументами, которые в ассемблере принято называть операндами. Способом, или режимом адресации называют процедуру нахождения операнда для выполняемой команды. Если команда использует два операнда, то для каждого из них должен быть задан способ адресации, причем режимы адресации первого и второго операнда могут как совпадать, так и различаться. Операнды команды могут находиться в разных местах: непосредственно в составе кода команды, в каком-либо регистре, в ячейке памяти; в последнем случае существует несколько возможностей указания его адреса. Строго говоря, способы адресации являются элементом архитектуры процессора, отражая заложенные в нем возможности поиска операндов. С другой стороны, различные способы адресации определенным образом обозначаются в языке ассемблера и в этом смысле являются разделом языка.
Следует отметить неоднозначность термина «операнд» применительно к программам, написанным на языке ассемблера. Для машинной команды операндами являются те данные (в сущности, двоичные числа), с которыми она имеет дело. Эти данные могут, как уже отмечалось, находиться в регистрах или в памяти. Если же рассматривать команду языка ассемблера, то для нее операндами (или, лучше сказать, параметрами) являются те обозначения, которые позволяют сначала транслятору, а потом процессору определить местонахождение операндов машинной команды. Так, для команды ассемблера

mov mem, AX

в качестве операндов используется обозначение ячейки памяти mem, a также обозначение регистра АХ. В то же время, для соответствующей машинной команды операндами являются содержимое ячейки памяти и содержимое регистра. Было бы правильнее говорить об операндах машинных команд и о параметрах, или аргументах команд языка ассемблера.
По отношению к командам ассемблера было бы правильнее использовать термин «параметры», оставив за термином «операнд» обозначение тех физических объектов, с которыми имеет дело процессор при выполнении машинной команды, однако обычно эти тонкости не принимают в расчет, и говоря об операндах команд языка, понимают в действительности операнды машинных команд.
В архитектуре современных 32-разрядных процессоров Intel предусмотрены довольно изощренные способы адресации; в МП 86 способов адресации меньше. Пока будем разбираться с режимами адресации, используемыми в МП 86.
В книгах, посвященных языку ассемблера, можно встретить разные подходы к описанию способов адресации: не только названия этих режимов, но даже и их количество могут различаться. Разумеется, способов адресации существует в точности столько, сколько их реализовано в процессоре; однако, режимы адресации можно объединять в группы по разным признакам, отчего и создается некоторая путаница, в том числе и в количестве имеющихся режимов.
И так начнем разбираться…

asmforfun.blogspot.com

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *