Считывание из порта ввода/вывода

1) ins op1, DX

2) insb

3) insw

4) insd ; i386 и >

Эти команды считывают из порта ввода/вывода, номер которого содержится в регистре DX, байт (insb), слово (insw) или двойное слово (insd) и пересылает их в память по адресу ES:DI или ES:EDI. Команда 1) принимает одну из форм 2), 3), 4) в зависимости от типа операнда.

При использовании с префиксом rep она считывает из порта ввода/вывода блок данных (байтов, слов или двойных слов) длинной, определяемой регистром CX (ECX) и пересылает в память по адресу приемника.

Запись в порт в/в содержимого ячейки памяти, размером в байт, слово или дв. слово, находящейся по адресу DS:SI или DS:EDI

1) outs DX, op2

2) outsb

3) outsw

4) outsd ; i386 и >

Номер порта в командах работы с портами в/в должен находиться в регистре DX. В команде outs можно заменить DS на ES, FS, GS, CS SS. Используя префикс rep можно переслать в порт блок данных размером в (CX) или (ECX) байтов, слов или двойных слов.

Команды управления флагами.

После выполнения команд со строками изменяется содержимое регистров – индексов в зависимости от значения флажка направления DF. Автоматически его значение не изменяется, его должен изменить программист с помощью команд:

cld ; CLear Df, DF = 0

std ; SeT Df, DF = 1

Программист может установить следующие флажки:

stc ; CF = 1

clc ; CF = 0

cmc ; инвертировать флаг переноса

lahf ; копирует младший байт регистра FLAGS а AH

sahf ; из AH загружает флажки SF, ZF, AF, PF, CF

cli ; IF = 0

sti ; IF = 1

salc ; установить регистр AL в соответствии с CF

Загрузка сегментных регистров

lds op1, op2

les op1, op2

lfs op1, op2

lgs op1, op2

lss op1, op2

Первый операнд регистр. Для всех команд op2 – переменная в ОП размером в 32 или 48 бит в зависимости от разрядности операндов. Первые 16 бит этой переменной загружаются в соответствующий сегмент DS, ES и т.д., а следующие 16 или 32 - в регистр общего назначения, указанный в качестве первого операнда. В защищенном режиме значение, загружаемое в сегментный регистр, всегда должно быть правильным селектором сегмента, в реальном режиме любое число может использоваться как селектор.

S1 DB “ABC$”

ADR DD S1

Les DI, ADR

В переменную ADR записывается полный адрес, определяемый именем S1 (Seg:Ofs). В ES записывается значение сегментной части адреса S1, а в DI ее смещение.

Пример 1 использования команд работы со строками:

X DW 100 dup (?)

Y DW 100 dup (?)

Выполнить пересылку содержимого одной области памяти в другую X = Y

CLD ; DF = 0 (просмотр строки слева направо)

Lea SI, Y ; DS:SI – начало Y

Push DS

pop ES ; (ES) = (DS)

Lea DI, X ; ES:DI –начало X

Mov CX, 100

Rep movsw

Пример 2. В строке S, состоящей из 500 символов заменить первое вхождение звездочки на точку.

CLD ; просмотр строки слева направо

push DS

pop ES

lea DI, S ; ES:DI –начало S

mov CX, 500

mov AL, ‘ * ‘

repne scasb ; сканирование строки S и сравнение с (AL)

jne finish ; ‘ * ‘ в строке нет

mov byte ptr ES:[DI – 1], ‘ . ‘ ; замена

finish: --------------------------

Здесь используется выражение [DI – 1] т.к. после того как звездочка найдена DI увеличивается на 1 и указывает на следующий символ.

32) Работа с подпрограммами в Ассемблере, организация рекурсивных подпрограмм

Основные трудности, возникающие при реализации рекурсии – это опасность «зацикливания » рекурсии и использование параметров. Зацикливания не произойдет, если в процедуре есть рекурсивная и не рекурсивная ветви и при выполнении некоторого условия вычислительный процесс пойдет по не рекурсивной ветви.

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

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

входе в ПП их необходимо сохранять в стеке, а при выходе из нее восстанавливать. Это значит, что лучше сразу параметры передавать через стек.

Пример рекурсивной функции

F(n) = 1, если n = 0 или n = 1 и

F(n) = F(n – 1) + F(n – 2), если n >1

Вычисление n-го ряда Фибоначчи

Fib proc ; BX = F(n), AL = n

Cmp AL, 1

ja m1 ; если n > 1, m1

; не рекурсивная ветвь

mov BX, 1 ; если n < 1 или n = 1 BX = F(n) = 1

Ret

; рекурсивная ветвь

m1: push AX ;

dec AL ; AL = n - 1

call Fib ; BX = F(n-1)

Push BX ; сохранить в стеке F(n-1)

dec AL ; AL = n - 2

call Fib ; BX = F(n – 2)

pop AX ; AX = F(n – 1)

add BX, AX ; BX = F(n – 2) + F(n – 1)

Pop AX ; восстановить AX

Ret

Fib endp

34) Не вошедшее

Форматы данных

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

Целые числа без знака могут занимать байт, слово, двойное слово и принимать значения из диапазонов: 0 - 255, 0 - 65535, 0 – 4294967295 соответственно.

Считывание из порта ввода/вывода - student2.ru Целые числа со знаком могут занимать также байт, слово, двойное слово. Они хранятся в дополнительном коде и имеют следующий вид.

Дополнительный код положительного числа равен самому числу.

Дополнительный код отрицательного числа в любой системе счисления может быть получен по формуле: X = 10n - |X|, где n – разрядность числа.

Например, представим в слове отрицательное 16-ричное число -AC716: 104 - AC7 = F539.

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

Например, - 12 в байте: 1) 12 = 000011002, 2) инверсия – 111100112,

3) дополнительный код – 111101002.

Рассмотрим выполнение операции вычитания в машине: дополнительный код вычитаемого прибавляется к уменьшаемому.

Например: 65 – 42 = 23.

1) 65 = 010000012,

2) 42 = 001010102,

3) - 42 = 110101102,

4) 65 - 42 = 000101112 = 20 + 21 + 22 + 24 = 1+2+4+16=23.

Числа с плавающей точкой могут занимать 32 бита или 64 бита или 80 бит, и называются короткое вещественное, длинное вещественное, рабочее вещественное. Формат числа с плавающей точкой состоит из трех полей: <знак числа>, <машинной порядок>, <мантисса>.

короткое вещественное 1+ 8 + 23 - 10±32 - + 10±32

длинное вещественное 1+ 11 + 52 - 10±308 - + 10±308

рабочее вещественное 1+ 15 + 64 - 10±4932 - + 10±4932.

Машинный порядок(Пм) включает в себя неявным образом знак порядка и связан с истинным порядком (Пи) формулой: Пм = Пи + 12710 (102310, 1638310).

Считывание из порта ввода/вывода - student2.ru Предполагается, что мантисса нормализована и старший единичный разряд мантиссы не помещается в разрядную сетку.

Например, для короткого вещественного:

Считывание из порта ввода/вывода - student2.ru Пример, 306010 представить в виде числа с плавающей точкой, занимающего 4 байта.

1) 306010 = BF416 £ |M| <1

2) нормализуем число 0. BF4*10316

3) получим машинный порядок Пм = 316 + 7F16 = 8216

4) запишем в разрядную сетку в 2-ичной системе счисления:

0 1000 0010 011 1111 0100 0000 0000 00002

Или в 16-ричном виде: 413F400016.

0100 0001 0 011 1111 0100 0000 0000 00002

Двоично-десятичные данные - процессором могут обрабатываться 8-ми разрядные в упакованном и неупакованном формате, и сопроцессором могут обрабатываться 80-ти разрядные данные в упакованном формате. Упакованный формат предполагает хранение двух цифр в байте, а неупакованный – хранит одну цифру в цифровой части байта.

Символьные данные – символы в коде ASCII. Для любого символа отводится один байт.

Строковые данные – это последовательности бит, байт, слов или двойных слов.

Указатели– существуют два типа указателей: длинный указатель, занимающий 48 бит -селектор(16) + смещение(32) и короткий указатель, занимающий 32 бита - только смещение.

Наши рекомендации