Программа ассемблер это: Почему Ассемблер — это круто, но сложно
Содержание
Структура программы на ассемблере
Программирование на уровне машинных команд — это тот минимальный уровень, на котором возможно составление программ. Система машинных команд должна быть достаточной для того, чтобы реализовать требуемые действия, выдавая указания аппаратуре вычислительной машины.
Каждая машинная команда состоит из двух частей:
- операционной — определяющей, «что делать»;
- операндной — определяющей объекты обработки, «с чем делать».
Машинная команда микропроцессора, записанная на языке ассемблера, представляет собой одну строку, имеющую следующий синтаксический вид:
метка команда/директива операнд(ы) ;комментарии
При этом обязательным полем в строке является команда или директива.
Метка, команда/директива и операнды (если имеются) разделяются по крайней мере одним символом пробела или табуляции.
Если команду или директиву необходимо продолжить на следующей строке, то используется символ обратный слеш: \.
По умолчанию язык ассемблера не различает заглавные и строчные буквы в написании команд или директив.
Примеры строк кода:
Count db 1 ;Имя, директива, один операнд
mov eax,0 ;Команда, два операнда
cbw ; Команда
Метки
Метка в языке ассемблера может содержать следующие символы:
- все буквы латинского алфавита;
- цифры от 0 до 9;
- спецсимволы: _, @, $, ?.
В качестве первого символа метки может использоваться точка, но некоторые компиляторы не рекомендуют применять этот знак. В качестве меток нельзя использовать зарезервированные имена Ассемблера (директивы, операторы, имена команд).
Первым символом в метке должна быть буква или спецсимвол (но не цифра). Максимальная длина метки – 31 символ. Все метки, которые записываются в строке, не содержащей директиву ассемблера, должны заканчиваться двоеточием : .
Команды
Команда указывает транслятору, какое действие должен выполнить микропроцессор. В сегменте данных команда (или директива) определяет поле, рабочую область или константу. В сегменте кода команда определяет действие, например, пересылка (mov) или сложение (add).
Директивы
Ассемблер имеет ряд операторов, которые позволяют управлять процессом ассемблирования и формирования листинга. Эти операторы называются директивами. Они действуют только в процессе ассемблирования программы и, в отличие от команд, не генерируют машинных кодов.
Операнды
Операнд– объект, над которым выполняется машинная команда или оператор языка программирования.
Команда может иметь один или два операнда, или вообще не иметь операндов. Число операндов неявно задается кодом команды.
Примеры:
- Нет операндов ret ;Вернуться
- Один операнд inc ecx ;Увеличить ecx
- Два операнда add eax,12 ;Прибавить 12 к eax
Метка, команда (директива) и операнд не обязательно должны начинаться с какой-либо определенной позиции в строке. Однако рекомендуется записывать их в колонку для большего удобства чтения программы.
В качестве операндов могут выступать
- идентификаторы;
- цепочки символов, заключенных в одинарные или двойные кавычки;
- целые числа в двоичной, восьмеричной, десятичной или шестнадцатеричной системе счисления.
Идентификаторы
Идентификаторы – последовательности допустимых символов, использующиеся для обозначения таких объектов программы, как коды операций, имена переменных и названия меток.
Правила записи идентификаторов.
- Идентификатор может состоять из одного или нескольких символов.
- В качестве символов можно использовать буквы латинского алфавита, цифры и некоторые специальные знаки: _, ?, $, @.
- Идентификатор не может начинаться символом цифры.
- Длина идентификатора может быть до 255 символов.
- Транслятор воспринимает первые 32 символа идентификатора, а остальные игнорирует.
Комментарии
Комментарии отделяются от исполняемой строки символом ; . При этом все, что записано после символа точка с запятой и до конца строки, является комментарием. Использование комментариев в программе улучшает ее ясность, особенно там, где назначение набора команд непонятно. Комментарий может содержать любые печатные символы, включая пробел. Комментарий может занимать всю строку или следовать за командой на той же строке.
Структура программы на ассемблере
Программа, написанная на языке ассемблера, может состоять из нескольких частей, называемых модулями. В каждом модуле могут быть определены один или несколько сегментов данных, стека и кода. Любая законченная программа на ассемблере должна включать один главный, или основной, модуль, с которого начинается ее выполнение. Модуль может содержать сегменты кода, сегменты данных и стека, объявленные при помощи соответствующих директив. Перед объявлением сегментов нужно указать модель памяти при помощи директивы . MODEL.
Пример «ничего не делающей» программы на языке ассемблера:
.686P
.MODEL FLAT, STDCALL
.DATA
.CODE
START:
RET
END START
В данной программе представлена всего одна команда микропроцессора. Эта команда RET. Она обеспечивает правильное окончание работы программы. В общем случае эта команда используется для выхода из процедуры.
Остальная часть программы относится к работе транслятора.
.686P — разрешены команды защищенного режима Pentium 6 (Pentium II). Данная директива выбирает поддерживаемый набор команд ассемблера, указывая модель процессора. Буква P, указанная в конце директивы, сообщает транслятору о работе процессора в защищенном режиме.
.MODEL FLAT, stdcall — плоская модель памяти. Эта модель памяти используется в операционной системе Windows. stdcall — используемое соглашение о вызовах процедур.
.DATA — сегмент программы, содержащий данные.
.CODE — блок программы, содержащей код.
START — метка. В ассемблере метки играют большую роль, что не скажешь о современных языках высокого уровня.
END START — конец программы и сообщение транслятору, что начинать выполнение программы надо с метки START.
Каждый модуль должен содержать директиву END, отмечающую конец исходного кода программы. Все строки, которые следуют за директивой END, игнорируются. Если опустить директиву END, то генерируется ошибка.
Метка, указанная после директивы END, сообщает транслятору имя главного модуля, с которого начинается выполнение программы. Если программа содержит один модуль, метку после директивы END можно не указывать.
Назад
Назад: Язык ассемблера
Ассемблер — это… Что такое Ассемблер?
Эта статья — о компьютерных программах. О языке программирования см. Язык ассемблера.
Ассе́мблер (от англ. assembler — сборщик) — компьютерная программа, компилятор исходного текста программы, написанной на языке ассемблера, в программу на машинном языке.
Как и сам язык (ассемблера), ассемблеры, как правило, специфичны для конкретной архитектуры, операционной системы и варианта синтаксиса языка. Вместе с тем существуют мультиплатформенные или вовсе универсальные (точнее, ограниченно-универсальные, потому что на языке низкого уровня нельзя написать аппаратно-независимые программы) ассемблеры, которые могут работать на разных платформах и операционных системах. Среди последних можно также выделить группу кросс-ассемблеров, способных собирать машинный код и исполняемые модули (файлы) для других архитектур и ОС.
Ассемблирование может быть не первым и не последним этапом на пути получения исполнимого модуля программы. Так, многие компиляторы с языков программирования высокого уровня выдают результат в виде программы на языке ассемблера, которую в дальнейшем обрабатывает ассемблер. Также результатом ассемблирования может быть не исполнимый, а объектный модуль, содержащий разрозненные блоки машинного кода и данных программы, из которого (или из нескольких объектных модулей) в дальнейшем с помощью программы-компоновщика может быть скомпонован исполнимый файл.
Архитектура x86
Ассемблеры для DOS
Наиболее известными ассемблерами для операционной системы DOS являлись Borland Turbo Assembler (TASM), Microsoft Macro Assembler (MASM) и Watcom Assembler (WASM). Также в своё время был популярен простой ассемблер A86.
Windows
При появлении операционной системы Windows появилось расширение TASM, именуемое TASM 5+ (неофициальный пакет, созданный человеком с ником !tE), позволившее создавать программы для выполнения в среде Windows. Последняя известная версия TASM — 5.3, поддерживающая инструкции MMX, на данный момент включена в Turbo C++ Explorer. Но официально развитие программы полностью остановлено.
Microsoft поддерживает свой продукт под названием Microsoft Macro Assembler. Она продолжает развиваться и по сей день, последние версии включены в наборы DDK. Но версия программы, направленная на создание программ для DOS, не развивается. Кроме того, Стивен Хатчессон создал пакет для программирования на MASM под названием «MASM32».
GNU и GNU/Linux
В состав операционной системы GNU входит пакет binutils, включающий в себя ассемблер gas (GNU Assembler), использующий AT&T-синтаксис, в отличие от большинства других популярных ассемблеров, которые используют Intel-синтаксис (поддерживается с версии 2. 10).
Переносимые ассемблеры
Также существует открытый проект ассемблера, версии которого доступны под различные операционные системы, и который позволяет получать объектные файлы для этих систем. Называется этот ассемблер NASM (Netwide Assembler).
Yasm — это переписанная с нуля версия NASM под лицензией BSD (с некоторыми исключениями).
flat assembler (fasm) — молодой ассемблер под модифицированной для запрета перелицензирования (в том числе под GNU GPL) BSD-лицензией. Есть версии для KolibriOS, Linux, DOS и Windows; использует Intel-синтаксис и поддерживает инструкции x86-64.
Архитектуры RISC
MCS-51
MCS-51 (Intel 8051) — классическая архитектура микроконтроллера. Для неё существует кросс-ассемблер ASM51, выпущенный корпорацией MetaLink.
Кроме того, многие фирмы — разработчики программного обеспечения, такие как IAR или Keil, представили свои варианты ассемблеров. В ряде случаев применение этих ассемблеров оказывается более эффективным благодаря удобному набору директив и наличию среды программирования, объединяющей в себе профессиональный ассемблер и язык программирования Си, отладчик и менеджер программных проектов.
AVR
На данный момент существуют 3 компилятора производства Atmel (AVRStudio 3, AVRStudio 4, AVRStudio 5 и AVRStudio 6).
В рамках проекта AVR-GCC (он же WinAVR) существует компилятор avr-as (это портированный под AVR ассемблер GNU as из GCC).
Также существует свободный минималистический компилятор avra[1].
ARM
PIC
Пример программы на языке Assembler для микроконтроллера PIC16F628A:
LIST p=16F628A __CONFIG 0309H STATUS equ 0x003 TRISB equ 0x086 PORTB equ 0x006 RP0 equ 5 org 0 goto start start: bsf STATUS,RP0 movlw .00 movwf TRISB bcf STATUS,RP0 led: movlw .170 movwf PORTB goto led end
AVR32
MSP430
Пример программы на языке Assembler для микроконтроллера MSP430G2231 (в среде Code Composer Studio):
. cdecls C,LIST, "msp430g2231.h" ;------------------------------------------------------------------------------ .text ; Program Start ;------------------------------------------------------------------------------ RESET mov.w #0280h,SP ; Initialize stackpointer StopWDT mov.w #WDTPW+WDTHOLD,&WDTCTL ; Stop WDT SetupP1 bis.b #001h,&P1DIR ; P1.0 output ; Mainloop bit.b #010h,&P1IN ; P1.4 hi/low? jc ON ; jmp--> P1.4 is set ; OFF bic.b #001h,&P1OUT ; P1.0 = 0 / LED OFF jmp Mainloop ; ON bis.b #001h,&P1OUT ; P1.0 = 1 / LED ON jmp Mainloop ; ; ;------------------------------------------------------------------------------ ; Interrupt Vectors ;------------------------------------------------------------------------------ . sect ".reset" ; MSP430 RESET Vector .short RESET ; .end
PowerPC
Программный пакет The PowerPC Software Development Toolset от IBM включает в себя ассемблер для PowerPC.
MIPS
Архитектуры MISC
SeaForth
Существуют:
- 8-разрядные Flash-контроллеры семейства MCS-51
- 8-разрядные RISC-контроллеры семейства AVR (ATtiny, ATmega, classic AVR). На данный момент семейство classic AVR трансформировано в ATtiny и ATmega
- 8-разрядные RISC-контроллеры семейства PIC (PIC10,PIC12,PIC16,PIC18)
- 16-разрядные RISC-контроллеры семейства PIC (PIC24HJ/FJ,dsPIC30/33)
- 32-разрядные RISC-контроллеры семейства PIC (PIC32) с архитектурой MIPS32 M4K
- 32-разрядные RISC-контроллеры семейства AVR32 (AVR32)
- 32-разрядные RISC-контроллеры семейства ARM Thumb высокой производительности (серия AT91)
Макроассемблер
Не следует путать с MASM.
Макроассемблер (от греч. μάκρος — большой, обширный) — макропроцессор, базовым языком которого является язык ассемблера.[2]
Ассемблирование и компилирование
Процесс трансляции программы на языке ассемблера в объектный код принято называть ассемблированием. В отличие от компилирования, ассемблирование — более или менее однозначный и обратимый процесс. В языке ассемблера каждой мнемонике соответствует одна машинная инструкция, в то время как в языках программирования высокого уровня за каждым выражением может скрываться большое количество различных инструкций. В принципе, это деление достаточно условно, поэтому иногда трансляцию ассемблерных программ также называют компиляцией.
Примечания
См. также
Литература
- Вострикова З. П. Программирование на языке ассемблера ЕС ЭВМ. М.: Наука, 1985.
- Галисеев Г. В. Ассемблер для Win 32. Самоучитель. — М.: Диалектика, 2007. — С. 368. — ISBN 978-5-8459-1197-1
- Зубков С. В. Ассемблер для DOS, Windows и UNIX.
- Кип Ирвина. Язык ассемблера для процессоров Intel = Assembly Language for Intel-Based Computers. — М.: Вильямс, 2005. — С. 912. — ISBN 0-13-091013-9
- Калашников О. А. Ассемблер? Это просто! Учимся программировать. — БХВ-Петербург, 2011. — С. 336. — ISBN 978-5-9775-0591-8
- Магда Ю. С. Ассемблер. Разработка и оптимизация Windows-приложений. СПб.: БХВ-Петербург, 2003.
- Нортон П., Соухэ Д. Язык ассемблера для IBM PC. М.: Компьютер, 1992.
- Владислав Пирогов. Ассемблер для Windows. — СПб.: БХВ-Петербург, 2002. — 896 с. — ISBN 978-5-9775-0084-5
- Владислав Пирогов. Ассемблер и дизассемблирование. — СПб.: БХВ-Петербург, 2006. — 464 с. — ISBN 5-94157-677-3
- Сингер М. Мини-ЭВМ PDP-11: Программирование на языке ассемблера и организация машины. М.: Мир, 1984.
- Скэнлон Л. Персональные ЭВМ IBM PC и XT. Программирование на языке ассемблера. М. : Радио и связь, 1989.
- Юров В., Хорошенко С. Assembler: учебный курс. — СПб.: Питер, 2000. — С. 672. — ISBN 5-314-00047-4
- Юров В. И. Assembler: учебник для вузов / 2-е изд. СПб.: Питер, 2004.
- Юров В. И. Assembler. Практикум: учебник для вузов / 2-е изд. СПб.: Питер, 2004.
- Юров В. И. Assembler. Специальный справочник. СПб.: Питер, 2000.
Ссылки
Написание резидентных программ для MS DOS
Написание резидентных программ для MS DOS
Написание
резидентных программ для MS DOS
В статье описаны основные
шаги, используемые при написании
резидентных программ на ассемблере
для операционной системы MS DOS. В
конце статьи подробно разобран
пример резидентной программы.
Резидентная программа для
MS DOS представляет собой фрагмент
кода, постоянно находящийся в
оперативной памяти компьютера и
вызываемый при возникновении
определённых условий. Далее будет
показано как написать резидентную
программу на ассемблере, постоянно
находящуюся в памяти и вызываемую
при возникновении в системе
прерываний. Сначала рассмотрим
определения и основные типы
прерываний для процессоров x86.
Прерывание для
процессоров x86 представляет собой
некоторое событие в системе,
нуждающееся в определённой
обработке. При возникновении
прерывания, за исключением одного
случая, выполнение текущей
программы прерывается и происходит
обработка прерывания. После
обработки прерывания продолжается
выполнение прерванной программы.
Для процессоров x86
существуют следующие виды
прерываний: аппаратные,
программные и внутренние
прерывания процессора. Аппаратные
прерывания, в свою очередь,
разделяются на маскируемые и
немаскируемые. Маскируемые
аппаратные прерывания при
определённых условиях могут быть
проигнорированны процессором, а
немаскируемые прерывания
обрабатываются всегда.
Аппаратное прерывание
можно определить как запрос от
некоторого периферийного
устройства (клавиатура,
последовательный порт, дисковод и
т. д.) на обработку данных этого
устройства, управление им или
возникновение исключительной
ситуации для этого устройства. При
возникновении такого запроса
выполнение текущей программы
прерывается (если это прерывание не
замаскировано) и вызывается
процедура обработчика прерывания.
Обработчик прерывания выполняет
необходимые действия для получения
данных от периферийного устройства
или для управления им и возвращает
управление в прерванную программу.
Программные прерывания
представляют собой вызов
каких-либо функций или сервисов
операционной системы и прикладных
программ с использованием команды
INT XX, где XX — номер прерывания от 0 до
255. Внутренние прерывания
процессора возникают при
выполнении программой каких-либо
операций, вызывающих фатальные
ошибки (например, деление на 0,
переполнение при делении, выход за
границы сегмента и т. д.), а также при
использовании режима отладки.
В любом случае, при
возникновении прерывания
какого-либо типа вызывается
обработчик этого прерывания,
который представляет собой
специальным образом оформленную
процедуру. Для аппаратных
прерываний обработчик прерывания
должен помимо работы с устройством,
вызвавшим прерывание, выполнить
некоторые операции по управлению
аппаратурой механизма прерываний
процессора x86.
Рассмотрим процесс
написания процедуры обработчика
прерывания на ассемблере,
вызываемого при возникновении
программного прерывания. Общая
структура и синтаксис для
обработчика программного
прерывания:
NAME proc ; 1. сохранение модифицируемых регистров . . . ; 2. инициализациясегментных регистров . . . ; 3. выполнение необходимых действий . . . ; 4. восстановление используемых регистров . . . IRET NAME ENDP
|
Идентификатор NAME
определяет имя процедуры
обработчика, которое может быть
любой последовательностью
разрешённых в ассемблере символов,
но не должно быть служебным или
зарезервированным словом.
В секции 1 выполняется
сохранение всех регистров,
изменяемых в процедуре
обработчика. Это необходимо для
того, чтобы после возвращения
управления в прерванную программу,
она получила регистры в том же виде,
какими они были до вызова
программного прерывания. Если
прерывание должно возвращать в
вызвавшую его программу некоторые
результаты в регистрах, то
сохранять значение этих регистров
не требуется.
В секции 2 выполняется
инициализация сегментных
регистров DS, ES или SS для обращения
процедуры обработчика прерывания к
своим внутренним данным, стеку или
некоторому дополнительному
сегменту. Значения
инициализируемых регистров должны
быть сохранены в секции 1.
В секции 3, собственно,
выполняется основной код процедуры
обработчика прерывания,
выполняются необходимые действия и
заносятся значения в регистры, если
прерывание должно возвращать в
вызвавшую его программу некоторые
результаты в регистрах.
В секции 4 происходит
восстановление значений для
изменённых процедурой обработчика
прерывания регистров, кроме тех
регистров, в которых вызвавшей
прерывание программе возвращаются
результаты.
Команда IRET выполняет
возврат из процедуры обработчика
прерывания в вызвавшую его
программу.
Рассмотрим подробнее
какие действия выполняют команды INT
и IRET.
Так как при выполнении
команды INT XX должен быть вызван
некоторый обработчик прерывания с
номером XX необходимо по номеру
узнать адрес обработчика в памяти
(сегмент и смещение). Для этого
служит специальная таблица
векторов прерываний,
располагающаяся по адресу 0000:0000 в
оперативной памяти компьютера. Эта
таблица содержит 256
четырёхбайтовых значений,
определяющих адреса обработчиков
прерываний в памяти. Первые 15
четырёхбайтовых значений в таблице
зарезервированны для аппаратных
прерываний (маскируемых и
немаскируемых) и для внутренних
прерываний процессора. Остальные
значения в таблице определяют
адреса обработчиков программных
прерываний. Среди этих значений
есть и такие, которые предназначены
для пользовательских обработчиков
программных прерываний. Первые два
байта для каждой ячейки в таблице
определяют смещение обработчика
соответствующего программного
прерывания. Следующие два байта
определяют сегмент обработчика
прерывания. При вызове команды INT XX
выполняются следующие действия:
В стеке сохраняются в
следующей последовательности:
регистр флагов, сегментный
регистр CS, регистр указателя
команд IP. Сбрасываются флаги IF
и TF в регистре флагов.Вычисляется смещение
относительно начала таблицы
векторов прерываний:
смещение=XX * 4, где XX — номер
прерывания.В сегментный регистр CS
по вычисленному смещению из
таблицы векторов прерываний
заносится значение сегмента
обработчика прерывания, а в
регистр IP — смещение
обработчика прерывания.Происходит передача
управления на обработчик
программного прерывания. При
этом все регистры кроме CS, IP и
регистра флагов сохраняют своё
значение таким, каким оно было
до вызова команды INT XX.
Таким образом, при входе в
обработчик программного
прерывания, в стеке находятся
значения регистров CS, IP и регистра
флагов. Эти значения находились в
данных регистрах до вызова команды
INT XX. В вершине стека располагается
значение регистра IP.
При вызове команды IRET
выполняются следующие действия:
Из стека
восстанавливается значение
регистра IP.Из стека
восстанавливается значение
регистра CS.Из стека
восстанавливается значение
регистра флагов.Происходит передача
управления в прерванную
программу, на команду,
находящуюся непосредственно
за командой программного
прерывания INT XX.
После выполнения команды
IRET структура стека становится
такой же, какой она была до вызова
команды INT XX.
Таковы основные моменты,
используемые при написании
обработчиков программных
прерываний. Рассмотрим теперь
структуру и работу обработчиков
аппаратных прерываний.
В отличие от обработчиков
программных прерываний,
обработчики аппаратных прерываний
вызываются не командой INT, а самим
процессором. Выше было сказано, что
при написании обработчиков
аппаратных прерываний они должны
выполнять ещё и некоторые действия
по управлению аппаратурой
механизма прерываний процессора x86.
В простейшем случае, структура
такого обработчика выглядит
следующим образом:
NAME PROC ; 1. сохранение модифицируемых регистров . . . ; 2. инициализациясегментных регистров . . . ; 3. выполнение необходимых действий . . . ; 4. восстановление используемых регистров . . . MOV AL, 20h OUT 20h, AL IRET NAME endp
|
Команда OUT 20h, AL выполняет
действия по управлению аппаратурой
механизма прерываний процессоров
x86. Конкретно, она посылает сигнал EOI
(End Of Interrupt — конец прерывания) в
контроллер прерываний, сообщая ему
таким образом, что обработка
аппаратного прерывания завершена.
При возникновении
аппаратного прерывания от
некоторого периферийного
устройства контроллер прерываний
выполняет проверку, не
замаскировано ли это прерывание.
Если оно не замаскировано, то
контроллер выполняет сравнение
приоритетов этого прерывания с
другим, если несколько прерываний
поступили в контроллер
одновременно. Если прерывание
замаскировано или заблокировано,
то оно игнорируется контроллером.
После выбора прерывания с более
высоким приоритетом (логика
назначения приоритетов
прерываниям может быть
запрограммирована пользователем)
контроллер посылает сигнал INTR
(Interrupt Request — запрос прерывания) в
процессор. Если в процессоре в
регистре флагов сброшен флаг
прерывания IF, то сигнал INTR
игнорируется. Если флаг IF
установлен, то процессор отвечает
контроллеру сигналом INTA (Interrupt
Acknoledge) на что контроллер, в свою
очередь, посылает процессору номер
вектора прерывания для выбранного
прерывания и блокирует все
прерывания этого и более низкого
приоритета. Процессор по
полученному номеру вектора
прерывания отыскивает в таблице
векторов прерываний адрес
соответствующего обработчика
аппаратного прерывания и вызывает
его.
Команда OUT 20h, AL, вызываемая
в конце обработчика аппаратного
прерывания, разблокирует
контроллер прерываний, разрешая
ему работу с ранее
заблокированными прерываниями.
Если требуется написать
обработчик аппаратного прерывания,
который должен только выполнять
определённые действия при
возникновении аппаратного
прерывания (например, выдавать
звуковой сигнал при нажатии на
любую клавишу), всю работу по
управлению соответствующей
аппаратурой можно возложить на
системный обработчик этого
аппаратного прерывания. В таком
случае, структура обработчика
будет следующей:
SYS_HANDLER DD ? . . . NAME PROC PUSHF CALL CS:SYS_HANDLER ; 1. сохранение модифицируемых регистров . . . ; 2. инициализациясегментных регистров . . . ; 3. выполнение необходимых действий . . . ; 4. восстановление используемых регистров . . . IRET NAME endp
|
Команда CALL CS:OLD_HANDLER
вызывает системный обработчик
нужного аппаратного прерывания,
который выполняет все необходимые
действия по управлению аппаратурой
и контроллером прерываний. OLD_HANDLER
определяет ячейку памяти размером
в двойное слово (4 байта) для
хранения адреса системного
обработчика прерывания. Команда PUSHF
создаёт в стеке структуру для
команды IRET, вызываемой в системном
обработчике. Подобный подход можно
использовать и для программных
прерываний, когда помимо тех
действий, которые выполняет
системный обработчик программного
прерывания (например, INT 10h -
прерывание BIOS) нужно выполнить
какие-либо дополнительные
действия. Также можно определить
структуру обработчика
программного или аппаратного
прерывания, когда системный
обработчик вызывается в конце
процедуры нашего обработчика:
SYS_HANDLER DD ? . . . NAME PROC ; 1. сохранение модифицируемых регистров . . . ; 2. инициализациясегментных регистров . . . ; 3. выполнение необходимых действий . . . ; 4. восстановление используемых регистров . . . JMP SYS_HANDLER NAME endp
|
В этом случае команда JMP
SYS_HANDLER выполняет дальний переход на
системный обработчик прерывания,
поэтому в конце нашего обработчика
не нужно вызывать команду IRET — она
будет вызвана в системном
обработчике.
После того, как определено,
каким образом оформить процедуру
обработчика аппаратного или
программного прерывания,
рассмотрим действия, необходимые
для того, чтобы эта процедура
обработчика вызывалась при
возникновении прерывания.
Как уже было сказано выше,
в оперативной памяти компьютера по
адресу 0000:0000 располагается таблица
векторов прерываний, элементы
которой определяют адреса
обработчиков прерываний в памяти.
Для обработчика программного или
аппаратного прерывания без вызова
системного обработчика нужно лишь
записать в соответствующий элемент
таблицы векторов прерываний
значение сегмента и смещения этого
обработчика. Рассмотрим
необходимые операции для записи
сегмента и смещения в таблицу для
обработчика программного или
аппаратного прерывания с номером N:
MOV AX, 0000H ; запись в ES значения MOV ES, AX ; сегмента 0000h MOV DI, N ; запись в DI номера обработчика MOV CL, 2 ; умножение DI SHL DI, CL ; на 4 MOV AX, OFFSET HANDLER ; запись в AX смещения обработчика STOSW ; сохранение смещения в таблице MOV AX, SEGMENT HANDLER ; запись в AX сегмента обработчика STOSW ; сохранение сегмента в таблице
|
После выполнения этих
действий и при выполнении команды
INT N будет вызван обработчик, адрес
которого был установлен в таблице
векторов прерываний.
Рассмотрим теперь
необходимые операции для установки
сегмента и смещения в таблице для
обработчика программного или
аппаратного прерывания, в котором
будет вызван системный обработчик
этого прерывания. Для этого перед
записью в таблицу новых значений
сегмента и смещения нужно сначала
сохранить значения сегмента и
смещения системного обработчика:
SYS_HANDLER DD ? ; определение ячейки памяти для хранения ; адреса системного обработчика . . . MOV AX, 0000H ; запись в ES значения MOV ES, AX ; сегмента 0000h MOV DI, N ; запись в DI номера обработчика MOV CL, 2 ; умножение DI SHL DI, CL ; на 4 MOV WORD PTR SYS_HANDLER, ES:[DI] ; сохранение смещения системного обработчика MOV AX, OFFSET HANDLER ; запись в AX смещения нового обработчика STOSW ; сохранение смещения в таблице MOV WORD PTR SYS_HANDLER+2, ES:[DI] ; сохранение сегмента системного обработчика MOV AX, SEGMENT HANDLER ; запись в AX сегмента нового обработчика STOSW ; сохранение сегмента в таблице
|
При установке значений
сегмента и смещения обработчика
аппаратного прерывания нужно до
этого сбросить флаг IF (команда CLI), а
после установки новых значений
установить флаг IF (команда STI). Это
необходимо для того, чтобы в
процессе установки значений
сегмента и смещения не возникло
аппаратное прерывание.
Приведённые выше
фрагменты кода можно упростить,
используя функции прерывания DOS INT
21h. Функция DOS 35h позволяет получить
адрес обработчика прерывания. При
этом в регистр AH записывается номер
функции (35h), в регистр AL
записывается номер прерывания.
После вызова прерывания INT 21h в
регистре ES возвращается значение
сегмента обработчика указанного
прерывания. В регистре BX
взвращается значение смещения
обработчика указанного прерывания:
SYS_HANDLER DD ? . . . MOV AH, 35H MOV AL, N INT 21H MOV WORD PTR SYS_HANDLER, BX MOV WORD PTR SYS_HANDLER+2, ES
|
Функция DOS 25h позволяет
установить адрес обработчика
прерывания. В регистр AH
записывается номер функции (25h), в
регистр AL записывается номер
прерывания. В регистр DS
записывается значение сегмента
обработчика прерывания, адрес
которого нужно установить в
таблице векторов прерываний. В
регистр DX записывается значение
смещения обработчика прерывания:
MY_HANDLER PROC . . . MY_HANDLER_ENDP . . . MOV AH, 25H MOV AL, N MOV DS, SEGMENT MY_HANDLER MOV DX, OFFSET MY_HANDLER INT 21H
|
При написании обработчика
аппаратного прерывания нужно
учитывать то, что он должен быть
завершен до возникновения
очередного аппаратного прерывания
для этого обработчика. Если это
условие не выполнено, то, в лучшем
случае, возникшее прерывание будет
потеряно. В худшем случае
невыполнение этого условия может
повлечь за собой потерю данных или
зависание компьютера. Например, при
написании аппаратного обработчика
прерываний от таймера, код
обработчика должен выполнятся по
времени менее 1/18 с., так как
прерывания от таймера по умолчанию
генерируются 18.2 раз в секунду. То же
можно сказать и об обработчике
аппаратных прерываний от
клавиатуры — код обработчика должен
выполняться не дольше задержки
повторения символов.
Также при написании любого
обработчика прерывания нужно
инициализировать сегментный
регистр DS, если обработчик
обращается к каким-либо внутренним
ячейкам памяти. Вместо этого можно
использовать обращение к ячейкам
памяти с использованием префикса
замены сегмента (например CS:[BX]), но
это увеличивает размер
соответствующей команды.
Использование префикса замены
сегмента эффективно в том случае,
когда количество обращений к
внутренним ячейкам памяти
обработчика невелико (2 — 3).
Рассмотрим теперь
средства для завершения
резидентной программы и сохранении
части её кода в памяти для
последующего использования при
возникновении прерываний.
Прерывание DOS INT 27h.
Прерывание предназначено для
завершения программы и
сохранения её резидентной в
памяти. Для этого в регистр DX
нужно занести количество байт
для сохраняемой части
программы плюс один байт.
Начало сохраняемой части
программы совпадает со
смещением 0000h относительно
кодового сегмента, поэтому для
COM программ нужно учитывать
размер префикса программного
сегмента (PSP — Program Segment Prefix) — 256
байт.Прерывание DOS INT 21h,
функция 31h. Функция 31h
прерывания DOS INT 21h выполняет те
же действия, что и прерывание DOS
INT 27h, но в регистр DX заносится
размер сохраняемой части
программы в параграфах (блоки
памяти длиной 16 байт). Также
имеется возможность
определить код возврата при
завершении резидентной
программы (заносится в регистр
AL).
Ниже приведёна общая
структура резидентной программы:
;
данные для резидентной части программы ...
HANDLER
...
HANDLER
...
;
...
;
|
Следующий фрагмент кода
даёт пример определения основной
структуры резидентной программы на
ассемблере (программа типа COM):
CODE SEGMENT ; определение кодового сегмента ASSUME CS:CODE, DS:CODE ; CS и DS указывают на сегмент кода ORG 100H ; размер PSP для COM файла BEGIN: JMP START ; переход на нерезидентную часть программы SYS_HANDLER DD ? ; определение ячейки памяти для хранения ; адреса системного обработчика A DW 0 ; определение внутренних ячеек памяти для B DB 1 ; резидентной части программы . .. KB_HANDLER PROC ; процедура обработчика прерываний ; от клавиатуры PUSHF ; создание в стеке структуры для IRET CALL CS:SYS_HANDLER ; вызов системного обработчика ... IRET ; возврат из обработчика KB_HANDLER ENDP KB_END: ; метка для определения размера резидентной ; части программы C DB 2 ; ячейки памяти для нерезидентной части D DW 3 ; программы ... START: ; начало нерезидентной части программы ... MOV AH, 35H ; получение адреса системного обработчика MOV AL, 09H ; прерываний от клавиатуры INT 21H MOV WORD PTR SYS_HANDLER, BX MOV WORD PTR SYS_HANDLER+2, ES MOV AH, 25H ; установка адреса нового обработчика MOB AL, 09H ; прерываний от клавиатуры MOV DX, OFFSET KB_HANDLER INT 21H MOV DX, (KB_END + 10FH) / 16 ; вычисление размера резидентной части INT 31H ; завершение резидентной программы с ; сохранением части её кода в памяти CODE ENDS ; конец сегмента кода END BEGIN ; конец программы
|
Рассмотрим пример
резидентной программы «часы»
на ассемблере (CLOCK2. ZIP — 827
байт). Программа перехватывает
обработчик прерываний от таймера и
с возникновением очередного
прерывания выводит в левом верхнем
углу экрана текущее время. Ниже
представлен исходный текст
программы с комментариями.
code segment ; определение кодового сегмента assume cs:code,ds:code ; CS и DS указывают на сегмент кода org 100h ; размер PSP для COM программы start: jmp load ; переход на нерезидентную часть old dd 0 ; адрес старого обработчика buf db ' 00:00:00 ',0 ; шаблон для вывода текущего времени decode proc ; процедура заполнения шаблона mov ah, al ; преобразование двоично-десятичного and al, 15 ; числа в регистре AL shr ah, 4 ; в пару ASCII символов add al, '0' add ah, '0' mov buf[bx + 1], ah ; запись ASCII символов mov buf[bx + 2], al ; в шаблон add bx, 3 ret ; возврат из процедуры decode endp ; конец процедуры clock proc ; процедура обработчика прерываний от таймера pushf ; создание в стеке структуры для IRET call cs:old ; вызов старого обработчика прерываний push ds ; сохранение модифицируемых регистров push es push ax push bx push cx push dx push di push cs pop ds mov ah, 2 ; функция BIOS для получения текущего времени int 1Ah ; прерывание BIOS xor bx, bx ; настройка BX на начало шаблона mov al, ch ; в AL - часы call decode ; вызов процедуры заполнения шаблона - часы mov al, cl ; в AL - минуты call decode ; вызов процедуры заполнения шаблона - минуты mov al, dh ; в AL - секунды call decode ; вызов процедуры заполнения шаблона - секунды mov ax, 0B800h ; настройка AX на сегмент видеопамяти mov es, ax ; запись в ES значения сегмента видеопамяти xor di, di ; настройка DI на начало сегмента видеопамяти xor bx, bx ; настройка BX на начало шаблона mov ah, 1Bh ; атрибут выводимых символов @@1: mov al, buf[bx] ; цикл для записи символов шаблона в видеопамять stosw ; запись очередного символа и атрибута inc bx ; инкремент указателя на символ шаблона cmp buf[bx], 0 ; пока не конец шаблона, jnz @@1 ; продолжать запись символов @@5: pop di ; восстановление модифицируемых регистров pop dx pop cx pop bx pop ax pop es pop ds iret ; возврат из обработчика clock endp ; конец процедуры обработчика end_clock: ; метка для определения размера резидентной ; части программы load: mov ax, 351Ch ; получение адреса старого обработчика int 21h ; прерываний от таймера mov word ptr old, bx ; сохранение смещения обработчика mov word ptr old + 2, es ; сохранение сегмента обработчика mov ax, 251Ch ; установка адреса нашего обработчика mov dx, offset clock ; указание смещения нашего обработчика int 21h ; вызов DOS mov ax, 3100h ; функция DOS завершения резидентной программы mov dx, (end_clock - start + 10Fh) / 16 ; определение размера резидентной ; части программы в параграфах int 21h ; вызов DOS code ends ; конец кодового сегмента end start ; конец программы
Рассмотрим работу
программы.
Идентификатор old
определяет ячейку памяти размером 4
байта, которая хранит адрес старого
обработчика прерываний от таймера.
Эта ячейка будет нужна, когда будет
вызываться старый обработчик
прерываний от таймера.
Идентификатор buf
определяет шаблон для формирования
строки, содержащей значение
текущего времени в формате
часы:минуты:секунды. Последний байт
в шаблоне — нулевой — нужен для
определения длины шаблона.
Процедура decode
преобразует двоично-десятичное
число в регистре AL в два ASCII символа,
соответствующих значению часов,
минут или секунд (это зависит от
конкретного значения, записанного
в регистре AL). Процедура прибавляет
к значению разряда числа (младший
разряд находится в первых четырёх
битах регистра AL, старший — в
старших четырёх битах) ASCII код
символа ‘0’, тем самым формируя ASCII
код для цифры младшего или старшего
разряда. Далее этот ASCII код
записывается в текущую позицию
шаблона. После записи в шаблон
значение указателя на текущий
символ шаблона увеличивается на 3
(две цифры для часов, минут или
секунд, плюс символ ‘:’).
Процедура clock
является обработчиком прерываний
от таймера. Дело в том, что номер
аппаратного обработчика
прерываний от таймера — 08h. Но в
системном обработчике этого
аппаратного прерывания есть вызов
INT 1Ch. Прерывание 1Ch определяет
пользовательский обработчик
прерываний от таймера, который
вызывается системным. Таким
образом, ячейка old хранит
адрес старого пользовательского
обработчика прерываний от таймера.
В начале процедуры clock
командой PUSHF в стеке
подготавливается структура для
команды IRET и затем вызывается
старый пользовательский
обработчик прерываний от таймера.
Далее в процедуре clock
сохраняются в стеке все
модифицируемые регистры (в том
числе и сегментные). После этого
инициализируется сегментный
регистр DS для последующего
обращения к ячейкам памяти
резидентной части программы.
Следующим шагом является получение
значения текущего времени из BIOS при
помощи прерывания BIOS 1Ah. После
вызова команды INT 1Ah в регистре CH
находится значение часов, в
регистре CL — значение минут и в
регистре DH — значение секунд. Каждое
значение представлено в
двоично-десятичном формате -
младший разряд числа находится в
младших четырёх битах регистра, а
старший разряд числа — в старших
четырёх битах. После получения
значения текущего времени регистр
BX настраивается на начало шаблона
для записи в шаблон значений часов,
минут и секунд. Далее три раза
вызывается процедура decode
для записи в шаблон соответственно
часов, минут и секунд. После записи
в шаблон необходимой информации
происходит вывод символов шаблона
в левый верхний угол экрана. Для
этого регистр ES настраивается на
сегмент видеопамяти, а регистр DI
настраивается на начало сегмента
видеопамяти. Далее в цикле
происходит вывод в видеопамять
символов шаблона и атрибутов. После
этого восстанавливаются значения
всех модифицируемых процедурой
регистров и командой IRET происходит
возврат из обработчика.
В основной (нерезидентной)
части программы при помощи функции
DOS 35h происходит получение адреса
старого пользовательского
обработчика прерываний от таймера
(прерывание 1Сh). Значения сегмента и
смещения старого обработчика
записываются в ячейку old.
Далее устанавливается адрес нашего
обработчика прерываний от таймера.
Для этого в регистр DX записывается
смещение нашего обработчика
(смещение процедуры clock) и
вызывается функция DOS 25h (регистр DS
уже содержит значение сегмента
нашего обработчика). После этого
вычисляется размер резидентной
части программы в параграфах. Для
этого сначала вычисляется размер
резидентной части в байтах, не
считая префикса программного
сегмента. Затем к полученному
значению прибавляется размер
префикса программного сегмента — 256
и число 0Fh. Прибавление числа 0Fh
необходимо, чтобы округление при
делении на 16 осуществлялось в
большую сторону. После вычисления
размера резидентной части в
параграфах происходит вызов
функции DOS 31h, которая завершает
программу и сохраняет часть её кода
в памяти. Резидентная программа
запущена.
Copyright © 2000 by
HackMaster
3.1. Организация приложений MS-DOS Как уже отмечалось выше, язык ассемблера является отражением архитектуры процессора,
Программа типа .ЕХЕ
Программа начинается с директивы ассемблера .586, разрешающей использовать в
mov AX,data ;Инициализация
где data — имя, данное
mov AX,4C00h ;Вызов функции
в которых вызывается функция
tasm /z /zi /n /m2 p,p,p
Включение указанных описателей
Рассмотрим текст приведенного
add disk,AL ;Преобразуем
где к байту с адресом disk
Структура и образ памяти программы .СОМ
Программа содержит единственный
Рис. 3.2. Образ памяти
Программы типа .СОМ отличаются
data segment byte
системные программы располагают
tlink /x /v /3 /t p,p
Для того, чтобы избежать
В начале программы отведено
Рис. 3.3. Вывод программы
С таким же успехом можно
Таким образом, данные могут быть размещены как после программы, так и среди
Это второе обязательное условие: из чего бы ни состояла программа, все ее компоненты
Обработчики аппаратных
Рис. 3.4. Функционирование
Обработчик прерываний может
В приведенном примере обработчик
то к ним можно было бы
mov DX,offset new_08 ;Смещение
Однако регистр DS у нас
В примере 3-3 использован
push CS pop DS
После возврата из DOS надо
Ids DX,dword ptr old_08_offs
Между прочим, здесь так
Указанную последовательность
Что же касается основной
mov AH,01h
В результате программа,
Рис. 3.5. Вывод программы
Приведенный пример позволяет
Как будет работать такая
Рис. 3.6. Стек прерванной
Именно такая структура
Обработчики программных
Резидентные программы
ressize=$-main
где main — смещение начала
При первом запуске программы
Рис. З.7. Структура
Как видно из рис. 3.7,
Структура программы соответствует
Рис. 3.8. Вывод программы
Полученный результат далек
30 36 33 44 68
Рассмотренный метод вывода
|
Лекция 4. Основы языка Ассемблер. Синтаксис языка Ассемблер. Ассемблерные вставки в языке C/C++.
4.1. Назначение языков
ассемблера.
Ассемблер (от англ. assemble — собирать) —
компилятор с языка ассемблера в команды машинного языка.
Сейчас
разработка программ на ассемблере применяется в основном в программировании
небольших микропроцессорных систем (микроконтроллеров), как правило,
встраиваемых в какое-либо оборудование. Очень редко возникает потребность
использования ассемблера в разрабатываемых программах в тех случаях, когда
необходимо, например, получить наивысшую скорость выполнения определенного
участка программы, выполнить операцию, которую невозможно реализовать
средствами языков высокого уровня, либо уместить программу в память
ограниченного объема (типичное требование для загрузчиков операционной
системы).
Под
каждую архитектуру процессора и под каждую ОС или семейство ОС существует свой
ассемблер. Есть также так называемые кроссассемблеры, позволяющие на машинах с
одной архитектурой (или в среде одной ОС) ассемблировать программы для другой
целевой архитектуры или другой ОС и получать исполняемый код в формате,
пригодном к исполнению на целевой архитектуре или в среде целевой ОС.
Язык ассемблера — тип языка программирования
низкого уровня. Команды языка ассемблера один в один соответствуют командам
процессора и представляют собой удобную символьную форму записи (мнемокод)
команд и аргументов. Язык ассемблера обеспечивает связывание частей программы и
данных через метки, выполняемое при ассемблировании (для каждой метки
высчитывается адрес, после чего каждое вхождение метки заменяется на этот
адрес).
Каждая
модель процессора имеет свой набор команд и соответствующий ему язык (или
диалект) ассемблера.
Обычно
программы или участки кода пишутся на языке ассемблера в случаях, когда
разработчику критически важно оптимизировать такие параметры, как
быстродействие (например, при создании драйверов) и размер кода (загрузочные
секторы, программное обеспечение для микроконтроллеров и процессоров с
ограниченными ресурсами, вирусы, навесные защиты).
Связывание ассемблерного кода с
другими языками.
Большинство современных компиляторов позволяют комбинировать в одной программе
код, написанный на разных языках программирования. Это дает возможность быстро
писать сложные программы, используя высокоуровневый язык, не теряя
быстродействия в критических ко времени задачах, применяя для них части,
написанные на языке ассемблера. Комбинирование достигается несколькими
приемами:
1.
Вставка фрагментов на языке ассемблера в текст программы (специальными
директивами языка) или написание процедур на языке ассемблера. Способ хороший
для несложных преобразований данных, но полноценного ассемблерного кода с
данными и подпрограммами, включая подпрограммы с множеством входов и выходов, не
поддерживаемых высокоуровневыми языками, с помощью него сделать нельзя.
2.
Модульная компиляция. Большинство современных компиляторов работают в два
этапа. На первом этапе каждый файл программы компилируется в объектный модуль.
А на втором объектные модули линкуются (связываются) в готовую программу.
Прелесть модульной компиляции состоит в том, что каждый объектный модуль
будущей программы может быть полноценно написан на своем языке программирования
и скомпилирован своим компилятором (ассемблером).
Достоинства языков ассемблера.
1.
Максимально оптимальное использование средств процессора, использование
меньшего количества команд и обращений в память и, как следствие, большая
скорость и меньший размер программы.
2.
Использование расширенных наборов инструкций процессора (MMX, SSE, SSE2, SSE3).
3.
Доступ к портам ввода-вывода и особым регистрам процессора (в большинстве ОС
эта возможность доступна только на уровне модулей ядра и драйверов)
4.
Возможность использования самомодифицирующегося (в том числе перемещаемого)
кода (под многими платформами она недоступна, так как запись в страницы кода
запрещена, в том числе и аппаратно, однако в большинстве общедоступных систем
из-за их врожденных недостатков имеется возможность исполнения кода,
содержащегося в сегменте (секции) данных, куда запись разрешена).X используется в OpenBSD , в других BSD-системах, в Linux. В Microsoft
Windows (начиная с Windows XP SP2) применяется схожая технология DEP.
Недостатки языков ассемблера.
1.
Большие объемы кода, большое число дополнительных мелких задач, меньшее
количество доступных для использования библиотек по сравнению с языками
высокого уровня.
2.
Трудоемкость чтения и поиска ошибок (хотя здесь многое зависит от комментариев
и стиля программирования).
3.
Часто компилятор языка высокого уровня, благодаря современным алгоритмам
оптимизации, даёт более эффективную программу (по соотношению качество/время
разработки).
4.
Непереносимость на другие платформы (кроме совместимых).
5.
Ассемблер более сложен для совместных проектов.
4.2. Синтаксис ассемблера.
Синтаксис
общих элементов языка. В отличие от языков программирования высокого уровня,
где основным элементом языка является оператор, синтаксически программа на
ассемблере состоит из последовательности строк. Строка – основная единица
ассемблерной программы.
Синтаксис
строки имеет следующий общий вид:
<метка:>
<команда или директива> <операнды> <;комметарий>
Все
эти четыре поля необязательны, в программе вполне могут присутствовать и
полностью пустые строки для выделения каких либо блоков кода. Метка может быть
любой комбинацией букв английского алфавита, цифр и символов _, $, @, ?, но
цифра не может быть первым символом метки, а символы $ и ? иногда имеют
специальные значения и обычно не рекомендуются к использованию. Большие и
маленькие буквы по умолчанию не различаются, но различие можно включить, задав
ту или иную опцию в командной строке ассемблера. Во втором поле, поле команды,
может располагаться команда процессора, которая транслируется в исполняемый
код, или директива, которая не приводит к появлению нового кода, а управляет
работой самого ассемблера. В поле операндов располагаются требуемые командой
или директивой операнды (то есть нельзя указать операнды и не указать команду
или директиву). И наконец, в поле комментариев, начало которого отмечается
символом ; (точка с запятой), можно написать все что угодно — текст от символа
«;» до конца строки не анализируется ассемблером.
4.3. Ассемблерные вставки в
языках высокого уровня.
Языки
высокого уровня поддерживают возможность вставки ассемблерного кода.
Последовательность команд Ассемблера
в С-программе размещается в
asm-блоке:
asm
{
команда_1 //комментарий_1
команда_2 /* комментарий_2 */
————————
команда_n ; комментарий_n
}
Язык ассемблера — Введение в программирование
ИЕРАРХИЯ ЯЗЫКОВ
Пусть необходимо вычислить сумму двух двоичных чисел, хранящихся в памяти машины, и поместить результат в некоторую ячейку памяти. Для этого используем некоторый регистр в качестве накопителя, т. е. для хранения промежуточных результатов вычислений. Необходимые команды:
1.«Загрузить» содержимое первой ячейки памяти в регистр общего назначения, используемый в качестве накопителя. По команде загрузки производится выборка содержимого первой ячейки памяти (оставляя содержимое самой ячейки неизменным) и запоминание его в нашем регистре-накопителе, при этом предыдущее содержимое этого регистра теряется.
2.«Сложить» содержимое второй ячейки памяти с содержимым регистра-накопителя. Как мы знаем, содержимое второй ячейки остается неизменным, а результат сложения по окончании выполнения команды оказывается в регистре-накопителе.
3.«Запомнить» результат, находящийся пока в регистре, в некоторой ячейке памяти. Таким образом, третья ячейка памяти, как и регистр, содержит результат сложения содержимых первых двух ячеек.
Предположим, что в рассмотренном примере первое число хранилось в ячейке 256, второе — в ячейке 260, и результат требовалось поместить в ячейку 249- Регистр 6 был выбран в качестве накопителя. Соответствующие команды машинного языка IBM 360 таковы:
В большинстве программ команд значительно больше. Однако и в рассмотренном выше примере для задания необходимых команд на машинном языке потребовалось задать 96 (3×32) нулей и единиц. Ошибка хотя бы в одном бите привела бы к неверному конечному результату. Кроме того, программы на машинном языке очень трудны в составлении и для понимания из-за отсутствия соответствия между языком машины и обычным «человеческим» языком.
Можно добиться некоторого упрощения, применяя шестнадцатеричную систему счисления для краткой записи цепочек двоичных цифр. В результате каждая группа из четырех битов заменяется соответствующей шестнадцатеричной цифрой. Проведение подобных преобразований было описано в предыдущей главе. Машинная программа в шестнадцатеричном представлении будет выглядить так:
Это значительное улучшение по сравнению с двоичной формой машинного языка. Для программирования сложения двух чисел вместо 96 двоичных цифр теперь требуется написать всего лишь 3×8=24 шестнадцатеричных. В самом деле, наиболее удобной формой представления двоичной информации является шестнадцатеричная форма. Но все же команды машинного языка независимо от формы их представления лишь очень отдаленно напоминают о действиях, которые в соответствии с, ними выполняются.
Нужно попытаться представить операции машинного языка и адреса в форме более понятной программисту. Этой цели служит язык ассемблера. Символические формы представления, или мнемоники кодов операций, позволяют нам, например, писать Lвместо кода операции «Загрузка» (LOAD), А вместо кода операции «Сложение» (ADD),
STвместо кода операции «Запись в память» (STORE). Применение мнемоник исключает необходимость использования двоичных кодов операций машинного языка.
Но гораздо более важным является то, что в языке ассемблера можно использовать символические имена для указания адресов памяти, регистров и констант. Результат применения символа в программе будет тот же, как если бы мы указали его двоичный эквивалент. Но поскольку выбор символа для представления некоторого числа или ячейки памяти зависит только от нас, то мы можем выбрать для этой цели символ, характеризующий данное число. Например, если программа вычисляет среднее значение нескольких чисел, то для обозначения адреса ячейки, в которой будет находиться результат, можно выбрать символ AVERAGE(СРЕДНЕЕ). Если мы не используем символов для обозначения ячеек памяти, то необходимо знать физические адреса тех ячеек, в которых хранится обрабатываемая информация. Использование символов облегчает программирование, поскольку оно устраняет необходимость иметь дело с действительными машинными адресами.
Возвращаясь к нашему примеру, назовем три ячейки памяти NUM- BER1, NUMBER2 и NUMсоответственно и регистр 6 — REGSIX. Теперь мы можем переписать команды так:
Несмотря на то что кое-что в нашем примере еще не совсем ясно, очевидно, что программу на ассемблере гораздо легче и писать и воспринимать, чем программу в машинных кодах.
Язык ассемблера — это символическое представление машинного языка. Каждой правильной команде языка ассемблера соответствует команда машинного языка, и каждой команде, записанной на языке ассемблера в некоторой программе, соответствует команда окончательной программы на машинном языке.
Программа, переведенная на язык машины, может быть выполнена ЭВМ. При работе по программе ЭВМ выполняет указанные действия так, как это было описано в предыдущей главе. Таким образом, трансляция и выполнение — два различных этапа обработки программы, написанной на символическом языке.
Существуют языки, такие, как, например, ФОРТРАН, программы на которых гораздо больше походят на математическое или словесное описание необходимых вычислений. На ФОРТРАНе рассмотренная выше программа будет выглядить так:
NUM=NUMBER1+NUMBER2
Рис. 3.1. Иерархия языков.
Мы знаем, что конечной формой любой программы является программа на языке машины. Как же программа, написанная на символическом языке ассемблера, преобразуется в машинные коды? Эту задачу выполняет программа-ассемблер. Входной информацией для программы-ассемблер является программа, написанная на языке ассемблера. На выходе получается эквивалент исходной программы на машинном языке.
ФОРТРАН, КОБОЛ, АЛГОЛ, ПЛ/1 и многие другие символические языки принадлежат классу языков, называемых компилируемыми языками. Вообще говоря, одно предложение или команда такого языка после обработки программой, называемой компилятором, преобразуется в несколько команд машинного языка. Мы уже видели, что оператор языка ФОРТРАН, задающий сложение двух чисел, эквивалентен трем машинным командам. В этом принципиальная разница между компилируемыми языками и языком ассемблера. Выражаясь математическим языком, между предложениями языка ассемблера и командами машинного языка существует взаимно однозначное соответствие, тогда как между предложениями компилируемых языков и командами машинного языка такого соответствия нет.
Компилируемые языки вообще являются языками более высокого уровня, чем машинный язык или язык ассемблера. Существует понятие иерархии языков, уровень некоторого языка в которой определяется «степенью отличия» его от машинного языка, языка «низшего» уровня. Рис. 3.1 дает представление об интересующей нас части иерархической лестницы языков.
Использование программы, написанной на одном из символических языков, состоит из двух этапов: 1) программа, написанная на символическом языке, должна быть переведена на язык машины, т. е. исходный код должен быть преобразован в объектный код; 2) под управлением полученного объектного кода работает ЭВМ, иначе говоря, объектный код является выполняемой программой. На этапе трансляции ЭВМ выполняет программу-компилятор или ассемблер, при этом исходный код рассматривается как входные данные. На этапе выполнения выполняется программа в объектном коде, в качестве входных используются данные, определенные программистом.
Зачем изучать язык ассемблера?
Определив, что такое язык ассемблера, посмотрим теперь, как его применять и что дает его знание. Но прежде нам важно указать на существование двух типов программ. Первый — так называемые проблемные программы. С точки зрения администрации вычислительного центра проблемные программы составляются пользователями, и одной из обязанностей администрации является облегчение задачи пользователя настолько, насколько это возможно. В распоряжении администрации находятся системные программисты. Системные программы, которые они пишут, служат поставленной цели.
Большинство проблемных программ пишется на языках высокого уровня, поскольку они в известном смысле проще для использования и требуют гораздо менее детального изучения конкретной вычислительной установки, чем язык ассемблера. С другой стороны, в связи с большой эффективностью использования языка ассемблера и тесной связи системных программ с конкретной ЭВМ, большинство этих программ пишется на языке ассемблера. В дальнейшем мы увидим, что знание языка ассемблера совершенно необходимо системным программистам и так же достаточно полезно и тем, кто пишет проблемные программы. Сначала посмотрим на язык ассемблера глазами пользователя.
Во многих случаях программу для решения конкретной задачи удобнее писать на языке высокого уровня, чем на языке ассемблера, так как большинство языков высокого уровня специально ориентировано на выполнение некоторых видов работ. ФОРТРАН (FORmulaTRANslator) создан главным образом учеными; он соединяет вычислительные возможности с относительной простотой программирования алгебраических выражений, что сделало его наиболее употребимым языком для программирования научных вычислений. КОБОЛ (COmmonBusinessOrientedLanguage) был создан для программирования экономических задач; обработка больших объемов информации, например результатов инвентаризации товаров или списков сотрудников, наиболее легко программируется на КОБОЛе. АЛГОЛ (ALGOrithmicLanguage) является языком для описания алгоритмов, или правил вычислений.
Каждый из перечисленных языков служит вполне определенной цели. Но попытки выйти за пределы области ориентации языка приводят к значительным осложнениям. Обработку экономических данных трудно запрограммировать на ФОРТРАНе; чем больше требуется действий невычислительного типа для решения данной задачи, тем менее пригоден ФОРТРАН. С другой стороны, программирование на КОБОЛе сложных алгебраических выражений по меньшей мере утомительно. Кроме того, в КОБОЛе отсутствуют некоторые существенные особенности языков для научных вычислений, например библиотека стандартных подпрограмм для вычисления математических функций, и он слишком «словесен» для подобных применений. АЛГОЛ — международный язык описания алгоритмов; алгоритмы, написанные на АЛГОЛе, можно найти, например, в таком журнале, как САСМ. Однако большинство программистов согласится, что существует много задач, для которых этот язык неудобен. Язык сам по себе не содержит специальных операторов ввода-вывода, кроме того, синтаксис или структура языка, удобная для описания алгоритмов, затрудняет организацию вычислений. Таким образом, каждый из рассмотренных специализированных языков служит определенной цели, но чем он удобнее для программирования в конкретной области, тем больше теряет он в общности.
ПЛ/I(ProgrammingLanguageI) претендует на общность, которой так не хватает перечисленным выше языкам. Синтаксически этот язык является комбинацией АЛГОЛа, ФОРТРАНа и КОБОЛа и вдобавок обладает некоторыми чертами, которые делают возможным написание на нем полной операционной системы. Платой за эту гибкость является чрезвычайная сложность языка для начинающего программиста. Именно эта сложность не позволила и, вероятно, не позволит этому языку стать универсальным языком программирования для машин фирмы IBM. Для начинающего изучать вычислительную науку студента тот факт, что ПЛ/Iявляется языком высокого уровня, означает, что изучение его не может дать того, что дает изучение ассемблера — знания структуры и функций вычислительной системы.
В распоряжении программиста на ассемблере все возможности ЭВМ. Язык ассемблера по существу является машинным языком. Специализированные языки высокого уровня обычно используют только часть возможностей машины. Это вовсе не означает, что, изучив язык ассемблера, следует все программы писать только на нем. Это было бы все равно, что сказать, что, если кто-нибудь научился водить машину, ему следует перестать ходить пешком. Но можно применять ассемблер для использования тех возможностей, которые отсутствуют в других языках программирования. В действительности большинство языков высокого уровня позволяет пользователю писать подпрограммы на языке ассемблера для использования возможностей, не предусмотренных или трудно программируемых в данном языке.
Программисту, пишущему на языке высокого уровня, знание языка ассемблера дает дополнительные возможности. Чем ближе он знаком с ЭВМ и ее возможностями, тем большую выгоду он может извлечь для себя независимо от того, на каком языке он программирует. Например, человеку, знакомому с ассемблером, понятны форматы, используемые в ФОРТРАНе, и предложения определения файлов в КОБОЛе. Ему известно, для чего употребляется знак = в ФОРТРАНе и какова разница между целыми и вещественными переменными. Встретившись с вопросом: «Можно ли это сделать на ФОРТРАНе?», он сможет использовать свои знания возможностей машины для определения, имеет ли смысл этот вопрос с машинной точки зрения. Этого обычно достаточно для получения по крайней мере частичного ответа на вопрос.
Кроме того, знание языка ассемблера значительно облегчает поиск ошибок в программах, написанных на языках высокого уровня. Большинство компиляторов располагает возможностью распечатки оттранслированной программы в форме программы на языке ассемблера. Имея эту распечатку, а также распечатку распределения памяти и содержимого регистров на момент, когда была зафиксирована ошибка, программист, знающий ассемблер, имеет очевидные преимущества в отыскании ошибки.
Наконец, надо отметить, что эффективность использования возможностей ЭВМ важна для любого программиста. В дальнейшем этот вопрос будет рассмотрен более подробно. Пока только утверждается, что знание основных принципов работы вычислительной машины необходимо для более эффективного ее использования.
Мы уже видели, что знание языка ассемблера и основных принципов работы ЭВМ полезно и программирующему на языках высокого уровня. Теперь рассмотрим язык ассемблера с точки зрения системного программиста. Мы увидим, почему большинство системных программ пишутся на языке ассемблера и как это влияет на использование всех возможностей ЭВМ.
Системные программы служат цели освобождения пользователя от выполнения машинно- и системно-ориентированных задач, не представляющих непосредственного интереса для него. Например, программист использует компилятор или ассемблер для трансляции исходной программы на машинный язык; пользователь, который был бы вынужден прежде, чем написать программу на ФОРТРАНе, написать компилятор, вероятно, откажется от такого способа решения своей задачи. Такие необходимые действия, как преобразование исходных данных из символьного кода в двоичное представление, удобное для выполнения арифметических операций, управление периферийными устройствами и управление вычислениями в целом непосредственно не связаны с проблемной программой и выполняются системными программами. Короче говоря, системные программы служат связующим звеном между программистом и аппаратурой вычислительной машины.
Поскольку системные программы расположены как бы между пользователем и машиной, то в своем большинстве они пишутся на языке ассемблера. Системные программы имеют дело с деталями конкретных машинных операций, обращение к которым невозможно при использовании языков высокого уровня. Например, программист на ФОРТРАНе обычно не управляет конкретным расположением программ в памяти машины, и ему все равно, какое конкретно устройство ввода с перфокарт будет использовано для ввода данных его программы. Действительно, поскольку он программирует на языке высокого уровня, ему нет необходимости заботиться об этих деталях. Но очевидно, что некоторые системные программы вынуждены работать с такого рода детальной информацией для обеспечения правильности работы программ пользователя и получения этими программами нужных данных. Язык ассемблера — это язык, дающий возможность выполнить эти задачи.
Теперь, как и было обещано, возвратимся к вопросу эффективности. Машинное время, т. е. время, в течение которого центральный процессор находится в распоряжении пользователя, стоит очень дорого, обычная цена составляет от 250 до 500 долларов в час. В некоторых случаях дополнительная плата взимается за использование памяти и загрузку периферийных устройств. Решение некоторых задач требует использования огромного количества памяти и машинного времени, в этих случаях возможность и экономичность их решения определяется эффективностью используемой программы.
Именно на ассемблере можно составить наиболее эффективную программу. Кроме того, программисту на ассемблере значительно •облегчается проблема использования всех возможностей ЭВМ. Так, он может увеличить скорость вычислений, используя большое количество памяти, и наоборот.
Компиляторы в общем не обеспечивают получения наиболее эффективных программ. Создатель компилятора не может предусмотреть все возможные предложения, которые могут появиться в обрабатываемых программах. Поэтому компилятор можно создать лишь как программу, классифицирующую некоторые типы предложений на входном языке и обрабатывающую предложения одного класса одинаково. Такая степень общности приводит к снижению эффективности получаемой машинной программы.
Особую важность имеет эффективность для системных программистов. Вряд ли пользователь пожелает оплачивать неэффективность операционной системы. Таким образом, мерой полезности системного программиста является его способность организации более эффективного использования всех ресурсов вычислительной установки.
Можно сказать, что ЭВМ напоминают многие другие машины тем, что, чем больше мы о них знаем, тем лучше мы можем их использовать. Знание языка ассемблера полезно системному программисту во многих аспектах: оно позволяет решить те задачи, решение которых сложно или невозможно с использованием лишь процедурных языков, помогает в отыскании ошибок и наиболее эффективном использовании всех ресурсов ЭВМ. Вследствие своих широких возможностей и высокой эффективности язык ассемблера незаменим для системных программистов.
Но основным мотивом изучения ассемблера является возможность получения с его помощью информации о самих вычислительных машинах. Для изучения ассемблера необходимо понять структуру и функции вычислительной машины, форму представления информации о ней. Эти знания не только помогут вам стать хорошим программистом и исследователем, но могут послужить основой для освоения новых научных и инженерных направлений. Например, одной из важных областей исследования сейчас является использование миникомпьютеров или даже микрокомпьютеров для выполнения некоторых специальных видов обработки данных, управления технологическими процессами и научных исследований. Разумное использование этих относительно простых систем значительно упростится, если вы хорошо понимаете, как работает ЭВМ.
Ассемблер это что? Компилятор/интерпритатор/нечто уникальное?
← →
wHammer ©
(2007-02-08 09:24)
[0]
Помогите разобраться пожалуйста? Информация на различных информационных сайтах весьма противоречива.
С наилучшими…
Александр.
← →
Алхимик ©
(2007-02-08 09:28)
[1]
http://ru.wikipedia.org/wiki/%D0%90%D1%81%D1%81%D0%B5%D0%BC%D0%B1%D0%BB%D0%B5%D1%80
← →
wHammer ©
(2007-02-08 09:35)
[2]
> Алхимик © (08.02.07 09:28) [1]
Это все понятно. Но я могу тоже привести http://www.softcraft.ru/translat/lect/t01-02.shtml и отттуда:
Транслятор — обслуживающая программа, преобразующая исходную программу, предоставленную на входном языке программирования, в рабочую программу, представленную на объектном языке.
Приведенное определение относится ко всем разновидностям транслирующих программ. Однако у каждой из таких программ могут иметься свои особенности по организации процесса трансляции. В настоящее время трансляторы разделяются на три основные группы: ассемблеры, компиляторы и интерпретаторы.
Интересно личное мнение форумчан по этому поводу?
← →
palva ©
(2007-02-08 09:35)
[3]
Компилятор.
← →
@!!ex ©
(2007-02-08 09:42)
[4]
Язык программирования? 🙂
← →
TUser ©
(2007-02-08 09:43)
[5]
> Интересно личное мнение форумчан по этому поводу?
Ну, что ж. Скажу тебе свое личное мнение — мне пофиг. Хоть горшком назови, только в печь не ставь.
← →
wHammer ©
(2007-02-08 09:44)
[6]
> Ну, что ж. Скажу тебе свое личное мнение — мне пофиг. Хоть
> горшком назови, только в печь не ставь.
Понятно, а мне вот нет.
← →
Сергей М. ©
(2007-02-08 10:02)
[7]
> wHammer © (08.02.07 09:44) [6]
Ассемблер — это, прежде всего, язык программирования.
Любую среду программирования, использующую этот язык для создания программ, часто тоже называют «ассемблером», такие среды используют механизм компилирующего типа, т.к. результатом ассемблирования является код, ориентированный на исполнение той или иной исполняющей системой, например, процессором.
← →
Сергей М. ©
(2007-02-08 10:06)
[8]
> wHammer
В нек.случаях ассемблерные программы интерпретируются, например, для пошаговой отладки программного кода в условиях отсутствия целевой исполняющей системы (режим эмуляции целевой системы команд)
← →
wHammer ©
(2007-02-08 10:14)
[9]
> Сергей М. © (08.02.07 10:02) [7]
Язык ассемблера. Язык программирования низкого уровня.
Язык получил свое название от слова ассемблер (lang-en|assembler — сборщик) — названия транслятора (компилятора) c языка ассемблера. Язык ассемблера, в некоторых случаях, для краткости, называют «ассемблером» (а что-то связанное с ним — «ассемблерный»), но в общем случае это неправильно. Также, сам ассемблер (программу) никогда не называют -компилятором языка ассемблера или компилятором ассемблера (разве что в редких случаях).
← →
wHammer ©
(2007-02-08 10:16)
[10]
…отсюда http://ru.wikipedia.org/wiki/%D0%AF%D0%B7%D1%8B%D0%BA_%D0%B0%D1%81%D1%81%D0%B5%D0%BC%D0%B1%D0%BB%D0%B5%D1%80%D0%B0
← →
TUser ©
(2007-02-08 10:20)
[11]
А какая разница, как классифицировать этот объект. О чем речь идет — и там всем понятно.
← →
wHammer ©
(2007-02-08 10:27)
[12]
> TUser © (08.02.07 10:20) [11]
Да нет, не все, т.к. интересует процесс преобразования ассемблер-программы в машинные коды. Как мне кажется, этот процесс — практичеки типичный процесс компиляции, ну за некоторыми исключениями. Но есть иное мнение, например:
Ассемблер (транслятор языка ассемблера), своего рода компилятор – берётся программа, написанная на языке ассемблера (исходный текст) и переводится в машинный код. Однако есть некоторые различия. Когда компилятор делает перевод с одного языка на другой, предполагается получить программу на целевом языке, который будет управлять программой теми же самыми методами и давать те же самые результаты. Подобно выбору между языками программирования различного строения, но выполняющих одну и ту же работу, компилятор имеет свободу выбора – одновременно предполагая, что выбор будет оптимальным. Различные компиляторы, переводящие программы с языка на язык могут давать весьма различные результаты, даже при том, что программы будут делать одно и тоже. В этом плане танслятор языка ассемблера немного отличается, так как инструкции языка ассемблера точно соответствуют машинным кодам, на которые они переведены. В большинстве случаев мы точно знаем какие байты будут переведены языком ассемблера. В данном случае работа транслятора подобна работе интепритатора. Это наиболее очевидно при рассмотрении следующей директивы:
db 90h
котороя указывает транслятору на необходимость поместить один байт с информацией (90h) в текущую позицию в шестнадцетиричном коде. В данном случае работа транслятора ассемблера больше похожа на работу интерпритатора, а машинный код произведённый транслятором – просто перевод с языка исходной программы.
Когда кто-то пишет программу на языке ассемблера, он обычно думает, что программа, которую он пишет, написана на машинном коде – ассемблере, только выполняется эта задача по созданию программы, на более простом к восприятию машинном языке, обеспечивающем более лёгкое запоминание имён инструкций (называемых мнемоникой). Ещё этот машинный язык разрешает маркировать различные места в памяти, а затем вычислять соответствующие адреса и смещения автоматически. При написании некоторой простой последовательности инструкций на языке ассемблера:
mov ax, 4C00h
int 21h
никто обычно не думает о том, как интерпретируются эти директивы, каким получается машинный код.
Но фактически имеются две программы, слитые вместе (компилятор и интерпритатор). Это наделяет ассемблер новым качеством: инструмент, который, оказывается и компилятором и интерпритатором одновременно.
Рассмотрим две простые команды языка ассемблера. Они прибавляют EAX к самому себе, повторяя этот процесс пять раз. Первая команда (mov) использует ECX, чтобы считать количество повторений:
mov ecx,5
square: add eax,eax
loop square
Транслятор переводит три инструкции в машинный код и приводит их в действие, которое добавляет EAX к самому себе. Это повторяется пять раз, пока процессор выполняет машинный код. Каждый проход уменьшает ECX на единицу и, в случае если ECX – все еще не ноль, переходит обратно к метке (square).
Так как ассемблер является и компилятором и интерпритатором одновременно, то ни один из этих терминов не даёт полного представления о работе транслятора языка ассемблера.
Оригиал:
Assembler as a compiler and assembler as an interpreter
The implementations of programming languages are divided into two main classes: compilers and interpreters. The interpreter is a program which takes a program written in some language and executes it. And the compiler is simply a program that translates program written in one language into another one — the most commonly the target language is the machine language, so the result can be then executed by the machine.
From this point of view, the assembler appears to be a kind of compiler — it takes the program written in assembly language (the source code) and translates it into machine language. However there are some differences. When compiler does the translation from one language to another, it is expected to make the program in the target language that will run (when executed by some interpreter or processor) the same way and give the same results. But in exact details like choosing between many possible language constructs that would do the same, the compiler has freedom of choice — while it is expected to make possibly the best choice, the various compilers translating between the same two languages may give quite different results, even though the programs will do the same. The assembler is a bit different in this aspect, as there is a kind of exact correspondence between the instructions of assembly language and the instructions of machine language they are translated to. In fact in most cases you know what bytes exactly will be generated by the assembly language construct. This is what in fact makes assembler behave a bit like interpreter. This is the most obvious in the case of directives like:
db 90h
which tells the assembler to put the one byte with value 90h at the current position in the output code. This is more like if the assembler was an interpreter, and the machine language generated by assembler was simply an output of the interpreted program. Even the instructions, which in fact represent the machine language instructions they are translated to, can be considered to be actually the directives that tell assembler to generate the opcode of given instruction and place it at current position in output.
Also one can put no instruction mnemonics at all into the source code, and use only DB directives to create, for instance, just some text. In such case the output is not a program at all, as it doesn»t contain any machine language instructions. This makes assembler appear to be really an interpreter.
But when someone writes the program in assembly language, he usually thinks about the program he writes in machine language — assembler just makes the task of creating program in machine language easier, providing easy to memorize names for instructions (called mnemonics for that very reason), allowing to label various places in memory and other values with names and then calculating the appropriate addresses and displacements automatically. When writing some simple sequence of instructions in assembly language:
mov ax,4C00h
int 21h
one usually doesn»t think about them as interpreted directives that generate the machine language instructions. One does think as if they actually were the instructions which they generate, one thinks in terms of the program he writes with the assembly language, not the program he writes in assembly language. But there are actually those two programs merged together, two different layers of thinking in one source code. This makes assembler a new quality: a tool that appears to be both compiler and interpreter at the same time.
← →
wHammer ©
(2007-02-08 10:30)
[13]
…
Объяснение не очень, но ключевая фраза здесь:
Так как ассемблер является и компилятором и интерпритатором одновременно, то ни один из этих терминов не даёт полного представления о работе транслятора языка ассемблера.
← →
@!!ex ©
(2007-02-08 10:40)
[14]
Бред. Или у енмя уж совсем не правильное определение «интрепритатора» забито.
← →
evvcom ©
(2007-02-08 10:41)
[15]
> [12] wHammer © (08.02.07 10:27)
> В данном случае работа транслятора ассемблера больше похожа
> на работу интерпритатора
Чушь какая-то. В моем понимании:
1. Компилятор — программа, преобразующая исходный код в объектный.
2. Транслятор — то же, что и компилятор, за исключением того, что выполняется однозначное преобразование: одна инструкция — одна машинная команда.
3. Интерпретатор — программа, которая преобразует исходный текст или некий оптимизированный, но все же еще виртуальный, во время выполнения в некие инструкции и далее их выполняет.
Транслятор с языка ассемблера не выполняет исходный код (текст), написанный программистом, потому называть его интерпретатором просто в корне неверно.
← →
Desdechado ©
(2007-02-08 11:00)
[16]
Сложности с толкованием связаны, имхо, с тем, что ранние компиляторы выполняли трансляцию не сразу в машинные коды, а в промежуточный ассемблерный код, который уже дополнительно транслировался в машинный. Эта двухфазность (не считая компоновки) и вызывает «три основные группы: ассемблеры, компиляторы и интерпретаторы».
Такая двухфазность хорошо документирована на советских многотерминальных машинных комплексах, которые я застал в нашем ХНУРЭ.
← →
Сергей М. ©
(2007-02-08 11:19)
[17]
> evvcom © (08.02.07 10:41) [15]
1. Совершенно верно. Следует лишь уточнить, что результирующий «объектный код» нельзя рассматривать без жесткой привязки к целевой исполняющей системе, каковой м.б. как «железо» (процессор), так и «софт» (виртуальная машина, например, java-машина)
2. Не согласен. Трансляторы выполняют преобразование языковых конструкций входного языка программирования в логически эквивалентные им языковые конструкции выходного языка программирования. Среды же транслирующего типа, как правило, сочетают в себе функции транслятора и компилятора — программа, к примеру, на Фортране в ходе обработки средой транслируется сначала в промежуточное языковое представление (низкоуровневое, традиционно ассемблерное), а уж затем (опционально) компилирует промежуточный рез-т в объектный код.
3. Ассемблерные среды интерпретирующего типа имеют право на существование и довольно широко распространены, скажем, для интерактивной трассировки/отладки на эмулирующих виртуальных машинах кода для целевых машин с иной системой команд.
← →
Плохиш ©
(2007-02-08 11:23)
[18]
Классная ветка, не думал, что философов уже тоже заставляют изучать программирования, са ещё и на ассемблере :-))
← →
wHammer ©
(2007-02-08 11:46)
[19]
> Desdechado © (08.02.07 11:00) [16]
> Сложности с толкованием связаны, имхо, с тем, что ранние
> компиляторы выполняли трансляцию не сразу в машинные коды,
> а в промежуточный ассемблерный код, который уже дополнительно
> транслировался в машинный. Эта двухфазность (не считая компоновки)
> и вызывает «три основные группы: ассемблеры, компиляторы
> и интерпретаторы».
> Такая двухфазность хорошо документирована на советских многотерминальных
> машинных комплексах, которые я застал в нашем ХНУРЭ.
Вот это, как мне кажется основное. Спасибо. Теперь более менее понятно откуда ноги растут.
> Плохиш © (08.02.07 11:23) [18]
> Классная ветка, не думал, что философов уже тоже заставляют
> изучать программирования, са ещё и на ассемблере :-))
Это почемуже сразу такое предвзятое обо мне мнение? :))
← →
evvcom ©
(2007-02-08 12:58)
[20]
> [17] Сергей М. © (08.02.07 11:19)
> 2. Не согласен.
Ну пусть будет так. Не возражаю. Мое понимание в общем основывалось на некотором опыте знакомства в былые времена с ассемблером и только. С Фортраном же я близко не знакомился. В принципе твое пояснение лишь немного расширило мое представление о трансляторах. Согласен, что я слишком узко его изобразил в [15] 🙂
← →
Сергей М. ©
(2007-02-08 13:06)
[21]
> evvcom © (08.02.07 12:58) [20]
Строго говоря, сравнивать или противопоставлять «Трансляторы/Компиляторы» vs «Интерпретаторы» не уместно.
← →
evvcom ©
(2007-02-08 13:15)
[22]
> [21] Сергей М. © (08.02.07 13:06)
Угу, согласен. Я и не пытался. Кстати,
> [17] Сергей М. © (08.02.07 11:19)
> 3. Ассемблерные среды интерпретирующего типа
я бы все ж назвал просто эмуляторами. Понятное дело, что все они интерпретирующего типа, причем совсем неважно, что берется за источник: текст на языке ассемблера или «исполняемый» код.
← →
Чапаев ©
(2007-02-08 14:29)
[23]
> Бред. Или у енмя уж совсем не правильное определение «интрепритатора»
> забито.
У етбя слова с ошибками. Откуда правильному определению взяться? %-)
> [17] Сергей М. © (08.02.07 11:19)
Компилятор и интерпретатор — два вида трансляторов, которые так или иначе исходный текст программы транслируют в машинный код.
← →
evvcom ©
(2007-02-08 14:30)
[24]
> [23] Чапаев © (08.02.07 14:29)
> Компилятор и интерпретатор — два вида трансляторов, которые
> так или иначе исходный текст программы транслируют в машинный
> код.
Это интерпретатор транслирует в машинный код? LOL 🙂
← →
Сергей М. ©
(2007-02-08 14:46)
[25]
> Чапаев © (08.02.07 14:29) [23]
Интерпретатор ничего не «транслирует», он интерпретирует вх.языковые конструкции «шаг за шагом», вызывая при этом на выполнение уже имеющиеся участки нативного кода, реализующего логику текущей интерпретируемой языковой конструкции.
← →
Чапаев ©
(2007-02-08 16:04)
[26]
> Это интерпретатор транслирует в машинный код?
Если программа исполняется, то она так или иначе транслируется в машинный код, нес па?
← →
Сергей М. ©
(2007-02-08 16:09)
[27]
> Чапаев © (08.02.07 16:04) [26]
>
> Если программа исполняется
Кем исполняется ? Процессором ? Виртуальной машиной ?
Определись уже …
← →
evvcom ©
(2007-02-08 16:12)
[28]
> [26] Чапаев © (08.02.07 16:04)
Программа эта исполняется в интерпретаторе, т.е. в тех функциях/процедурах, которые к программисту-пользователю не имеют никакого отношения, а значит и к машинному коду. Вот если бы ты сказал «к коду виртуальной машины» про интерпретатор, я б еще согласился, но с выражением «машинный код» AFAIK связывают именно инструкции для процессора.
> нес па?
это на каком? Французский я не знаю совсем.
← →
Чапаев ©
(2007-02-08 16:17)
[29]
> Кем исполняется ? Процессором ? Виртуальной машиной ?
А процессор — не «виртуальная машина для машинного кода»? 😉
← →
Чапаев ©
(2007-02-08 16:19)
[30]
> [29] Чапаев © (08.02.07 16:17)
+ туда же проц, который нативно исполняет жабовский байт-код. Не помню только, сумели его сделать или плюнули
← →
Сергей М. ©
(2007-02-08 16:40)
[31]
> Чапаев © (08.02.07 16:17) [29]
> процессор — не «виртуальная машина для машинного кода»?
С каких пор «железный» процессор стал «виртуальной машиной» ?
> проц, который нативно исполняет жабовский байт-код
Пример такого «железного» процессора ты, разумеется, не приведешь, ибо «не помнишь»)
← →
Чапаев ©
(2007-02-08 16:57)
[32]
> Пример такого «железного» процессора ты, разумеется, не
> приведешь, ибо «не помнишь»)
Могу, конечно, поискать в стопке журналов статью об этом… Но, как я уже сказал, я даже не знаю, довели ли разработку до конца.
← →
Чапаев ©
(2007-02-08 17:05)
[33]
> [32] Чапаев © (08.02.07 16:57)
Гм… Статью нашёл в «Компьютерном обозрении» №10 за 1998 год.
Вот ещё статьи нагуглил: http://www.osp.ru/nets/1997/01/142118, http://www.osp.ru/os/1999/01/179635.
← →
Stexen ©
(2007-02-08 18:39)
[34]
> Помогите разобраться пожалуйста? Информация на различных
> информационных сайтах весьма противоречива.
Компилятор — это программа
Интерпритатор — программа
Ассемблер — язык программирования низкого уровня — стандарта вообще говоря нет, для каждого процессора обычно свой… Хотя, вообще говоря, последнее утверждение вполне противоречиво, все опять таки же будет зависеть от компилятора, но с другой стороны для создания компилятора для языка ассемблера под конкретный процессор должен быть стандарт, т.о. для каждого процессора могут быть свои стандарты, соответсвенно Язык ассемблера некий абстрактный класс, имеющий множество классов детей — являющимися реализациями языка под конкретный тип процессора. А вообще wasm.ru есть!
Может ничего нового не сказал(лень все перечитывать) так что извените за флуд если что…
← →
oldman ©
(2007-02-08 18:43)
[35]
Анекдот из прошлого:
Купили мы как-то новую версию ассемблера.
Скопировали ее на диск.
Папку-то надо как-то назвать…
Так и назвали — ASS (блин, мозгов не хватило назвать TASM)
Пришел зав.отделом.
Долго пялился в монитер с медленно расширяющимися глазами.
Потом аккуратно подвел курсор к данной папке и нажал Ентер.
А ТАМ АССЕМБЛЕР!!! :))))))))))))
← →
GrayFace ©
(2007-02-08 19:10)
[36]
Уж точно не интерпретатор.
wHammer © (08.02.07 10:27) [12]
Бред какой-то. Вначале автор четко пишет, что интерпретатор исполняет программу, потом говорит о какой-то однозначности соответствия, чотя ежу понятно, Ассемблер ничего не исполняет, значит не удволитворяет его же определению.
evvcom © (08.02.07 10:41) [15]
3. Интерпретатор — программа, которая преобразует исходный текст или некий оптимизированный, но все же еще виртуальный, во время выполнения в некие инструкции и далее их выполняет.
Преобразовывать он ничего не должен. Если преобразует, то это уже Just in Time компилятором попахивает.
Чапаев © (08.02.07 16:04) [26]
Если программа исполняется, то она так или иначе транслируется в машинный код, нес па?
Не она. Исполняется код интерпретатора, программа ни к чему не приобразуется.
← →
GrayFace ©
(2007-02-08 19:11)
[37]
P.S. ИМХО
← →
oldman ©
(2007-02-08 19:14)
[38]
> GrayFace © (08.02.07 19:10) [36]
> Чапаев © (08.02.07 16:04) [26]
> Если программа исполняется, то она так или иначе транслируется
> в машинный код, нес па?
> Не она. Исполняется код интерпретатора, программа ни к чему
> не приобразуется.
Слова спиши…
Буду потомкам показывать в назидание…
← →
oldman ©
(2007-02-08 19:18)
[39]
> GrayFace © (08.02.07 19:10) [36]
Без обид:
По анкете — 20 лет.
Пора бы уж где-нибудь почитать, чем компилятор отличается от интерпретатора и как они работают с исходным текстом программы…
Чтобы больше вышеизложенного тобой не писать в форум программистов.
← →
GrayFace ©
(2007-02-08 22:25)
[40]
oldman © (08.02.07 19:18) [39]
По анкете — 20 лет.
19.
oldman © (08.02.07 19:18) [39]
Пора бы уж где-нибудь почитать, чем компилятор отличается от интерпретатора и как они работают с исходным текстом программы…
http://ru.wikipedia.org/wiki/%D0%98%D0%BD%D1%82%D0%B5%D1%80%D0%BF%D1%80%D0%B5%D1%82%D0%B0%D1%82%D0%BE%D1%80
Видимо, Вы плохо читали мой пост.
Что такое ассемблер? — Определение с сайта WhatIs.com
От
Ассемблер — это программа, которая принимает базовые компьютерные инструкции и преобразует их в набор битов, которые процессор компьютера может использовать для выполнения своих основных операций. Некоторые люди называют эти инструкции языком ассемблера, а другие используют термин язык ассемблера .
Вот как это работает:
- Большинство компьютеров поставляются с определенным набором самых простых инструкций, которые соответствуют основным операциям, которые компьютер может выполнять.Например, команда «Загрузить» заставляет процессор перемещать строку битов из места в памяти процессора в специальное место хранения, называемое регистром. Предполагая, что процессор имеет не менее восьми регистров, каждый из которых пронумерован, следующая инструкция переместит значение (последовательность битов определенной длины) из ячейки памяти 3000 в место хранения, называемое регистром 8:
L 8,3000
- Программист может написать программу, используя последовательность этих инструкций ассемблера.
- Эта последовательность инструкций ассемблера, известная как исходный код или исходная программа, затем указывается программе ассемблера при запуске этой программы.
- Программа на ассемблере принимает каждый оператор программы в исходной программе и генерирует соответствующий битовый поток или шаблон (последовательность нулей и единиц заданной длины).
- Выходные данные программы ассемблера называются объектным кодом или объектной программой относительно исходной программы ввода. Последовательность нулей и единиц, которые составляют объектную программу, иногда называют машинным кодом.
- После этого объектную программу можно запустить (или выполнить) в любое время.
На самых ранних компьютерах программисты фактически писали программы в машинном коде, но вскоре были разработаны языки ассемблера или наборы инструкций для ускорения программирования. Сегодня программирование на ассемблере используется только там, где требуется очень эффективный контроль над операциями процессора. Однако для этого требуется знание набора команд конкретного компьютера. Исторически сложилось так, что большинство программ было написано на языках «более высокого уровня», таких как COBOL, FORTRAN, PL / I и C.Эти языки легче изучать и быстрее писать программы, чем язык ассемблера. Программа, обрабатывающая исходный код, написанный на этих языках, называется компилятором. Как и ассемблер, компилятор принимает операторы языка более высокого уровня и сводит их к машинному коду.
Новейшей идеей в подготовке и переносимости программ является концепция виртуальной машины. Например, при использовании языка программирования Java операторы языка компилируются в общую форму машинного языка, известную как байт-код, которая может выполняться виртуальной машиной, своего рода теоретической машиной, которая приближает большинство компьютерных операций.Затем байт-код можно отправить на любую компьютерную платформу, которая ранее была загружена или встроена в виртуальную машину Java. Виртуальная машина знает об определенной длине инструкций и других особенностях платформы и гарантирует, что байт-код Java может работать.
Последний раз обновлялся в ноябре 2005 г.
Продолжить чтение об ассемблере
Узнайте подробнее о стратегии серверного оборудования
Введение в Ассемблер — GeeksforGeeks
Ассемблер — это программа для преобразования инструкций, написанных на низкоуровневом ассемблерном коде, в перемещаемый машинный код и генерации дополнительной информации для загрузчика.
Он генерирует инструкции, оценивая мнемонику (символы) в поле операции и находя значение символа и литералов для создания машинного кода. Теперь, если ассемблер выполняет всю эту работу за одно сканирование, он называется однопроходным ассемблером, в противном случае, если он выполняет несколько сканирований, он называется многопроходным ассемблером. Здесь ассемблер разделяет эти задачи на два прохода:
- Pass-1:
- Определите символы и литералы и запомните их в таблице символов и таблице литералов соответственно.
- Отслеживание счетчика местоположения
- Обработка псевдоопераций
- Pass-2:
- Создание объектного кода путем преобразования символьного кода операции в соответствующий числовой код операции
- Создание данных для литералов и поиск значений символов
Во-первых, мы возьмем небольшую программу на языке ассемблера, чтобы понять работу соответствующих проходов. Формат инструкции на языке ассемблера:
[Метка] [Код операции] [операнд] Пример: M ADD R1, = '3' где, M - метка; ADD - символический код операции; R1 - операнд символьного регистра; (= '3') - буквальный Программа сборки: Метка Операционный код операнда значение LC (счетчик местоположения) ДЖОН СТАРТ 200 MOVER R1, = '3' 200 MOVEM R1, X 201 L1 ДВИГАТЕЛЬ R2, = '2' 202 LTORG 203 Х ДС 1 204 КОНЕЦ 205
Давайте посмотрим, как работает эта программа:
- START: Эта инструкция запускает выполнение программы с позиции 200, а метка с START дает имя программе.(JOHN — имя программы)
- MOVER: Перемещает содержимое литерала (= ’3 ′) в регистровый операнд R1.
- MOVEM: Перемещает содержимое регистра в операнд памяти (X).
- MOVER: Он снова перемещает содержимое литерала (= ’2 ′) в регистровый операнд R2, а его метка указывается как L1.
- LTORG: Назначает адрес литералам (текущее значение LC).
- DS (пространство данных): Он назначает пространство данных 1 символу X.
- END: Завершает выполнение программы.
Работа Pass-1: Определите символьную и буквальную таблицу с их адресами.
Примечание: буквальный адрес указывается как LTORG или END.
Шаг 1: START 200 (здесь нет символа или литерала, поэтому обе таблицы будут пустыми)
Шаг 2: MOVER R1, = ‘3 ′ 200 (=’ 3 ‘- литерал, поэтому буквенная таблица)
Литерал | Адрес |
---|---|
= ‘3 ′ | — — — |
Шаг 3: MOVEM R1, X 201
упоминается до его объявления, поэтому он сохраняется в таблице символов с пустым полем адреса.
Символ | Адрес |
---|---|
X | — — — |
Step-4: L1 MOVER R2, = ‘2 ′ 202
L1 — метка 2 ′ является буквальным, поэтому сохраните их в соответствующих таблицах
Символ | Адрес | |
---|---|---|
X | — — — | |
L1 | 202 | |
Адрес | ||
= ‘3’ | — — — | |
= ‘2’ | — — — |
Шаг 5: первый LTORG 203
Назначить указанный адрес указанному адресу по значению LC, т.е.e., 203
Буквальный | Адрес |
---|---|
= ‘3’ | 203 |
= ‘2’ | — — — Шаг |
: X DS 1 204
Это оператор объявления данных, т.е. X назначается пространство данных 1. Но X — это символ, который упоминался ранее на шаге 3 и определен на шаге 6. Это состояние называется проблемой прямой ссылки, где переменная упоминается раньше. к его декларации и может быть решен путем обратного исправления.Итак, теперь ассемблер назначит X адрес, указанный значением LC текущего шага.
Шаг 7: END 205
Программа завершает выполнение, и оставшийся литерал получит адрес, указанный значением LC инструкции END. Вот полная таблица символов и букв, составленная на первом этапе ассемблера.
Литерал | Адрес |
---|---|
= ‘3’ | 203 |
= ‘2’ | 205 |
передаст
вместе со своими таблицами, сгенерированными с помощью таблицы Now перейти на второй этап ассемблера для дальнейшей обработки псевдо-кодов операций и машинных кодов операций.
Работа второго этапа:
Второй этап ассемблера генерирует машинный код путем преобразования символьных машинных кодов операций в их соответствующую битовую конфигурацию (машинно-понятная форма). Он хранит все машинные коды операций в таблице MOT (таблица кодов операций) с символическим кодом, их длиной и их битовой конфигурацией. Он также будет обрабатывать псевдооперации и сохранять их в таблице POT (таблица псевдоопераций).
Различные Базы данных, необходимые для Pass-2:
1. Таблица MOT (таблица кодов операций станка) 2.Таблица POT (таблица псевдо-кодов операций) 3. Базовая таблица (хранящая значение базового регистра) 4. LC (счетчик местоположения)
Взгляните на блок-схему, чтобы понять:
В целом ассемблер работает как:
Разработка программного обеспечения на языке ассемблера от Valvano
Разработка программного обеспечения на языке ассемблера от Valvano
Разработка программного обеспечения на языке ассемблера
Обзор
Джонатан В. Вальвано
В этой статье, в которой обсуждается программирование на языке ассемблера,
прилагается к книге Embedded Microcomputer Systems: Real Time Interfacing , опубликованной Brooks-Cole 1999.В этом документе всего четыре
частей
Обзор (этот документ)
Синтаксис (поля, псевдооперации)
Локальные переменные
Примеры
Программное обеспечение на языке ассемблера аналогично другому программному обеспечению
процессы разработки. Для получения общей информации о процессе
по разработке программного обеспечения см. главу 2 в документе Embedded Microcomputer Systems: Real Time Interfacing by Jonathan W. Valvano. Опять же, в этой статье речь пойдет о сборке.
языковая разработка с использованием приложения TExaS .Есть два типа команд, которые существуют в нашем
сборка исходный код . Коды операций — это обычные инструкции, которые переводятся в машинный код для
выполняться компьютером при запуске программы. Мы используем псевдооперацию
коды в нашем исходном коде, чтобы дать инструкции ассемблеру
сам. Ниже перечислены настройки цвета по умолчанию для
Редактор TExaS .
Метки показаны фиолетовым цветом
Операционные коды показаны синим
Псевдооперационные коды показаны серым
Числа показаны темно-синим цветом
Строки показаны в магните
Операнды показаны черным
Комментарии показаны зеленым цветом
Ошибки сборки показаны красным цветом
————————————————- ————————————-
Пример: замок на базе микрокомпьютера
Для иллюстрации процесс разработки программного обеспечения, мы реализуем
простой цифровой замок.Система блокировки имеет 7 тумблеров и
соленоид, как показано на следующем рисунке. Если 7-битный двоичный
шаблон на порте A биты 6-0 становится 0100011 минимум на 10 мс,
тогда соленоид активируется. Задержка 10 мс компенсирует
для дребезга переключателя. Для получения информации о переключателях и соленоидах
см. главу 8 книги «Встроенные микрокомпьютерные системы : интерфейс в реальном времени » Джонатана В. Вальвано. На данный момент нам нужно понять, что
что биты 6-0 порта A являются входными сигналами для компьютера и порта
Бит 7 — это выходной сигнал.
Прежде чем мы напишем ассемблерный код, нам нужно разработать план программного обеспечения.
Разработка программного обеспечения — это итеративный процесс. Хотя мы перечисляем
шагает процесс разработки в порядке 1,2,3 …, на самом деле
мы повторяем эти шаги снова и снова.
1) Начнем со списка входов и выходов. Мы указываем
диапазон значений и их значимость. В этом примере мы
будет использовать ПОРТУ. Биты 6-0 будут входами. 7 входных сигналов представляют
беззнаковое целое число от 0 до 127.Порт Бит 7 будет выходом.
Если PA7 равен 1, соленоид сработает, и дверь откроется.
быть разблокированным. В языке ассемблера мы используем псевдупы equ pseudoops для присвоения символьных имен PORTA DDRA соответствующим адресам портов $ 0000 $ 0002 .
PORTAequ $ 0000; PA6-PA0switches, PA7solenoidlock
DDRAequ $ 0002; задает вход или выход
2) Далее мы составляем список необходимых структур данных.
Структуры данных используются для сохранения информации. Если данные нужны
чтобы быть постоянным, то он размещается в глобальном пространстве.Если
программное обеспечение изменит свое значение, после чего оно будет размещено в ОЗУ.
В этом примере нам нужен 16-битный беззнаковый счетчик. Мы используем
org для размещения структур данных в ОЗУ, $ 0800 . Псевдопетля rmb резервирует байты для структуры. Эти строки также присваивают
символьное имя CNT на соответствующий адрес информации $ 0800 .
cntrmb2; 16-битный счетчик
org $ F000; EEPROM
Если структура данных может быть определена во время сборки и останется
исправлено, то его можно разместить в EEPROM.В этом примере мы
определит 8-битную фиксированную константу для хранения кода клавиши, который
оператору необходимо настроить разблокировку двери. Мы разместим эти
строки сразу после программы, чтобы они были определены
в памяти ROM или EEPROM. Псевдопетля fcb определяет 8-битную константу. Эта строка также присваивает
символическое имя ключ к соответствующему адресу информации.
keyfcb% 00100011; код клавиши
На данный момент не совсем понятно, где именно в EEPROM это
константа будет, но, к счастью для нас, ассемблер вычислит
точный адрес автоматически.После сборки программы
мы можем посмотреть строку в файле листинга или в таблице символов
чтобы увидеть, где в памяти размещена каждая структура.
3) Далее мы разрабатываем программный алгоритм, который представляет собой последовательность
операций, которые мы хотим выполнить. Есть много подходов к
описание плана. Опытные программисты могут разработать алгоритм
прямо на ассемблере. С другой стороны, большинству из нас нужно
абстрактный метод документирования желаемой последовательности действий.
Блок-схемы, псевдокод и код языка высокого уровня — это три
общие описательные форматы.Приложение TExaS уникально тем, что если вы нарисуете блок-схему
на компьютере, вы можете вставить его прямо в программу как
комментарий. Нет никаких формальных правил относительно псевдокода, скорее
это сокращение для описания того, что и когда делать.
Мы можем поместить наш псевдокод в качестве документации в комментарий
области нашей программы. Ниже показана блок-схема
слева и псевдокод и код C справа для нашего цифрового замка
пример.
Обычно мы помещаем программы в ROM или EEPROM.На MC68HC812A4
EEPROM начинается с $ F000, поэтому мы помещаем следующую псевдопетлю org перед программой.
org $ F000; EEPROM
Даже если эта программа не будет использовать стек, мы инициализируем
указатель стека на последнее место ОЗУ. На 6812 мы
выполните следующую инструкцию для инициализации стека.
mainlds # $ 0C00
Затем мы пишем ассемблерный код для реализации алгоритма, как показано.
в приведенной выше блок-схеме и псевдокоде. На шаге 1) мы инициализируем
Порт A, так что PA7 является выходом, а PA6-PA0 — входами.Для информации
о портах и регистрах направления см. главу 1 из Встроенные микрокомпьютерные системы: интерфейс в реальном времени Джонатана В. Вальвано.
movb # 80, DDRA; PA6-PA0 вход, PA7 выход
На шаге 2) отключаем соленоид.
bclrPORTA, # 80 долларов США; отключить электромагнитный замок
На шаге 3) мы инициализируем счетчик до 4000, что является числом
циклов требуется ждать 10 мс.
movw # 4000, cnt; 10,000,000 нс / (125 * 20)
На шаге 4) мы реализуем неопределенный цикл.Размещаем сборку
метка в местах программы, к которым мы хотим перейти. В
bra инструкция является безусловным переходом.
петля
бюстгальтер
Внутри неопределенного цикла мы проверяем,
соответствует ключевому коду. В этой реализации мы переходим к с , если переключатели не соответствуют ключевому коду. Если они совпадают, мы
выполнит инструкцию сразу после bne off .
loopldaaPORTA; [3] inputfrom7switches
anda # $ 7F; [1]
cmpakey; [3] matchkeycode?
bneoff; [3]
Если переключатели соответствуют коду клавиши, то 16-битный счетчик
уменьшено.
ldxcnt; [3]
dex; [1]
stxcnt; [3]
Если счетчик обнуляется, дверь разблокирована. Команда bne перейдет в цикл, если cnt не равно нулю. Команда bset установит PA7 в 1.
bneloop; [2] = 20циклов / цикл
bsetPORTA, # $ 80; enablesolenoidlock
braloop
Если переключатели не совпадают с кодом ключа, значит соленоид неисправен.
выключен, и cnt вернется к 4000.
offmovw # 4000, cnt; 10,000,000ns / (125 * 20)
bclrPORTA, # 80; disablesolenoidlock
braloop
Мы соединили вышеупомянутые части, чтобы создать исходный код.В
порядок инструкций очень важен, потому что он определяет
последовательность исполнения. Последние две строки определяют, где
компьютер начнет выполнение после сброса.
; ****** lock.rtf ************
; активировать соленоид (PA7 = 1) ifswitchesmatchkeycode
; переключить bounceisles меньше 10 мс
PORTAequ $ 0000; PA6-PA0switches, PA7solenoidlock
DDRAequ $ 0002; указывает вход или выход org $ 0800; RAM
cntrmb2; 16-битный счетчик
org $ F000; EEPROM
mainlds # $ 0C00
movb # 80 $, DDRA; PA6-PA0input, PA7output
bclrPORTA, # 80 $; disablesolenoidlock
,000,000,000,000 / movw # 4000, cnt; (125 * 20)
loopldaaPORTA; [3] inputfrom7switches
anda # $ 7F; [1]
cmpakey; [3] matchkeycode?
bneoff; [3]
ldxcnt; [3]
dex; [1]
stxcnt; [3]
bneloop; [2] = 20cycles / loop
; 7switchmatchkeycodeformorethan10ms
bsetPORTA, # 80; enablesolenoidlock
braloop
, cnt; 10,000,000 нс / (125 * 20)
bclrPORTA, # $ 80; disablesolenoidlock
braloop
keyfcb% 00100011; код клавиши
org $ FFFE
fdbmain
4) Последний этап — отладка.Вы можете запустить этот пример на
симулятор TExaS путем загрузки файлов lock.rtf , lock.uc и lock.io . Есть версии для всех четырех микрокомпьютеров, расположенных в
Каталоги MC6805, MC6808, MC6811 и MC6812. Для информации
по отладке см. главу 2 из Embedded Microcomputer Systems: Real Time Interfacing by Jonathan W. Valvano.
————————————————- ————————————-
Основы ассемблера
Ассемблеры — это программы, обрабатывающие язык ассемблера. источник
программные операторы и переводить их в исполняемую машину
языковые объектные файлы.Кросс-ассемблеры (такие как TExaS ) позволяют писать и редактировать исходные программы на одном компьютере (
host) для генерации исполняемого кода для другого компьютера (цели).
В нашем случае целью является симулятор микрокомпьютера, но поскольку TExaS генерирует записи S19, вы можете загрузить файл S19 на реальный компьютер.
для выполнения.
Символьный язык, используемый для кодирования исходных программ, которые будут
обрабатываемый Ассемблером, называется языком ассемблера. Язык
представляет собой набор мнемонических символов, представляющих: операции (т.е.,
мнемоники машинных инструкций или директивы ассемблеру),
символьные имена, операторы и специальные символы. Язык ассемблера
предоставляет мнемонические коды операций для всех машинных инструкций
в наборе инструкций. Инструкции определены и объяснены
в Справочном руководстве по программированию (для моделей 6805, 6808, 6811
или 6812), который можно найти в каталоге pdf на компакт-диске. Печатные копии этих руководств Motorola
можно получить в Литературном центре Motorola.Краткий обзор
каждой инструкции и примера использования можно найти, выполнив поиск
Contents страница механизма справки, включенного в приложение TExaS . Ассемблер также содержит мнемонические директивы.
которые определяют вспомогательные действия, которые должен выполнить Ассемблер.
Эти директивы не всегда переводятся на машинный язык.
Этот ассемблер поддерживает многие псевдооперационные коды.
Ассемблер TExaS — это двухпроходный ассемблер.Во время первого прохода
Исходная программа читается для разработки таблицы символов. В течение
на втором проходе объектный файл создается (собирается) с использованием
таблица символов, разработанная на первом этапе. Это во время второго прохода
что также создается листинг исходной программы. Таблица символов
воссоздается во втором проходе. Ошибка фазирования возникает, если значения таблицы символов, рассчитанные за два прохода
разные.
Ошибки, возникающие в процессе сборки (например, undefined
символ, недопустимый код операции, слишком далеко место назначения ветвления и т. д.) находятся
объяснено в файле со списком (я сократил комментарии, чтобы каждый
строка поместится на странице).
Copyright 1999-2000 Test EXecute And Simulate — Версия 1.00
; ****** lock.rtf *******
; активировать соленоид (PA7 = 1)
; bounceislessthan 10ms
$ 0000PORTAequ $ 0000
$ 0002DDRAequ $ 0002
$ 0800org $ 0800
$ 0800cntrmb2
$ F000org $ F000
$ F000CF0C00 [2] (0) {OP} mainlds # $ 0C00
$ F003180B800002 [4] (2) {OPwP} movb # 80 $, DDRA
$ F0084D0080 [4] (6) {rPOw} offbclrPORTA, # $ 80
$ F00BCC115C [2] (10) {OP} lookldd # 4444
$ F00E7C0800 [3] (12) {WOP} stdcnt
$ F0119600 [3] (15) {rfP} loopldaaPORTA
$ F013847F [1] (18) {P} anda # $ 7F
$ F015B1F028 [3] (19) {rOP} cmpakey
$ F01826EE [3] (22) {PPP / P} bneoff
$ F01AFE0800 [3 ] (25) {ROP} ldxcnt
$ F01D09 [1] (28) {O} dex
$ F01E7E0800 [3] (29) {WOP} stxcnt
$ F02126EE [3] (32) {PPP / P} bneloop
; 7switchesmatchkeycode
$ F0234C0080 [4] (35) {rPOw} bsetPORTA, # 80 $
$ F02620E3 [3] (39) {PPP} bralook
$ F02823keyfcb% 00100011
$ FFFEorg * FainFFE
db $ FFFEF ********** Таблица символов *********************
DDRA $ 0002
PORTA $ 0000
cnt $ 0800
ключ $ F028
look $ F00B
loop $ F011
main $ F000
off $ F008
Сборка прошла успешно
Исходный код — это файл символов ASCII, который обычно создается
с редактором.Каждый исходный оператор обрабатывается полностью
до того, как будет прочитан следующий исходный оператор. Поскольку каждое утверждение
обработано, Ассемблер проверяет метку, код операции и
поля операндов. Таблица кодов операций сканируется на соответствие
с известным кодом операции. Во время обработки стандартной операции
мнемоника кода, стандартный машинный код вставляется в
объектный файл. Если директива ассемблера обрабатывается,
предпринимаются надлежащие действия.
Любые ошибки, обнаруженные Ассемблером, отображаются после фактического
печатается строка, содержащая ошибку.Если исходный список не
сообщения об ошибках по-прежнему отображаются в TheLog.RTF
чтобы указать, что процесс сборки не прошел нормально.
Объектный код — это двоичные значения (инструкции и данные), которые,
при исполнении на компьютере выполнять намеченную функцию.
Файл листинга содержит адрес, объектный код и копию
исходного кода. При желании вы можете указать количество циклов
для выполнения инструкции, текущего количества циклов и явного
подробные сведения о типах циклов, необходимых для выполнения инструкции.Файл листинга также содержит таблицу символов, описывающую, где
в память будут загружены программа и данные. Таблица символов
это список всех имен, используемых в программе вместе с
значения. Символ создается, когда вы помещаете метку, начиная с столбца
1. Примеры этого типа: DATA, CNT, Start, Rep, Inp, NAME.
и РАЗМЕР. Значение таблицы символов для этого типа — абсолютное
адрес памяти, по которому будет выполняться инструкция, переменная или константа.
хранятся в памяти. Метка второго типа создается равной
псевдооперация.Значение для этого типа символа — это просто число
указанный в поле операнда. Когда ассемблер обрабатывает
инструкция с символом в ней, она просто заменяет фиксированный
значение вместо символа. Поэтому мы будем использовать символы для
уточнить (облегчить понимание) наши программы. Символ
таблица для этого примера —
*************** Таблица символов *********************
DDRA $ 0002
PORTA $ 0000
cnt $ 0800
key $ F033
loop $ F011
main $ F000
off $ F028
Компилятор преобразует исходный код языка высокого уровня в
объектный код.Кросс-компилятор также преобразует исходный код в объект.
code и создает файл листинга, за исключением того, что объектный код
создан для целевой машины, которая отличается от машины
запуск кросс-компилятора. TExaS — кросс-ассемблер, потому что он работает на компьютере Intel, но
создает код объекта 6805/6808/6811/6812. Hiware и ImageCraft’s
ICC11 и ICC12 включают кросс-ассемблер и кросс-компиляторы.
потому что они запускаются на ПК и создают объект 6805/6808/6811/6812
код.Для получения общей информации о разработке программного обеспечения на языке C
см. главу 2 из Встроенные микрокомпьютерные системы: интерфейс в реальном времени Джонатана В. Вальвано.
Motorola использует S-записи для хранения объектного кода. 16-битный
значения сохраняются в памяти с первым старшим байтом.
Для получения дополнительной информации о конкретном формате S-записи
см. записи S19 содержат объектный код. S-запись для приведенного выше примера выглядит как
следует. Фактический объектный код окрашен в синий цвет.
S121F000CF0C00180B8000024D008018030FA008009600847FB1F033260EFE0800091F
S119F01E7E080026EE4C008020E918030FA008004D008020DE23A9
S105FFFEF0000D
S
————————————————- ————————————-
Запуск на оценочной плате
Когда отладка включает управление реальное оборудование, мы должны использовать
настоящий микрокомпьютер, работающий в режиме реального времени. Потому что программы
хранятся в ПЗУ или EEPROM на однокристальном микрокомпьютере.
трудно отлаживать.Для решения этой проблемы существуют оценки
платы, которые запускают микрокомпьютер в расширенном режиме и включают
отладчик. В этой системе разработки мы также используем кросс-ассемблер.
или кросс-компилятор для преобразования наших исходных программ в листинг
файл и объектный файл. Объектный файл передается по серийному
порт на оценочную плату и загружается в оперативную память. Простой отладчик
(например, 6811 EVB с использованием отладчика BUFFALO) позволяет нам тестировать
наше программное обеспечение. Типичные функции отладчика включают:
запускать выполнение по определенному адресу
устанавливать точку останова по определенному адресу
читать / изменять регистры микрокомпьютера
читать / изменять порты ввода-вывода микрокомпьютера
читать / изменять RAM
читать / стирать / программировать EEPROM
загружать объектный код в оперативную память, полученную с ХОЗЯЙСТВЕННОГО ПК.
Сложные среды разработки включают редактор, компилятор,
ассемблер, связь через последовательный порт и отладчик в одном
приложение, запущенное на ПК. Для получения дополнительной информации о программном обеспечении
о разработке см. главу 2 из Встроенные микрокомпьютерные системы: интерфейс в реальном времени Джонатана В. Вальвано. Для информации о разработке оборудования
платформы, см. Руководство по лабораторной работе, прилагаемое к этой книге.
————————————————- ————————————-
Моделирование
При разработке программного обеспечения с использованием симулятора мы использовать кросс-ассемблер
или кросс-компилятор, работающий на ПК, для преобразования наших исходных программ
в файл листинга и объектный файл.Затем мы «запускаем» нашу программу
на симуляторе, имитирующем микрокомпьютер с его внешним компонентом.
Моделирование в этой среде сложнее, чем на другом компьютере.
приложение из-за исполнения программного обеспечения тесно связано
к аппаратному обеспечению (чрезвычайно зависящему от него). Моделирование встроенного
система эффективна только в том случае, если все программное обеспечение, компьютер, внешние
моделируются механические и внешние электрические компоненты. Другой
Проблема усложняется тем, что внешний механический
и электрические устройства.На следующем рисунке показано программное обеспечение.
процесс разработки с использованием тренажера.
Дополнительные темы включают.
Синтаксис языка ассемблера
Поле метки
Поле операции
Поле операнда
Поле комментария
Список ошибок сборки дает результаты сборки
Список ошибок сборки типы ошибок сборки
Псевдооперации сборки — это операции времени сборки
Записи S19 содержат объект код
За подробным объяснением инструкций и их адресацией
режимах, см. справочную систему приложения TExaS .Иногда лучший способ изучить новую технику
это наблюдать за примерами. См. Файл ReadMe.txt для получения списка примеров, которые можно запустить на симуляторе.
В приложение TExaS включено множество примеров на языке ассемблера. В этот документ включены несколько простых примеров 6812.
Этот документ состоит из четырех общих частей
Обзор (этот документ)
Синтаксис (поля, псевдооперации)
Локальные переменные
Примеры
Введение в историческую эволюцию практики программирования
В первые дни вычислительной техники оборудование было дорогим, а программисты — дешевыми.На самом деле программисты были настолько дешевы, что их даже не называли «программистами», а на самом деле они обычно были математиками или инженерами-электриками. Ранние компьютеры использовались для быстрого решения сложных математических задач, поэтому математики естественно подходили для работы по «программированию».
Что такое программа?
Для начала немного предыстории. Компьютеры ничего не могут сделать сами по себе, поэтому им требуются программы, управляющие их поведением. Программы можно рассматривать как очень подробные рецепты, которые принимают ввод и производят вывод.Шаги в рецепте состоят из инструкций, которые работают с данными. Хотя это звучит сложно, вы, вероятно, знаете, как работает это утверждение:
1 + 2 = 3
Знак плюс — это «инструкция», а цифры 1 и 2 — это данные. Математически знак равенства указывает на то, что обе стороны уравнения «эквивалентны», однако в большинстве компьютерных языков используется некоторый вариант равенства для обозначения «присваивания». Если бы компьютер выполнял этот оператор, он бы сохранил результаты сложения («3») где-нибудь в памяти.
Компьютеры умеют вычислять числа и перемещать данные по иерархии памяти машины. Я не буду много говорить о памяти, за исключением того, что она обычно бывает двух видов: быстрая / маленькая и медленная / большая. Регистры ЦП очень быстрые, очень маленькие и действуют как блокноты. Основная память обычно очень большая и не такая быстрая, как регистровая память. Процессоры перетасовывают данные, с которыми они работают, из основной памяти в регистры и обратно во время выполнения программы.
Сборщики
Компьютеры были очень дорогими, а люди — дешевыми.Программисты проводили бесконечные часы, переводя рукописные математические вычисления в компьютерные инструкции, которые компьютер мог выполнять. У самых первых компьютеров были ужасные пользовательские интерфейсы, некоторые из которых состояли только из переключателей на передней панели. Переключатели представляют единицы и нули в одном «слове» памяти. Программист настраивал слово, указывал, где его сохранить, и фиксировал слово в памяти. Это отнимало много времени и было подвержено ошибкам.
В конце концов, инженер-электрик решил, что его время недешево, и написал программу с вводом, написанным как «рецепт», выраженный в терминах, которые люди могут прочитать, вывод в машиночитаемой версии.Это был первый «ассемблер», и это было очень спорно. Люди, которым принадлежали дорогие машины, не хотели «тратить» вычислительное время на задачу, которую люди уже выполняли; хоть и медленно и с ошибками. Со временем люди начали ценить скорость и точность ассемблера по сравнению с программой, собранной вручную, и количество «реальной работы», выполняемой с помощью компьютера, увеличилось.
Хотя программы на ассемблере были большим шагом вперед от включения битовых шаблонов на лицевую панель машины, они все еще были довольно специализированными.Приведенный выше пример сложения мог бы выглядеть примерно так:
01 MOV R0, 1
02 MOV R1, 2
03 ADD R0, R1, R2
04 MOV 64, R0
05 STO R2, R0
Каждая строка представляет собой компьютерную инструкцию, которая начинается с сокращенного имени инструкции, за которым следуют данные, над которыми эта инструкция работает. Эта небольшая программа сначала «переместит» значение 1 в регистр R0, а затем 2 в регистр R1. Строка 03 добавляет содержимое регистров R0 и R1 и сохраняет полученное значение в регистре R2.Наконец, строки 04 и 05 определяют, где результат должен быть сохранен в основной памяти (адрес 64). Управление местом хранения данных в памяти — одна из самых трудоемких и подверженных ошибкам частей при написании компьютерных программ.
Компиляторы
Сборка была намного лучше, чем написание компьютерных инструкций вручную; однако первые программисты стремились писать программы так, как они привыкли писать математические формулы. Это стимулировало развитие компилируемых языков более высокого уровня, некоторые из которых являются историческими сносками, а другие используются до сих пор.ALGO — одна из таких сносок, в то время как реальные проблемы продолжают решаться сегодня с помощью таких языков, как Fortran и C.
Введение этих языков «высокого уровня» позволило программистам писать свои программы в более простых терминах. На языке C наша дополнительная программа ассемблера будет написана:
Первый оператор описывает часть памяти, которую будет использовать программа. В этом случае размер памяти должен быть целым числом, а ее имя — x . Второй оператор — это сложение, хотя и написано «в обратном порядке».«Программист на C прочитал бы это, поскольку« X присваивается результат один плюс два ». Обратите внимание, что программисту не нужно указывать, где поместить x в память, поскольку компилятор позаботится об этом.
Новый тип программы, называемый «компилятором», превращает программу, написанную на языке высокого уровня, в версию на языке ассемблера, а затем запускает ее через ассемблер для создания машиночитаемой версии программы. Такую композицию программ часто называют «цепочкой инструментов», поскольку выходные данные одной программы отправляются непосредственно на вход другой программы.
Огромным преимуществом компилируемых языков перед программами на ассемблере был перенос с одной компьютерной модели или марки на другую. В первые дни развития вычислительной техники произошел взрывной рост различных типов вычислительного оборудования таких компаний, как IBM, Digital Equipment Corporation, Texas Instruments, UNIVAC, Hewlett Packard и других. Ни у одного из этих компьютеров нет ничего общего, кроме того, что их нужно было подключать к источнику питания. Архитектуры памяти и ЦП сильно различались, и на перевод программ с одного компьютера на другой часто уходили человеко-годы.
Для языков высокого уровня необходимо было только перенести инструментальную цепочку компилятора на новую платформу. Как только компилятор был доступен, программы на языке высокого уровня можно было перекомпилировать для нового компьютера с небольшими изменениями или без них. Составление языков высокого уровня было поистине революционным.
Жизнь программистов стала очень хорошей. Было намного проще выразить проблемы, которые они хотели решить, с помощью языков высокого уровня. Стоимость компьютерного оборудования резко падала из-за достижений в области полупроводников и изобретения интегральных микросхем.Компьютеры становились быстрее и мощнее, а также становились намного дешевле. В какой-то момент, возможно, в конце 80-х, произошла инверсия, и программисты стали дороже, чем оборудование, которое они использовали.
Переводчики
Со временем возникла новая модель программирования, в которой специальная программа, называемая «интерпретатором», считывала программу и превращала ее в компьютерные инструкции, которые должны были выполняться немедленно. Интерпретатор принимает программу в качестве входных данных и интерпретирует ее в промежуточную форму, очень похожую на компилятор.В отличие от компилятора, интерпретатор затем выполняет промежуточную форму программы. Это происходит каждый раз, когда запускается интерпретируемая программа, тогда как скомпилированная программа компилируется только один раз, и компьютер выполняет машинные инструкции «как написано».
В качестве примечания: когда люди говорят «интерпретируемые программы работают медленно», это основной источник предполагаемой недостаточной производительности. Современные компьютеры настолько удивительны, что большинство людей не могут отличить скомпилированные и интерпретируемые программы.
Интерпретируемые программы, иногда называемые «скриптами», еще проще перенести на различные аппаратные платформы. Поскольку сценарий не содержит никаких машинно-зависимых инструкций, одна версия программы может работать на многих разных компьютерах без изменений. Загвоздка, конечно же, в том, что интерпретатор должен быть перенесен на новую машину, чтобы это стало возможным.
Одним из примеров очень популярного интерпретируемого языка является perl. Полное выражение нашей проблемы сложения на языке Perl:
$ х = 1 + 2
Хотя он выглядит и действует так же, как версия C, в нем отсутствует оператор инициализации переменной.Есть и другие отличия (которые выходят за рамки этой статьи), но вы можете видеть, что мы можем написать компьютерную программу, очень близкую к тому, как математик написал бы ее от руки карандашом на бумаге.
Виртуальные машины
Последнее повальное увлечение моделями программирования — виртуальные машины, часто сокращенно ВМ. Есть две разновидности виртуальной машины; системные виртуальные машины и виртуальные машины процессов. Оба типа виртуальных машин обеспечивают некоторый уровень абстракции от «реального» вычислительного оборудования, хотя и имеют разные области действия.Системная виртуальная машина — это программное обеспечение, которое предлагает замену физическому оборудованию, в то время как виртуальная машина процесса предназначена для выполнения программы независимо от системы. Таким образом, в этом случае виртуальная машина процесса (далее виртуальная машина) похожа по объему на интерпретатор в том, что программа сначала компилируется в промежуточную форму, прежде чем виртуальная машина ее выполнит.
Основное различие между интерпретатором и виртуальной машиной заключается в том, что виртуальная машина реализует идеализированный ЦП, доступ к которому осуществляется через его виртуальный набор команд.Эта абстракция позволяет писать инструменты интерфейса пользователя, которые компилируют программы, написанные на разных языках, и нацелены на виртуальную машину. Вероятно, самая популярная и известная виртуальная машина — это виртуальная машина Java (JVM). Первоначально JVM предназначалась только для языка программирования Java еще в 1990-х годах, но теперь она поддерживает многие популярные компьютерные языки: Scala, Jython, JRuby, Clojure и Kotlin, чтобы перечислить лишь некоторые из них. Есть и другие примеры, которые могут быть неизвестны. Я только недавно узнал, что мой любимый язык Python — это не интерпретируемый язык, а язык, размещенный на виртуальной машине!
Виртуальные машины продолжают историческую тенденцию к сокращению объема специфичных для платформы знаний, необходимых программисту для выражения своей проблемы на языке, который поддерживает их специфические потребности в предметной области.
Это обертка
Надеюсь, вам понравится этот учебник по некоторым из менее заметных частей программного обеспечения. Есть ли другие темы, в которые вы хотите, чтобы я погрузился в следующий раз? Дай мне знать в комментариях.
Эта статья изначально была опубликована на PyBites и перепечатывается с разрешения.
образование — Зачем нужен ассемблер?
Зачем нужен ассемблер?
Что ж, на самом деле есть только один язык, который нам когда-либо понадобится , который называется «машинный язык» или «машинный код».Выглядит это так:
0010000100100011
Это единственный язык, на котором ваш компьютер может разговаривать напрямую. Это язык, на котором говорит ЦП (и технически разные типы ЦП говорят на разных версиях). Также отстойно смотреть и пытаться понять.
К счастью, каждый раздел двоичного файла соответствует определенному значению. Он разделен на несколько разделов:
0010 | 0001 | 0010 | 0011
тип операции исходный регистр другой исходный целевой регистр
0010 0001 0010 0011
Эти значения соответствуют:
тип операции 0010 = сложение
исходный регистр 0001 = регистр 1
другой источник 0010 = регистр 2
регистр назначения 0011 = регистр 3
Таким образом, эта операция складывает числа в регистрах 1 и 2 и помещает это значение в регистр 3.Если вы буквально поместите эти значения в ЦП и скажете ему «идти», он добавит вам два числа. Операция «вычитание» может быть 0011 или что-то в этом роде, вместо 0010 здесь. Какое бы значение ни заставлял ЦП делать вычитание.
Итак, программа может выглядеть так (не пытайтесь понять ее, поскольку я придумал эту конкретную версию машинного кода для объяснения вещей):
инструкция 1: 0010000100100011
инструкция 2: 0011000110100100
инструкция 3: 0101001100010111
инструкция 4: 0010001001100000
Отстойно читать? Определенно. Но он нам нужен для ЦП . Что ж, если каждый машинный код соответствует определенному действию, давайте просто сделаем простое «английское» сокращение, а затем, когда мы поймем, что делает программа, преобразуем его в настоящий двоичный машинный код и передадим его ЦП для выполнения.
Итак, наша оригинальная инструкция сверху могла выглядеть так:
(значение) тип операции регистр источника другой регистр назначения источника
(машинный код) 0010 0001 0010 0011
("Английский") добавить r1 r2 r3
Обратите внимание, что эта английская версия имеет точное соответствие машинному коду .Поэтому, когда мы пишем строчку на этом «английском», мы на самом деле просто пишем более дружелюбный и понятный машинный код.
Ну, это ассемблер. Вот почему он существует и был создан изначально.
Чтобы понять, зачем нам это нужно сейчас, прочтите приведенные выше ответы, но ключ к пониманию заключается в следующем: языки высокого уровня не имеют единственного представления — это машинный код. Например. на C или Python, или что-то еще:
г = х + у
Это звучит так же, как наше добавление сверху, при условии, что x
находится в регистре 1, y
находится в регистре 2, а z
должно оказаться в регистре 3.Но как насчет этой линии?
г = х * 2 + (у / 6) * р + д - г
Попробуйте представить эту строку в 16-битном двоичном формате и сказать ЦП «идти». Вы не можете. В машинном коде нет единой инструкции операции для выполнения сложения, вычитания и всего остального с 4 или 5 переменными одновременно. Поэтому сначала его нужно преобразовать в последовательность машинного кода . Это то, что вы делаете, когда «компилируете» или «интерпретируете» язык высокого уровня.
Ну, у нас есть программы для этого, зачем нам сейчас сборка? Допустим, ваша программа работает медленнее, чем вы ожидаете, и вы хотите знать, почему.Глядя на «вывод» этой строки на машинном языке, он может выглядеть так:
1010010010001001
0010001000010000
0110010000100100
0010001011000010
0010100001000001
0100010100000001
0010010101000100
0010101010100000
0000100111000010
Просто чтобы закончить эту одну строчку Python. Так вы действительно хотите отладить это?!?!?! НЕТ . Вместо этого вы просите свой компилятор любезно предоставить вам вывод в форме, которую вы действительно легко понимаете, а именно версию на языке ассемблера, соответствующую точно этому машинному коду.Затем вы можете выяснить, делает ли ваш компилятор что-то глупое, и попытаться исправить это.
(Дополнительное примечание к совету @ Raphael: вы могли бы построить ЦП, который работает с вещами, отличными от двоичных кодов, такими как троичные (основание 3) или десятичные коды, или даже ASCII. Однако для практических целей мы действительно придерживаемся двоичного кода.)
Ассемблеры и язык ассемблера
Стр. 1 из 3
Инструкции, которые распознают большинство компьютеров, слишком просты, чтобы люди могли беспокоиться о них — и поэтому мы изобрели язык ассемблера.Узнайте, как это работает и как с него началось все движение по абстрагированию от аппаратного обеспечения компьютера.
Что знают программисты
Содержание
- Компьютер — в чем главная идея? *
- Принцип памяти — Компьютерная память и голубятни *
- Принципы исполнения — ЦП
- Суть программирования
- переменных — объем, время жизни и многое другое *
- Двоичная арифметика
- Шестнадцатеричный *
- Двоичный — отрицательные числа
- Числа с плавающей запятой
- Внутри компьютера — адресация
- Функция Mod
- Рекурсия
- Утерянное искусство карты памяти *
- Хеширование — величайшая идея в программировании
- Расширенное хеширование
- XOR — Волшебный своп
- Введение в XML для программистов
- От данных к объектам *
- Что такое функция первого класса — и почему вам это должно быть небезразлично *
- Стеки и деревья
- Стек LIFO — краткое руководство *
- Структуры данных — деревья
- Внутренние случайные числа
- Метод Монте-Карло
- Кэш-память и принцип кеширования
- Сжатие данных The Dictionary Way
- Сложные даты *
- Последовательное хранение *
- Магия слияния *
- Мощность операторов
- Сердце компилятора *
- Основы указателей
- Функциональное и дисфункциональное программирование *
* Недавно отредактированный
Мы уже рассмотрели, что такое компьютерная программа, но полностью проигнорировали вопрос о том, как в первую очередь создается компьютерная программа.Естественный язык большинства компьютеров — двоичный, потому что это то, на чем основано их оборудование.
Когда вы пишете инструкцию в двоичном формате, это больше, чем просто абстрактная идея о том, что что-то должно быть сделано, и то, как машина таинственным образом «понимает» и выполняет то, что ей говорят. Отдельные биты в инструкции управляют тем, что делает оборудование. Один бит может выбирать конкретный регистр, другой устанавливать добавляемое арифметическое устройство, а третий может очищать бит состояния. Двоичный код инструкции — это набор «рычагов», которые заставляют машину делать то, что вы хотите.
Вы можете запрограммировать компьютер в двоичном формате, если хотите. Однако программирование в двоичном формате — неинтересное и не очень продуктивное занятие. Вы должны помнить, что делает каждый бит и как собрать их вместе, чтобы получить нужные вам инструкции. Ошибка в одном бите, и инструкция означает другое. Чтение двоичного кода также является сложной задачей для обычного человека. Даже в этом случае в первые дни именно так программировали компьютеры — часто с использованием блоков переключателей и ламп на лицевых панелях.
Быстро изобрели лучший способ выражения вещей.
Мнемонические коды
Первым шагом от чистого двоичного или машинного кода было использование символов для инструкций.
Например, в машинном коде x86 инструкция для сохранения восьмибитового значения xxxxxxxx, где x равно 0 или 1, в регистре BL:
10110000xxxxxxxx
Например, если данные — 01010101, полная команда будет:
1011000001010101
Это немного легче читать, если он записан в шестнадцатеричном формате как B055, который загружает 55 шестнадцатеричных значений в регистр BL.(Обратите внимание, что буква B в начале инструкции — просто совпадение и не имеет ничего общего с именем регистра BL.)
Hex может быть лучше двоичного, но он все равно не запоминается большинству нормальных людей. Решение — использовать легко запоминающиеся символы или мнемонику.
Например:
MOV BL, 055H
естественно читается как «переместить 55 шестнадцатеричных чисел в регистр BL». Это представление также скрывает тот факт, что все различные инструкции «перемещения» имеют разные двоичные машинные коды.Например, чтобы переместить 16-битное значение в регистр BX, вы должны использовать:
10111000
, за которыми следуют 16 бит, которые вы хотите загрузить, но в качестве мнемоники это будет:
MOV BX, 01234H
, который больше похож на инструкцию первого хода.
Другими словами, использование мнемоники не только упрощает чтение, но и унифицирует структуру машинного кода, группируя все различные инструкции перемещения в виде MOV, за которым следует то, что следует переместить из источника в место назначения, т.е.е.
MOV пункт назначения, источник
Обратите внимание, что это сложнее, чем вы думаете, поскольку инструкция, которую программист считает одной единственной инструкцией, соответствует очень большому набору инструкций машинного кода, которые зависят от того, что перемещается и куда.
Давайте создадим ассемблер
Сначала эти мнемоники были просто вспомогательными средствами для запоминания.
Программист написал программу, используя мнемонику, а затем вручную перевел программу, используя список кодов, в машинный код.
Но тут какому-то умному программисту пришла в голову идея, сэкономившая много работы. В конце концов, все программисты в основном ленивы, это главная причина того, чтобы быть программистом!
Кто-то подумал,
«что, если я напишу программу для преобразования мнемоники в машинный код».
Совершенно очевидно.
Все, что нужно, — это большая таблица преобразований мнемонического кода в машинный. Результатом этой идеи стал первый «ассемблер» и первый «ассемблер».
Терминология вначале была не совсем стабильной, и вы обнаружите, что некоторые ранние языки ассемблера назывались «автокодированием» и многими другими вещами. Неважно, как вы это называете, идея ассемблера — это просто комбинация использования мнемоники для представления машинных кодов и использования программы для их преобразования в машинный код перед запуском программы.
Это начало процесса разработки, который идет от базового использования мнемоники до сложных языков программирования, которые мы используем сегодня.
Процесс сборки
Процесс сборки
Ассемблер — это переводчик, который переводит программу на ассемблере в обычную машину.
языковая программа. По сути, ассемблер просматривает программу по одной строке за раз, и
генерирует машинный код для этой инструкции. Затем ассемблер переходит к следующей инструкции.Таким образом создается вся программа машинного кода. Для большинства инструкций этот процесс работает
хорошо, например, для инструкций, которые ссылаются только на регистры, ассемблер может вычислить
машинный код легко, поскольку ассемблер знает, где находятся регистры.
Рассмотрим инструкцию ассемблера, подобную следующей
JMP ПОЗЖЕ ... ... ПОЗЖЕ:
Это называется прямой ссылкой. Если ассемблер обрабатывает файл по одной строке за раз,
тогда он не знает, где находится ПОЗЖЕ, когда впервые встречает инструкцию перехода.Итак, это не так
знать, является ли прыжок коротким, ближним или дальним. Есть большая разница между
эти инструкции. Они имеют длину 2, 3 и 5 байтов соответственно. Ассемблеру придется
угадайте, как далеко находится инструкция, чтобы сгенерировать правильную инструкцию. Если ассемблер
предположения ошибочны, тогда адреса всех остальных этикеток в программе будут неправильными, и
код необходимо будет регенерировать. Или ассемблер всегда мог выбрать худший вариант. Но
это будет означать неэффективность программы, так как все прыжки будут считаться далеко
jumps и будет иметь длину 5 байтов, тогда как на самом деле большинство переходов являются короткими, а их длина составляет всего 2
длина в байтах.
Soooooooo, что нужно сделать, чтобы ассемблер сгенерировал правильную инструкцию?
Ответ: просканируйте код дважды.