Системное программное обеспечение Лекция № 6 «Расширение системы команд в процессорах 80286 и 80386» Расширение системы команд в процессоре 80286 В систему команд процессора 80286 был введен ряд специальных команд, которые можно разбить на следующие группы: 1. Команды для использования компиляторами языков высокого уровня, хотя, безусловно, их можно применять в чисто ассемблерном коде. bound regW, memDW Команда bound проверяет, находится ли индекс в заданном диапазоне — и иногда называется проверкой диапазона в языках высокого уровня. Поскольку большинство таких языков выполняет вызов специальных подпрограмм для проверки индексов массивов, использование bound может увеличить скорость программы, сохраняя безопасность проверки диапазонов, которую многие программисты запрещают для увеличения скорости. Расширение системы команд в процессоре 80286 Команда bound требует два операнда. Первый из операндов должен быть 16-битовым регистром и должен содержать проверяемое индексное значение. Второй операнд - это адрес 32битового двойного слова в памяти, содержащего младшее и старшее значение диапазона индекса. Если величина первого операнда не входит в установленный диапазон, процессор осуществляет прерывание 5. В программе необходимо установить соответствующую процедуру перехвата и обслуживания этого прерывания. Прерывание 5 в BIOS – это печать экрана, что приводит к конфликту: если при проверке индекса он оказывается за пределами диапазона, а клавиша <PrtScr> не запрещена, то возникновение ошибки приведет к печати содержимого экрана и будет происходить снова и снова, до тех пор пока не будет перезагружена система. Расширение системы команд в процессоре 80286 Эта команда не меняет флаги. ; в сегменте данных BoundMas label word Low_Bound dw 0 Upp_Bound dw 20 mas 10 dup (?) dw ; в сегменте кода xor di,di ;очистка индексного регистра mov ax,mas[di] add di,2 bound di,BoundMas cycl: ;перебор элементов массива ; если значение в di не будет попадать в границы, то будет вызван ; обработчик прерывания 5, где можно скорректировать ; значение ip в стеке с тем, чтобы выйти ; из бесконечного цикла, например, на метку М2 или ; выполнить другие действия jmp М2: cycl Расширение системы команд в процессоре 80286 enter n, level Команда предназначена для выделения соответствующего пространства в стеке для локальных переменных процедуры. Такие переменные динамические — они существуют только во время работы подпрограммы. Эти методы обычно применяются в языках высокого уровня как составная часть их методов использования функций и процедур, но при желании их можно применять и в чисто ассемблерном коде. Команда enter обычно первая строка процедуры. enter требует двух операндов, каждый из которых должен быть числом. Первый операнд представляет собой число байтов, которые необходимо зарезервировать в стеке. Второй операнд представляет собой уровень вложения процедуры. Расширение системы команд в процессоре 80286 Если 3 процедуры включаются одна в другую, самая внутренняя находится на уровне 2, средняя — на уровне 1, а внешняя — на уровне 0. Уровни вложения нужны для поддержки таких языков, как Паскаль, который позволяет дочерним процедурам получать доступ к локальным переменным, описанным в родительских процедурах. Команда enter аналогична трем командам процессора 8086: push bр ; Сохранить текущее значение bр mov bp,sp ; Записать указатель стека в bр sub sp,n ; Выделить стековое пространство для переменных Вначале bр засылается в стек для сохранения его исходной величины. Затем в bр устанавливается значение указателя стека sp, что позволит командам использовать регистр для адресации локальных переменных. Затем выделяется место под переменные путем вычитания первого параметра команды enter из указателя стека. Расширение системы команд в процессоре 80286 В любой процедуре, использующей enter, перед выходом из процедуры командой ret необходимо выполнить команду leave для освобождения стекового пространства, выделенного enter, и для восстановления sp и bр. Команда leave выполняет те же действия, что и две команды процессора 8086: mov sp,bp ; Восстановить указатель стека из bр pop bр ; Восстановить значение bр Копирование bр в sp освобождает пространство, занятое в стеке перед восстановлением величины bр, которая могла использоваться другими процедурами для адресации их собственных локальных переменных. В качестве примера полной процедуры, использующий enter и leave, можно привести подпрограмму: Расширение системы команд в процессоре 80286 proc1 proc ;зарезервировать в стеке место для локальных переменных ;proc1 16 байт ;лексический уровень вложенности 0 enter 16,0 ... leave ret proc1 endp Эти команды не меняют флаги. 2. Новые команды для работы со стеком. Команда pusha сохраняет регистры ах, cx, dx, bx, sp, bp, si и di в стеке в перечисленном порядке. Обратите внимание, что указатель стека также сохраняется. Но величина sp, копируемая соответствует значению sp перед выполнением pusha. в стек, Расширение системы команд в процессоре 80286 Команда рора удаляет все регистры основного назначения из стека. Выполнение рора (обычно после предшествующей pusha) извлекает регистры di, si, bp, sp, bx, dx, cx и ax в соответствующем порядке. Все регистры общего назначения восстанавливают значения, которые они имели перед выполнением предыдущей команды pusha. Сегментные регистры не сохраняются и не восстанавливаются командами pusha и рора. Обычно это необходимо в начале и конце процедур обслуживания прерываний, хотя можно использовать эти команды и в простых процедурах. Эти команды не меняют флаги. Расширение системы команд в процессоре 80286 3. Команды ввода-вывода строк в порты Синтаксис команд аналогичен описанию примитивов команд обработки строк. ins dest, port Команда вводит данные из порта ввода-вывода, номер которого загружен в регистр dx, в память по адресу es:[di]. Сегментная составляющая адреса должна быть обязательно в регистре es. Замена сегментного регистра недопустима. Непосредственное задание порта в команде также недопустимо - для этого используется регистр dx. Размеры вводимых элементов (байт или слова) зависят от способа описания приемника в программе на Ассемблере. Транслятор, обработав команду ins и выяснив тип операнда, генерирует одну из машинных команд: Расширение системы команд в процессоре 80286 insb insw Как и в других командах обработки машинного аналога для команды ins нет. Пример. ; в сегменте данных str_10 db 10 dup(0) adr_str dd str_10 ; в сегменте кода les di,adr_str mov dx,300h mov cx,10 rep insb строк Расширение системы команд в процессоре 80286 outs port, src Команда выводит данные в порт ввода-вывода, номер которого загружен в регистр dx, из памяти по адресу ds:[si]. Замена сегментного регистра допустима. Непосредственное задание порта в команде недопустимо - для этого используется регистр dx. Размеры выводимых элементов (байт или слова) зависят от способа описания источника в программе на Ассемблере. Транслятор, обработав команду outs и выяснив тип операнда, генерирует одну из машинных команд: outsb outsw Как и в других командах обработки строк машинного аналога для команды outs нет. Расширение системы команд в процессоре 80286 Пример. ; в сегменте данных str_10 db 10 dup(0) adr_str dd str_10 lds si, adr_str mov dx, 300h mov cx, 10 rep outsb Эти команды не меняют флаги. 4. Модификация команд сдвига и циклического сдвига. Малозаметным улучшением в командах 80286 является возможность устанавливать величины непосредственного сдвига и циклического сдвига, большие, чем на 1. Это означает, что команды 8086: Расширение системы команд в процессоре 80286 mov shl cl, 4 ax, cl могут быть упрощены: shl ах,4 Такое же изменение применимо ко всем командам сдвига и циклического сдвига процессора 8086. При необходимости можно попрежнему указывать значение сдвига в cl. Расширение системы команд в процессоре 80386 В процессоре 80386 введены новые команды, позволяющие работать с 32-разрядными данными. Их можно разделить на следующие группы: 1. Команды битового сканирования и проверки битов bsf dest, src (Bit Scan Forward — битовое сканирование вперед) Используется для установки в 16- или 32-разрядный регистр приемника номера позиции первого ненулевого бита в байте, слове или двойном слове источника. Флаг zf при этом равен 0. Источником может быть регистр или ячейка памяти. Сканирование проходит от младшего бита к старшему. Если не найдено ни одного единичного бита, флаг zf устанавливается в 1 и содержимое приемника не меняется. Расширение системы команд в процессоре 80386 bsr dest, src (Bit Scan Reverse — обратное битовое сканирование) То же самое, что bsf, но только сканирование в обратном направлении от старшего бита к младшему. Одним из способов использования этих команд может быть установка в cl числа битов, необходимых для сдвига единичного бита в позицию нулевого бита. Например: mov dx, 00100000b bsf сx, dx jz short AllZero shr dx, cl AllZero: А теперь случай, когда больше, чем один бит, установлен в 1: Расширение системы команд в процессоре 80386 mov bx, 00010110b bsf cx, bx bsr cx, bx ; cx = 1 ; cx = 4 bt dest, src (Bit Test — проверка бита) Копирует бит приемника, номер которого указан в источнике, в флаг переноса cf. Каждый из операндов может быть 16- или 32разрядным регистром; второй операнд может задаваться непосредственным значением. Приемник может быть 16- или 32разрядной ячейкой памяти, а источник непосредственным значением. btс dest, src (Bit Test and Complement — проверка бита с инверсией) То же самое, что bt, но только бит приемника после копирования в флаг переноса cf меняет значение на противоположное. Расширение системы команд в процессоре 80386 btr dest, src (Bit Test and Reset — проверка бита с его сбросом в 0) То же самое, что bt, но только бит приемника после копирования в флаг переноса cf сбрасывается в 0. bts dest, src (Bit Test and Set — проверка бита с его установкой в 1) То же самое, что bt, но только бит приемника после копирования в флаг переноса cf устанавливается в 1. mov dx,01010011b bt dx,4 ;проверка состояния бита 4 и установка cf в 1 jc m1 ;перейти на m1, если проверяемый бит равен 1 2. Команды конвертирования данных В дополнение к cbw и cwd можно использовать: Расширение системы команд в процессоре 80386 cdq (Convert Double word to Quad word — преобразование двойного слова в учетверенное слово), для того чтобы конвертировать 32-битовое двойное слово со знаком в eax в 64-битовое четверное слово со знаком в паре регистров edx:eax путем копирования значения старшего бита регистра eax на все биты регистра edx и cwde (Convert Word to Double Word Extended — преобразование слова в двойное слово) для конвертации слова со знаком в ax в двойное слово со знаком в расширенный аккумулятор еах путем копирования значения старшего бита регистра ax на все биты старшего слова регистра еах. Эти команды не влияют на флаги. Расширение системы команд в процессоре 80386 mov cdq idiv eax,delimoe delitel ;частное в eax, остаток в edx movsx dest, src (MOVe and Sign eXtension — пересылка со знаковым расширением) преобразует элемент со знаком меньшей размерности в эквивалентный ему элементы со знаком большей размерности путем распространения значения знакового разряда источника на свободные старшие разряды приемника. movzx dest, src (MOVe and Zero eXtension — пересылка с нулевым расширением) то же самое, что и movsx, но для чисел без знака. При этом двоичный нуль распространяется на свободные старшие разряды приемника. Эти команды также не влияют на флаги. Расширение системы команд в процессоре 80386 Для обеих команд первый операнд должен быть 16- или 32битовым расширенным регистром. Второй операнд может быть 8либо 16-битовым регистром или указателем на память. mov al, 0ffh movsx bx, al ;bx=0ffffh 3. Команды для загрузки сегментных регистров Позволяют получить логический адрес в виде сегментной составляющей и смещения. lfs dest, src (Load pointer into fs segment register — загрузка сегментного регистра fs указателем из памяти) Алгоритм работы команды зависит от действующего режима адресации (16- или 32-разрядной): Расширение системы команд в процессоре 80386 • если 16-разрядный, то первые два байта из ячейки памяти источника загружаются в 16-разрядный регистр, указанный операндом приемник. Следующие два байта источника загружаются в регистр fs; • если 32-разрядный, то первые четыре байта из ячейки памяти источника заргужаются в 32-разрядный регистр, указанный операндом приемник. Следующие два байта источника загружаются в регистр fs. lgs dest, src (Load pointer into gs segment register — загрузка сегментного регистра gs указателем из памяти) То же самое, что lfs, только загружается сегментный регистр gs. Расширение системы команд в процессоре 80386 lss dest, src (Load pointer into ss segment register — загрузка сегментного регистра ss указателем из памяти) То же самое, что lfs, только загружается сегментный регистр ss. Все команды не влияют на флаги. Третья команда — lss позволяет, как частный случай, инициализировать одновременно ss и sp. Одним подхватывание из способов адреса монстрирует пример. применения альтернативного lss стека, является как де- Расширение системы команд в процессоре 80386 mov mov lss . . . mov mov oldss, ss oldsp, sp sp, newstack ; Сохранение старого стекового сегмента ; и старого указателя стека ; Загрузка ss:sp новыми значениями sp, oldsp ss, oldss ; Восстановление sp ; Восстановление ss 4. Команды для работы со стеком pushad (PUSH All general Double word registers onto stack — размещение всех регистров общего назначения в стеке) Размещает в стеке регистры общего назначения в следующей последовательности: eax, ecx, edx, ebx, esp, ebp, esi, edi. Величина сохраненного esp равна величине указателя стека до выполнения pushad. Расширение системы команд в процессоре 80386 popad (POP All general Double word registers from the stack — извлечение всех регистров общего назначения из стека) Извлекает из стека регистры общего назначения в следующей последовательности: edi, esi, ebp, esp, ebx, edx, ecx, eax. Регистр esp по-прежнему восстанавливается тем же значением, которое он имел до pushad. Команды не влияют на флаги. pushfd (PUSH eFlags Double word register onto stack — размещение расширенного регистра флагов в стеке) Размещает в стеке содержимое регистра флагов eflags. Расширение системы команд в процессоре 80386 popfd (POP eFlags Double word register from the stack — извлечение расширенного регистра флагов из стека) Извлекает из стека содержимое регистра флагов eflags. Действие на флаги аналогично командам pushf и popf с учетом 32-разрядного расширения. 5. Set-команды Набор команд, общий синтаксис которых, может быть представлен следующим образом: setcc dest (byte SET on condition — установка байта по условию) Расширение системы команд в процессоре 80386 Установка приемника (байтового регистра или ячейку памяти) логическим значением (0 или 1) в зависимости от истинности условия, заданного модификатором кода операции cc. Окончание cc у set такие же, как и у команд условного перехода: seta, setae, setb, setbe и т.д. Пример: ;подсчитать число единичных битов в регистре ax m1: mov cx,16 mov bh,0 rol ax,1 setc bl add bh,bl clc loop m1 Расширение системы команд в процессоре 80386 6. Сдвиги двойной точности shld dest, src, cnt (SHift Left Double word — cдвиг двойного слова влево) Первый операнд определяет приемник результата и может быть регистром слова либо двойного слова или ссылкой на память. Второй операнд, который должен быть регистром слова или двойного слова, содержит биты, сдвигаемые в первый операнд. Сам он при этом не меняется. Третий операнд представляет собой число битов, которые надо сдвинуть влево. Этот операнд может быть конкретной величиной от 0 до 31 или же регистром cl. shrd dest, src, cnt (SHift Right Double word — cдвиг двойного слова вправо) То же самое, что shld, только сдвиг вправо. Расширение системы команд в процессоре 80386 Пример показывает типичное использование shld. ; в сегменте данных v1 dd 00012345h v2 dd 6789ABCDh ; в сегменте кода mov сl, 8 mov eax, v2 shld v1, eax, cl shl v2, cl ; v1 = 01234567 ; v2 = 89ABCD00 Два двойных слова, vl и v2, образуют в памяти 64-битовую переменную. Только четыре инструкции требуются для сдвига этой переменной влево на любое число битов — в данном примере на 8. Прежде всего в cl загружается счетчик сдвига. Затем вторая часть значения загружается в еах. Инструкция shld сдвигает биты из еах в v1, которое также сдвигается влево равное число раз. Инструкция shl завершает сдвиг, сдвигая v2 в соответствии с этим же счетчиком, хранящимся в cl. Эффективным результатом является умножение за очень короткий промежуток времени полного 64-битового значения двойной точности на 28 (256 десятичное). Расширение системы команд в процессоре 80386 7. Команды обработки строк Во все примитивы команд обработки строк процессоров 8086 и 80286 добавлются команды для работы со строками, состоящими из двойных слов: movsd – копировать строку двойных слов; cmpsd – сравнение строк двойных слов; scasd – сканировать строку двойных слов; lodsd – загрузить строку двойных слов; stosd – сохранить строку двойных слов; insd – ввести строку двойных слов из порта; outsd - вывести строку двойных слов в порт.