Связь ассемблера с языками высокого уровня 


Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Связь ассемблера с языками высокого уровня



Существуют следующие формы комбинирования программ на языках высокого уровня с ассемблером:

· Использование ассемблерных вставок (встроенный ассемблер, режим inline). Ассемблерные коды в виде команд ассемблера вставляются в текст программы на языке высокого уровня. Компилятор языка распознает их как команды ассемблера и без изменений включает в формируемый им объектный код. Эта форма удобна, если надо вставить небольшой фрагмент.

· Использование внешних процедур и функций. Это более универсальная форма комбинирования. У нее есть ряд преимуществ:

o написание и отладку программ можно производить независимо;

o написанные подпрограммы можно использовать в других проектах;

o облегчаются модификация и сопровождение подпрограмм.

Встроенный ассемблер

При написании ассемблерных вставок используется следующий синтаксис:

1 способ:

_asm код_операции операнды; // комментарии

код_операции задает команду ассемблера, операнды – это операнды команды. В конце записывается «;», как и в любой команде языка Си. Комментарии записываются в той форме, которая принята для языка Си.

2 способ:

_asm 

{

 текст программы на ассемблере; комментарии

}

Текст программы пишется с использованием синтаксиса ассемблера, при необходимости можно использовать метки и идентификаторы. Комментарии в этом случае можно записывать как после «;», так и после «//».

В качестве примера рассмотрим программу, которая запрашивает ввод чисел a и b и вычисляет выражение a+5b. Для вывода приглашений Введите a: и Введите b: используем функцию CharToOem(_T("Введите "),s), где s – указатель на перекодированную строку, которая перекодирует русскоязычные сообщения.

#include <windows.h>

#include <tchar.h>

void main()

{

char s[20];

int a,b, sum;

CharToOem(_T("Введите "),s);

printf("%s a: ", s);

scanf("%d",&a);

printf("%s b: ",s);

scanf("%d",&b);

_asm mov eax, a;

_asm

{  

mov ecx, 5

m: add eax, b

loop m

    mov sum, eax

}

printf("\n %d + 5*%d = %d",a,b,sum);

getch();

}

Для компиляции программы создаем проект FileàNewàProject типа Win32 Console Application. Далее в мастере указываем создание пустого проекта (Empty Project) и добавляем файл программы с расширением.c. В результате выполнения программы появится консольное окно:

Использование внешних процедур

Для связи посредством внешних процедур возможны два варианта вызова:

· программа на языке высокого уровня вызывает процедуру на языке ассемблера;

· программа на языке ассемблера вызывает процедуру на языке высокого уровня.

Чаще используется первый способ.

Транслятор MASM генерирует подчеркивание перед именем процедуры автоматически (в отличие от TASM), если в начале программы устанавливается тип вызова stdcall (Standard Call, т.е. стандартный вызов).

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

Соглашение Параметры Очистка стека Регистры
Pascal (конвенция языка Паскаль) Слева направо Процедура Нет
C (конвенция С) Справа налево Вызывающая программа Нет
Fastcall (быстрый или регистровый вызов) Слева направо Процедура Задействованы три регистра (EAX,EDX,ECX), далее стек
Stdcall (стандартный вызов) Справа налево Процедура Нет

Конвенция Pascal заключается в том, что параметры из программы на языке высокого уровня передаются в стеке и возвращаются в регистре АХ/ЕАХ, — это способ, принятый в языке PASCAL (а также в BASIC, FORTRAN, ADA, OBERON, MODULA2), — просто поместить параметры в стек в естественном порядке. В этом случае запись

some_proc(a,b,c,d,e)

превращается в

    push a

push b

push с

push d

push e

call some_proc

Процедура some_proc, во-первых, должна очистить стек по окончании работы (например, завершившись командой ret 20) и, во-вторых, параметры, переданные ей, находятся в стеке в обратном порядке:

some_proc proc

       push  ebp

       mov   ebp,esp; создать стековый кадр

a   equ   [ebp+24]

b           equ   [ebp+20]

c      equ   [ebp+16]

d      equ   [ebp+12]

e      equ   [ebp+8]

   ...

    pop ebp

    ret 20

some_proc endp

Этот код в точности соответствует усложненной форме директивы proc, которую поддерживают все современные ассемблеры:

some_proc proc PASCAL, а:dword, b:dword, с:dword, d:dword, e:dword

...

       ret

some_proc endp

Главный недостаток этого подхода — сложность создания функции с изменяемым числом параметров, аналогичных функции языка С printf. Чтобы определить число параметров, переданных printf, процедура должна сначала прочитать первый параметр, но она не знает его расположения в стеке. Эту проблему решает подход, используемый в С, где параметры передаются в обратном порядке.

Конвенция С используется, в первую очередь, в языках С и C++, а также в PROLOG и других. Параметры помещаются в стек в обратном порядке, и, в противоположность PASCAL-конвенции, удаление параметров из стека выполняет вызывающая процедура. Запись

some_proc(a,b,c,d,e)     

превращается в

push e

push d

push с

push b

push a

call some_proc

add esp,20; освободить стек

Вызванная таким образом процедура может инициализироваться так:

some_proc proc

push ebp

mov ebp,esp; создать стековый кадр

a equ [ebp+8] 

b equ [ebp+12]

с equ [ebp+16]

d equ [ebp+20]

e equ [ebp+24]

...

pop ebp

ret 20

some_proc endp

Ассемблеры поддерживают и такой формат вызова при помощи усложненной формы директивы proc с указанием языка С:

some_proc proc С, а:dword, b:dword, с:dword, d:dword, e:dword

...

       ret

some_proc endp

Регистр EВР используется для хранения параметров, и его ни в коем случае нельзя изменять.

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

Смешанные конвенции

Существует конвенция передачи параметров STDCALL, отличающаяся и от С, и от PASCAL-конвенций, которая применяется для всех системных функций Win32 API. Здесь параметры помещаются в стек в обратном порядке, как в С, но процедуры должны очищать стек сами, как в PASCAL.

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

some_proc(a,b,с,d,e,f);

первые три параметра передаются соответственно в ЕАХ, EDX, ЕСХ, а только начиная с четвертого, параметры помещают в стек в обычном обратном порядке:

d equ [bp+8]

e equ [bp+12]

f equ [bp+16]

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

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

Тип возвращаемого значения Регистр
unsigned char al
char al
unsigned int eax
int eax
unsigned long int edx:eax
long int edx:eax

Как видим из таблицы, возвращаемое значение функции по умолчанию находится в регистре AL/ AX/ EAX/ EDX:EAX.

Рассмотрим пример: Умножить на 2 первый элемент массива.

//Вызывающая программа

#include <windows.h>

#include <tchar.h>

void main()

{

extern int MAS_FUNC (int *,int);

int *mas, i, n, k;

char s[30];

CharToOem(_T("Введите размер массива: "),s);

printf(s);

scanf("%d",&n);

mas = (int*) calloc(n,sizeof(int));

CharToOem(_T("Введите элементы массива: "),s);

printf(s);

for(i=0; i<n; i++)

{   

 printf("mas[%d]= ",i);

 scanf("%d",mas+i);

}

k = MAS_FUNC(mas, n);

printf("mas[1]*2 = %d",k);

getch();

}

 

;Вызываемая функция

.586

.MODEL FLAT, C

.CODE

MAS_FUNC PROC C mas:dword, n:dword

mov esi,mas

mov eax, [esi+4]

shl eax, 1

ret

MAS_FUNC ENDP

END

Результатом работы программы будет окно консоли.

Перед вызовом процедуры всегда нужно сохранять содержимое регистров  ebp, esp, а перед выходом из процедуры – восстанавливать содержимое этих регистров. Это делается компилятором языка Си. Остальные регистры нужно сохранять при необходимости (если содержимое регистра подвергается изменению в вызванной процедуре, а далее может использоваться в вызывающей программе) Это может быть сделано с помощью команды pusha.

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

Для компиляции проекта, состоящего из двух модулей, написанных на разных языках, в Visual Studio необходимо:

1) Создать проект FileàNew Project типа Windows Console Application с дополнительной опцией Empty Project.

2) Добавить файлы Source FilesàAdd Item в дереве проекта. Файл вызывающей программы (на языке Си) должен иметь расширение.c, а не.cpp. У файла с функцией на ассемблере также явно указывается расширение.asm.

3) Для установки «инструмента» трансляции файла на ассемблере выбираем в дереве проекта по правой кнопке Custom Build Rules… и указываем Microsoft Macro Assembler галочкой.

4) Скомпилировать проект BuildàBuild имя проекта.

5) Запустить программу DebugàStart Debugging или F5.

 

Обработка прерываний

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

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

В зависимости от источника прерывания классифицируют так:

· аппаратные — возникают как реакция микропроцессора на физический сигнал от некоторого устройства компьютера (клавиатура, системный таймер, жесткий диск и т.д.); по времени возникновения эти прерывания асинхронны, то есть возникают в случайные моменты времени;

· программные — вызываются искусственно с помощью соответствующей команды из программы (команда int); предназначены для выполнения некоторых действий операционной системы; являются синхронными;

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

СОЗДАНИЕ ИСПОЛНЯЕМОГО ФАЙЛА

Трансляция модуля на ассемблере проходит две стадии.

Двум стадиям трансляции соответствуют две основные программы MASM: ассемблер ML.EXE и редактор связей LINK.EXE.

Исполняемым форматом в Windows является формат PE. Сокращение PE означает Portable Executable, т.е. переносимый исполняемый формат. Этот формат имеют как ЕХЕ-файлы, так и динамические библиотеки (.DLL). Фирма Microsoft ввела «новый» формат и для объектных модулей - это COFF-формат (COFF - Common Object File Format).

1 стадия

Программа ассемблера ML.EXE имеет синтаксис:

ML [параметры] имя_файла.asm [/link опции_редактора_связей]

Атрибут [параметры] может принимать следующие значения:

Параметр Комментарий
/?, /help Вывод помощи.
/AT Создать файл в формате.СОМ. Для программирования в Windows этот ключ, естественно, бесполезен.
/Bl<linker> Использовать альтернативный компоновщик. Предполагается автоматический запуск компоновщика.
/c Компиляция без компоновки.
/Ср Сохранение регистров пользовательских идентификаторов. Может использоваться для дополнительного контроля.
/Cu Приведение всех пользовательских идентификаторов к верхнему регистру.
/Сх Сохранение регистров пользовательских идентификаторов, объявленных PUBLIC и EXTERNAL.
/coff Создание объектных файлов в стандарте coff. Применение обязательно.
/D<name>=[строка] Задание текстового макроса. Очень удобен для отладки с использованием условной компиляции.
/ЕР Листинг: текст программы с включаемыми файлами.
/F <hex> Размер стека в байтах. Размер стека по умолчанию равен 1 Мб.
/Fe<file> Имя исполняемого файла. Имеет смысл без параметра /с.
/Fl<file> Создать файл листинга.
/Fm<file> Создать map-файл. Имеет смысл без опции /с.
/Fo<file> Задать имя объектного файла.
/Fpi Включение кода эмулятора сопроцессора. Начиная с 486-ого микропроцессора, данный параметр потерял актуальность.
/Fr<file> Включить ограниченную информацию браузера.
/FR<file> Включить полную информацию браузера.
/G<c|d|z> Использовать соглашение вызова Паскаль, Си, stdcall.
/H<number> Установить максимальную длину внешних имен.
/I<name> Добавить путь для inc-файлов. Допускается до 10 опций /I.
/link <opt> Опции командной строки компоновщика. Имеет смысл без опции /с.
/nologo Не показывать заголовочный текст компилятора.
/Sa Листинг максимального формата.
/Sc Включить в листинг синхронизацию.
/Sf Листинг первого прохода.
/Sl<number> Длина строки листинга.
/Sn Не включать в листинг таблицу символов.
/Sp<number> Высота страницы листинга.
/Ss<string> Текст подзаголовка листинга.
/St<string> Текст заголовка листинга.
/Sx Включить в листинг фрагменты условной компиляции.
/Ta<file> Для компилирования файлов, расширение которых не.asm.
/W<number> Устанавливает перечень событий компиляции, трактуемые как предупреждения.
/WX Трактовать предупреждения как ошибки.
/w Тоже что /W0 /WX.
/X Игнорировать путь, установленный переменной окружения INCLUDE.
/Zd Отладочная информация состоит только из номеров строк.
/Zf Объявить все имена PUBLIC.
/Zi Включить полную отладочную информацию.
/Zm Включить совместимость с MASM 5.01.
/Zp<n> Установить выравнивание структур.
/Zs Выполнять только проверку синтаксиса.

Параметр [/link опции_редактора_связей] предполагает автоматический запуск редактора связей (2 стадия трансляции) при успешном получении объектного модуля. Компиляция без компоновки осуществляется с использованием параметра /c.

В Visual Studio параметры командной строки ассемблера можно посмотреть в окне Properties проекта после выбора «инструмента» Microsoft Macro Assembler.

2 стадия

Программа LINK.EXE имеет синтаксис:

LINK [параметры] [файлы] [@файл_параметров]

 

Атрибут [параметры] может принимать следующие значения:

Параметр Комментарий
/ALIGN:number Определяет выравнивание секций в линейной модели. По умолчанию 4096.
/BASE:{address| @filename,key} Определяет базовый адрес (адрес загрузки). По умолчанию для ЕХЕ-программы адрес 0х400000, для DLL — 0х10000000.
/COMMENT:["]comment["] Определяет комментарий, помещаемый в заголовок ЕХЕ- и DLL-файлов.
/DEBUG Создает отладочную информацию для ЕХЕ- и DLL-файлов. Отладочная информация помещается в pdb-файл.
/DEBUGTYPE:{CV|COFF| BOTH} CV — отладочная информация в формате Microsoft, COFF — отладочная информация в формате COFF (Common Object File Format), BOTH — создаются оба вида отладочной информации.
/DEF:filename Определяет DEF-файл (файл определений).
/DEFAULTLIB:library Добавляет одну библиотеку к списку используемых библиотек.
/DLL Создать DLL-файл.
/DRIVER[:{UPONLY|WDM}] Используется для создания NT-драйвера (Kernel Mode Driver).
/ENTRY:symbol Определяет стартовый адрес для ЕХЕ- и DLL-файлов.
/EXETYPE:DYNAMIC Данная опция используется при создании VxD-драйвера.
/EXPORT:entryname [=internalname] [,@ordinal[,NONAME]] [,DATA] Данная опция позволяет экспортировать функцию из вашей программы так, чтобы она была доступна для других программ. При этом создается import-библиотека.
/FIXED[:NO] Данная опция фиксирует базовый адрес, определенный в опции /BASE.
/FORCE[:{MULTIPLE| UNRESOLVED}] Позволяет создавать исполняемый файл, даже если не найдено внешнее имя или имеется несколько разных определений.
/GPSIZE:number Определяет размер общих переменных для MIPS и Alpha платформ.
/HEAP:reserve[,commit] Определяет размер кучи (HEAP) в байтах. По умолчанию этот размер равен одному мегабайту.
/IMPLIB:filename Определяет имя import-библиотеки, если она создается.
/INCLUDE:symbol Добавляет идентификатор к таблице имен.
/INCREMENTAL:{YES|NO} Если установлена опция /INCREMENTAL:YES, то в ЕХЕ добавляется дополнительная информация, позволяющая быстрее перекомпилировать этот файл. По умолчанию это информация не добавляется.
/LARGEADDRESSAWARE[:NO] Указывает, что приложение оперирует адресами, большими 2 Гб.
/LIBPATH:dir Определяет библиотеку, которая в первую очередь разыскивается компоновщиком.
/MACHINE: {ALPHA|ARM|IX86|MIPS|MIPS16|MIPSR41XX|PPC|SH3 |SH4} Определяет платформу. В большинстве случаев это делать не приходится.
/MAP[:filename] Дает команду создания МАР-файла.
/MAPINFO:{EXPORTS|FIXUPS|LINES} Указывает компоновщику включить соответствующую информацию в МАР-файл.
/MERGE:from=to Объединить секцию "from" с секцией "to" и присвоить имя "to".
/NODEFAULTLIB[:library] Игнорирует все или конкретную библиотеку.
/NOENTRY Необходимо для создания DLL-файла.
/NOLOGO Не выводить начальное сообщение компоновщика.
/OPT:{ICF[,iterations] |NOICF|NOREF|NOWIN98|REF| WIN98} Определяет способ оптимизации, которую выполняет компоновщик.
/ORDER:@filename Оптимизация программы путем вставки определенных инициализированных данных (COMDAT).
/OUT:filename Определяет выходной файл.
/PDB: {filename|NONE} Определить имя файла, содержащего информацию для отладки.
/PDBTYPE:{CON[SOLIDATE]| SEPT[YPES]} Определяет тип РDВ-файла.
/PROFILE Используется для работы с профайлером (анализатором работы программы).
/RELEASE Помещает контрольную сумму в выходной файл.
/SECTION:name,[E][R][W][S][D] [K][L][P][X] Данная опция позволяет изменить атрибут секции.
/STACK:reserve[,commit] Определяет размер выделяемого стека. Commit — определяет размер памяти, интерпретируемый операционной системой.
/STUB:filename Определяет STUB-файл, запускающийся в системе MS DOS.
/SUBSYSTEM:{NATIVE |WINDOWS|CONSOLE| WINDOWSCE|POSIX} [,#[.##]] Определяет, как запускать ЕХЕ-файл. CONSOLE — консольное приложение, WINDOWS — обычные WINDOWS-приложения,  NATIVE — приложение для Windows NT, POSIX — создает приложение в POSIX-подсистеме WINDOWS NT.
/SWAPRUN:{CD|NET} Сообщает операционной системе скопировать выходной файл в swap-файл (WINDOWS NT).
/VERBOSE[:LIB] Заставляет выводить информацию о процессе компоновки.
/VERSION:#[.#] Помещает информацию о версии в ЕХЕ-заголовок.
/VXD Создать VXD-драйвер.
/WARN[:warninglevel] Определяет количество возможных предупреждений, выдаваемых компоновщиком.
/WS:AGGRESSIVE Несколько уменьшает скорость выполнения приложения (Windows NT). Операционная система удаляет данное приложение из памяти в случае его простоя.

В Visual Studio параметры командной строки редактора связей можно посмотреть в окне Properties проекта.

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

c:\masm32\bin\ml /c /coff PROG.ASM - в результате появляется модуль PROG.OBJ,

c:\masm32\bin\link /SUBSYSTEM:WINDOWS PROG.OBJ - в результате появляется исполняемый модуль PROG.EXE.

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

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

· определить место логической ошибки;

· определить причину логической ошибки.

С помощью отладчика также возможно:

· выполнение трассировки программы в прямом направлении, то есть последовательное исполнение программы, при котором за один шаг выполняется одна машинная инструкция;

· просмотр и изменение состояния аппаратных ресурсов микропроцессора во время покомандного выполнения программы.

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

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

END имя_метки

· Исходный модуль должен быть оттранслирован с опцией /zi:

c:\masm32\bin\ml /c /coff /Zi PROG.ASM

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

· Компоновка модуля должна быть произведена с опцией /DEBUG:

c:\masm32\bin\link /SUBSYSTEM:WINDOWS /DEBUG PROG.OBJ

Опция /DEBUG указывает на необходимость сохранения отладочной информации в исполняемом файле.

Для отладки программы как в комбинированном проекте с использованием нескольких языков программирования, так и в проекте программы на ассемблере, можно использовать встроенную среду отладки Microsoft Visual Studio.

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

Запустить программу на выполнение в отладчике можно в одном из четырех режимов:

· режим безусловного выполнения;

· выполнение по шагам;

· выполнение до текущего положения курсора;

· выполнение с установкой точек прерывания.

Режим безусловного выполнения целесообразно применять, когда требуется посмотреть на общее поведение программы. Для запуска программы в этом режиме необходимо нажать клавишу F5 или выбрать меню DebugàStart Debugging. В точках, где необходимо ввести данные, отладчик, в соответствии с логикой работы применяемого средства ввода, будет осуществлять определенные действия. Аналогичные действия отладчик выполняет для вывода данных.

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

Выполнение по шагам применяется для детального изучения работы программы. В этом режиме можно выполнить программу по командам. При этом можно наблюдать результат исполнения каждой команды. Для активизации этого режима нужно нажать клавишу F11 (меню DrbugàStep Into) или F10 (меню DrbugàStep Over). Обе эти клавиши активизируют пошаговый режим; отличие их проявляется в том случае, когда в потоке команд встречаются команды перехода в процедуру call или на прерывание int. При использовании Step Into отладчик осуществит переход на процедуру или прерывание и выполнит их по шагам. Если же используется Step Over, то вызов процедуры или прерывания отрабатывается как одна обычная команда, и управление передается следующей команде программы.

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

Выполнение с установкой точек прерывания позволяет выполнить программу с остановкой ее в строго определенных точках прерывания (breakpoints). Перед выполнением программы необходимо установить эти точки в программе, для чего следует перейти в нужную строку и во всплывающем меню выбрать BreakpointàInsert Breakpoint. В выбранной строке слева появится красный кружок. Установленные ранее точки прерывания можно убрать — для этого нужно выбрать в нужной строке во всплывающем меню BreakpointàDelete Breakpoint  или BreakpointàDisable Breakpoint (неактивная точка останова). После установки точек прерывания программа запускается на безусловное выполнение клавишей F5. На первой точке прерывания программа остановится. Теперь можно посмотреть состояние микропроцессора и памяти, а затем продолжить выполнение программы.

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

- Для просмотра ассемблерного кода исполняемой программы выбрать меню DebugàWindowsàDisasembly;

- для просмотра содержимого регистра выбрать DebugàWindowsàRegisters (содержимое регистров содержится в левом нижнем окне, при изменении значения регистра его цвет становится красным);

- для просмотра значения идентификатора используется меню DebugàWindowsàWatch, где вводится имя идентификатора;

- для просмотра области памяти используется меню DebugàWindowsàMemory, где вводится адрес ячейки памяти.

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

МАТЕМАТИЧЕСКИЙ СОПРОЦЕССОР

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

Архитектура компьютеров на базе микропроцессоров вначале опиралась исключительно на целочисленную арифметику. С ростом мощи, а главное с осознанием разработчиками микропроцессорной техники того факта, что их устройства могут составить достойную конкуренцию своим «большим» предшественникам, в архитектуре компьютеров на базе микропроцессоров стали появляться устройства для обработки чисел с плавающей точкой. В архитектуре семейства микропроцессоров Intel 80x86 устройство для обработки чисел с плавающей точкой появилось в составе компьютера на базе микропроцессора i8086/88 и получило название математический сопроцессор (далее просто сопроцессор). Выбор такого названия был обусловлен тем, что, во-первых, это устройство было предназначено для расширения вычислительных возможностей основного процессора, а, во-вторых, оно было реализовано в виде отдельной микросхемы, то есть его присутствие было необязательным. Микросхема сопроцессора для микропроцессора i8086/88 имела название i8087. С появлением новых моделей микропроцессоров Intel совершенствовались и сопроцессоры, хотя их программная модель осталась практически неизменной. Как отдельные (а, соответственно, необязательные в конкретной комплектации компьютера) устройства, сопроцессоры сохранялись вплоть до модели микропроцессора i386 и имели название i287 и i387 соответственно. Начиная с модели i486, сопроцессор исполняется в одном корпусе с основным микропроцессором и, таким образом, является неотъемлемой частью компьютера.

Перечислим основные возможности сопроцессора:

· полная поддержка стандартов IEEE-754 и 854 на арифметику с плавающей точкой. Эти стандарты описывают как форматы данных, с которыми должен работать сопроцессор, так и набор реализуемых им функций;

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

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

· обработка вещественных чисел из диапазона 3.37х10-4932...1.18х10+4932.

 

Представление чисел с плавающей точкой
в разрядной сетке вычислительной машины

Числа с плавающей точкой представляются в следующей форме

Числа с плавающей точкой могут быть представлены в одном из трех форматов.

знаковое с плавающей точкой ±1.18e-38… 3.4e+38 float (DD)
знаковое с плавающей точкой двойной точности ±2.23e-308… 1.79e+308 double (DQ)
знаковое с плавающей точкой двойной расширенной точности ±3.37e-4932.. 1.18e+4932 long double (DT)

Числа простой и двойной точности (float и double, DD и DQ) могут быть представлены только в нормированной форме. При этом бит целой части числа является скрытым и «подразумевает» 1. Остальные 23 (52) разряда хранят двоичную мантиссу числа.

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

Основным типом данных, которыми оперирует математический сопроцессор, являются 10-байтные данные (DT).

Ниже приведены способы кодировки чисел с плавающей точкой в формате DT.

Тип чисел Знак Степень Целое Мантисса
0 11…11 1 00…00
положительные нормированные 0 00…01 11…10 1 00…00 11…11
положительные ненормированные 0 00…00 0 00…00 11…11
ноль 0,1 00…00 0 00…00
отрицательные ненормированные 1 00…00 0 00…00 11…11
отрицательные нормированные 1 00…01 11…10 1 00…00 11…11
–¥ 1 11…11 1 00…00
Нечисла NaN x 11…11 1 xx…xx ≠0
float   8 бит нет 23 бит
double   11 бит нет 52 бит
long double   15 бит 1 бит 63 бит

Степень числа представляет собой степень числа 2 со сдвигом. Величина сдвига обусловлена необходимостью представления как чисел 1…¥, так и чисел 0…1 и зависит от типа представляемого числа и составляет соответственно

Тип данных Сдвиг десятичный Сдвиг двоичный
float 127 0111 1111
double 1023 011 1111 1111
long double 16383 011 1111 1111 1111

Пример1: Представить число 178,125 в 32-разрядной сетке.

Нормированное число в десятичной системе счисления 178,125 = 1,7825E102.

Для представления числа в двоичной системе счисления преобразуем отдельно целую и дробную части:

17810 = 101100102.

0,12510 = 0,001.

Тогда 178,12510 = 10110010,0012=1,0110010001E2111 (для преобразования в двоичную форму осуществляется сдвиг на 7 разрядов влево).

Для определения степени числа применяем сдвиг 0111111+00000111 = 10000110.

Таким образом, число 178,12510 запишется в разрядной сетке следующим образом:

зн.

степень

Мантисса

0 1 0 0 0 0 1 1 0 0 1 1 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0
                                                               

Пример2: Представить число 12345678,123456710 в 64-разрядной сетке.

Для представления числа в двоичной системе счисления преобразуем отдельно целую и дробную части:

1234567810 = 1011 1100 0110 0001 0100 11102.

0,123456710 = 0,0001 1111 1001 1010 1101 1011 1011 12.

Тогда

12345678,123456710 = 101111000110000101001110,000111111001101011011011101112

или 1,0111 1000 1100 0010 1001 1100 0011 1111 0011 0101 1011 0111 01112E210111

(сдвиг на 23 разрядов влево).

Для определения степени числа применяем сдвиг

011 1111 1111 + 10111 = 10000010110.

Таким образом, число 12345678,123456710 запишется в разрядной сетке следующим образом:

s

степень

мантисса

0 1 0 0 0 0 0 1 0 1 1 0 0 1 1 1 1 0 0 0 1 1 0 0 0 0 1 0 1 0 0 1

мантисса

1 1 0 0 0 0 1 1 1 1 1 1 0 0 1 1 0 1 0 1 1 0 1 1 0 1 1 1 0 1 1 1

 

Архитектура сопроцессора

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

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

1. Восемь регистров r0…r7, составляющих основу программной модели сопроцессора — стек сопроцессора. Размерность каждого регистра 80 битов. Такая организация характерна для устройств, специализирующихся на обработке вычислительных алгоритмов.

2. Три служебных регистра:

· регистр состояния сопроцессора swr (Status Word Register — регистр слова состояния) — отражает информацию о текущем состоянии сопроцессора. В регистре swr содержатся поля, позволяющие определить: какой регистр является текущей вершиной стека сопроцессора, какие исключения возникли после выполнения последней команды, каковы особенности выполнения последней команды (некий аналог регистра флагов основного процессора) и т. д.;



Поделиться:


Последнее изменение этой страницы: 2020-12-09; просмотров: 490; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.21.233.41 (0.123 с.)