Материал: TextmetukSPO

Внимание! Если размещение файла нарушает Ваши авторские права, то обязательно сообщите нам

руют и код условия. В частности, такими командам являются команды сложения, вычитания и логические команды. Именно после арифметических команд обычно используются мнемокоды JZ, JNZ, в то время как после команды сравнения более естественным является применение команд JE, JNE.

Для выполнения не следующей по записи в программе команды, а некоторой другой команды, отмеченной некоторой меткой, предназначена команда

JMP метка

Учитывая, что она выполняется без всякого условия, ее называют безусловным переходом.

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

Табл. 1. Связь мнемокодов для команд условного перехода с условиями

Мнемокод команды

Условие перехода

Примечание

 

 

JE или JZ

=

(=0)

От слов equal и zero

 

JNE или JNZ

¹

(¹0)

От слов not, equal и zero

 

JL или JNGE

<

(не ³ )

Сравнение со знаком; от слова

 

 

 

less

 

 

JG или JNLE

>

(не £ )

Сравнение со знаком; от great-

 

 

 

er

 

 

JLE или JNG

£

(не > )

Сравнение со знаком

 

JGE или JNL

³

(не < )

Сравнение со знаком

 

JC

при флаге переноса

От слова carry

 

JNC

не было переноса

 

 

 

JB или JNAE

<

(не ³ )

Сравнение

беззнаковое;

от

 

 

 

слова below - ниже

 

JA или JNBE

>

(не £ )

Сравнение

беззнаковое;

от

 

 

 

слова above - выше

 

JBE или JNA

£

(не > )

Сравнение беззнаковое

 

JAE или JNB

³

(не < )

Сравнение беззнаковое

 

Следует обратить внимание, что для ряда машинных команд существует два (и более) различных мнемокодов, в различных терминах задающих семантически равносильные условия. Например, вместо "больше", задаваемого символическим кодом условия G, можно использовать равносильное условие "не меньше или не равно", задаваемое символическим кодом условия NLE. Конкретный вариант использования мнемокода выбирает программист согласно со своими текущими соображениями и удобствами.

Команды условного перехода архитектуры IA32 по причине ее происхождения от примитивных микропроцессоров в записи на ассемблере "по умолчанию" предполагают наиболее компактное формирование машинного кода команд. Этот вариант для размещения информации о величине перехода использует всего один байт в машинных кодах. Такое архаичное техническое решение приводит нередко к сообщению транслятора "ralative jump out of range", что обозначает необходи-

11

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

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

. . .

MOV [имя_области_для_хранения_значения], обозначение_регистра

. . .

MOV обозначение_регистра, [имя_области_для_хранения_значения]

Следует обратить особое внимание, что при использовании ассемблера nasm прямой способ адресации обязательно требует символов '[' и ']' в записи операнда.

При использовании в программе константных текстов, для обработки и вывода которых программисту нужно иметь значение длины этих текстов, очень удобным является следующий прием. Он основан на использовании макросимвола $. Этот макросимвол в программах на nasm обозначает относительный адрес, по которому в формируемом объектном коде размещается код, формируемый той строкой исходной программы, содержащий этот символ. Эти соображения приводят к использованию в программах записей вида

msg DB 'текст' lenmsg EQU $ - msg

Здесь конструкция $ - msg используется для поручения транслятору вычислить длину текста, описанного в предыдущей директиве (в общем случае предыдущих директивах). Такое вычисление выполняется как определение разности между относительным адресом, который соответствует месту сразу за текстом (началом строки lenmsg EQU …), и относительным адресом, по которому начинается текст, обозначенный меткой msg.

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

Контрольные вопросы.

12

1.Придумайте пример применения команд JB и JA для байтовых числовых данных, в котором использование соответствующих команд JL и JG приводит к ошибке.

2.Объясните, когда будет правильным использование команд условного перехода JE метка, а когда правильным будет использование подобных команд в форме JE NEAR метка.

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

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

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

Предварительные сведения. В отличие от языков высокого уровня, где обращение к подпрограммам осуществляется просто указанием их по имени без ка- ких-либо служебных слов, в ассемблерах требуется явное указание команды вызова подпрограммы. В качестве мнемоники команды такого вызова практически во всех ассемблерах используется служебное слово CALL. Эта команда имеет единственный операнд, которым является имя вызываемой программы. Аргументы в собственно машинной команде указаны быть не могут, поскольку для общего случая число их может быть любым. В простейших случаях эти аргументы передаются в регистрах. Изучение более общих способов передачи аргументов будут рассматриваться в одной из следующих лабораторных работ.

Сама подпрограмма на языке nasm оформляется очень просто. Она должна начинаться с метки, обозначающей первую команду подпрограммы, и ее действия должны завершаться командой RET. Команда RET обеспечивает возвращение действий выполнения программы, традиционно называемое возвратом управления, к тому месту, откуда была вызвана подпрограмма.

Более детальное рассмотрение показывает, что команда CALL запоминает адрес команды, следующей по порядку размещения в программе (точнее, адрес следующей команды в машинных кодах сегмента команд). Это запоминание в процессорах архитектуры IA32 выполняется в аппаратно-программном стеке процессора. На вершину такого стека показывает регистр EIP. При выполнении команды RET верхнее слово этого встроенного стека снимается и используется в качестве адреса возврата, размещаемого тут же в регистре EIP. Из такого технического решение сразу же вытекает необходимость обеспечивать в любой подпрограмме работу со встроенным стеком так, чтобы все информация, которая помещается в него при выполнении подпрограммы, была обязательно извлечена из стека до момента выполнения команды RET, завершающей действия подпрограммы.

В ассемблерах TASM и MASM применяется более сложное оформление подпрограмм, хотя фактически можно и в этих ассемблерах обойтись более простым построением, подобным используемому в NASM. Указанное оформление, настоятельно рекомендуемое фирменной документацией, заключается в использовании парных директив для начала и конца подпрограммы. Эти директивы имеют вид

13

имя_подпрограммы PROC команды подпрограммы

. . .

RET

имя_подпрограммы ENDP

При использовании команд умножения и деления в архитектуре IA32 необходимо иметь в виду неявное использование подразумеваемых операндов. Явно в них указывается только один операнд. Это множитель в команде MUL и делитетель в команде DIV. Разрядностью этого явного операнда и определяется разрядность всей выполняемой операции. В табл. 3 приведены варианты использования команды MUL, зависящие от разрядности выполняемой операции

Табл. 3. Размещение неявных операндов команды MUL

Разрядность

Результат

Множимое

8 бит

AX

AL

16

бит

DX – старшие биты, AX – младшие биты

AX

32

бита

EDX – старшие биты, EAX – младшие биты

EAX

Табл. 4 содержит информацию о размещении неявных операндов команды DIV.

 

 

Табл. 4. Размещение неявных операндов команды DIV

Разрядность

Результат

Делимое

8 бит

AH – остаток, AL – частное

AX

16

бит

DX – остаток, AX – частное

DX – старшие биты, AX – млад-

 

 

 

шие биты

32

бита

EDX – остаток, EAX – частное

EDX – старшие биты, EAX –

 

 

 

младшие биты

Следует иметь в виду, что команда DIV в качестве делителя допускает размещение операнда только в регистре или памяти, но не в виде константы. Это практически требует в большинстве случаев размещать константу, на которое производится деление в регистре, а уже потом использовать этот регистр в качестве явного операнда - делителя.

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

mov esi,10 ; основание позиционной системы счисления в регистр mov ecx, 0 ; ECX – регистр для счетчика вычисленных цифр

pov: mov edx, 0 ; обнуление левой части делимого

div esi

; деление для получения следующей цифры в остатке деления

add dl, '0'

;приведение числового значения цифры к ее коду представления

push edx

; сохранение цифры в стеке

inc ecx

; подсчет шага в регистре для счетчика

14

cmp eax, 0 ; проверка на завершение формирования ненулевых цифр jne pov

mov [cnt], ecx ; запоминание в поле cnt числа запомненных цифр

izv: pop edx

; извлечение очередной цифры из стека

mov [digit],dl ; digit into digit for write ; запись ее кода в служебное поля

 

; для последующего вывода

mov eax,4 ; N function=write

mov ebx,1

; N handle=1 (stdout)

mov ecx, digit; address of digit

mov edx, 1 ; number of byte

int 80h

; вывод цифры обращением к write write write через прерыва-

ние

dec dword [cnt] ; учет в счетчике выведенной цифры

cmp dword [cnt],0 ; проверка по счетчику на наличие не выведенных цифр jne izv

. . .

; в секции SECTION .data digit db 0

cnt dd 0

Листинге 1. Программа преобразования двоичного кода числа, помещенного в регистр EAX, в последовательность десятичных цифр

Соответствующий алгоритм (вывода десятичного числа из двоичного кода в регистре EAX) в словесной форме можно записать следующим образом, обозначая начальное значение регистра EAX переменной N:

1)Разделить N на 10, обозначим: остаток - R, частное - M {остаток равен значению очередной цифры десятичного представления}.

2)Преобразовать остаток в ASCII код для вывода на экран.

3)Сохранить символ для последующего вывода.

4)Подсчитать номер прохождения цикла (число запоминаемых цифр).

5)Перенести в N определенное выше частное.

6)Если частное <> 0, то повторить с пункта 1.

7)Извлекать в обратной последовательности цифры результата и выводить их на экран.

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

an p n +an −1 p n −1 + a2 p 2 +a1 p1 +a0

откуда по схеме Горнера получается более эффективная по простоте последующей реализации формула вычислений

(( ((an ×p +an −1 ) ×p +an −2 ) a2 ) ×p +a1 ) ×p +a0

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

15

Источник: https://studfile.net/preview/16469866/