Язык ассемблера уроки программирования: Уроки по Ассемблеру для начинающих
Погружение в ассемблер. Зачем учить ассемблер в 2020 году — «Хакер»
Ты решил освоить ассемблер, но перед этим хочешь понять, что тебе это даст как программисту? Стоит ли входить в мир программирования через ассемблер, или лучше начать с какого‑нибудь языка высокого уровня? И вообще, нужно ли знать ассемблер, чтобы стать полноценным программистом? Давай разберемся во всем этом по порядку.
Погружение в ассемблер
Это вводная статья цикла «Погружение в ассемблер», которую мы публикуем в честь его завершения. Ее полный текст доступен без подписки. Прочитав ее, ты можешь переходить к другим статьям этого курса:
Ради чего стоит изучать ассемблер?
Стоит освоить ассемблер, если ты хочешь:
- разобраться, как работают компьютерные программы. Разобраться в деталях, на всех уровнях, вплоть до машинного кода;
- разрабатывать программы для микроскопических встраиваемых систем. Например, для 4-битных микроконтроллеров;
- понять, что находится под капотом у языков высокого уровня;
- создать свой собственный компилятор, оптимизатор, среду исполнения JIT, виртуальную машину или что‑то в этом роде;
- ломать, отлаживать или защищать компьютерные системы на самом низком уровне. Многие изъяны безопасности проявляются только на уровне машинного кода и могут быть устранены только с этого уровня.
Не стоит осваивать ассемблер, если ты хочешь ускорить другие свои программы. Современные оптимизирующие компиляторы справляются с этой задачей очень хорошо. Ты вряд ли сможешь обогнать их.
Кто выдаст лучший ассемблерный код?
Почему обогнать компилятор практически невозможно? Смотри, для тебя же очевидно, что компьютер в шахматы не обыграть, даже если ты играешь лучше, чем создатель шахматной программы? С оптимизирующими компиляторами та же история. Только оптимизирующий компилятор играет не шахматными фигурами, а контекстными обстоятельствами.
В современных процессорах практически ничто из того, что влияет на производительность, нельзя обсуждать в отрыве от контекста. Одна и та же комбинация из десятка ассемблерных инструкций выполняется с резкими отличиями по скорости (в тысячи или даже миллионы раз), в зависимости от целой кучи самых разнообразных обстоятельств.
- Те данные, к которым ты сейчас обращаешься, загружены в кеш или нет? А сама комбинация ассемблерных инструкций?
- Если ни данные, ни код не размещены в кеше, то не перетаскивает ли их процессор туда втихомолку, предполагая, что к ним будут обращаться в ближайшее время?
- Какие инструкции были выполнены непосредственно перед нашим десятком? Они сейчас все еще на конвейере?
- Мы случаем не достигли конца текущей страницы виртуальной памяти? А то, не дай бог, добрая половина нашего десятка попадет на новую страницу, которая к тому же сейчас, по закону подлости, вытеснена на диск. Но если нам повезло и новая страница таки в физической памяти, можем ли мы добраться до нее через TLB-буфер? Или нам придется продираться к ней через полный адрес, используя таблицы страниц? И все ли нужные нам таблицы страниц загружены в физическую память? Или какие‑то из них вытеснены на диск?
- Какой именно процессор выполняет код? Дешевенький i3 или мощный i7? Бывает, что у дешевых процессоров тот же набор инструкций, что и у мощных, но продвинутые инструкции выполняются в несколько шагов, а не за один.
И все это только верхушка айсберга, малая часть того, что тебе придется учитывать и анализировать, когда будешь стараться переиграть компилятор.
Есть такой миф, что программы, написанные на ассемблере, работают в десять раз быстрее. Этот миф уходит корнями в семидесятые годы. Компиляторы в те далекие времена генерировали код настолько бездарно, что у каждого уважающего себя программиста был черный список запрещенных языковых конструкций.
Когда наши коллеги из прошлого писали программы, они либо держали в уме этот черный список и не давали своим пальцам набивать проблемные конструкции, либо настраивали специальный препроцессор, который конвертировал исходник в более низкоуровневое беспроблемное представление на том же языке. С тех пор минуло 50 лет. Компиляторы возмужали, но миф остался.
Конечно, даже сегодня можно изредка встретить уникума, который пишет более быстрый код, чем компилятор. Вот только времени у него на это уходит так много, что ни в какие ворота не лезет. Плюс для оптимизации от тебя требуется, чтобы ты назубок знал весь набор инструкций процессора.
Вдобавок, поскольку ты шлифуешь свой код вручную, никакой компилятор не подстрахует тебя, не поможет отловить баги, которые ты неизбежно плодишь, когда пишешь программу.
Кроме того, твой ассемблерный код будет непереносимым. То есть, если ты захочешь, чтобы твоя программа запускалась на другом типе процессора, тебе придется полностью переписать ее, чтобы создать модификацию, заточенную под набор инструкций этого другого процессора. Само собой, тебе эти инструкции тоже надо знать назубок.
В итоге ты потратишь в десятки и сотни раз больше времени, чем если бы доверился оптимизирующему компилятору, — но результат, скорее всего, окажется медленнее, а не быстрее.
При этом иногда оптимизирующий компилятор выплевывает ассемблерный код, логика которого ну совсем непонятна. Однако не спеши обвинять компилятор в глупости. Давай разберем пример.
Когда ты пишешь на С что‑то вроде x
, то естественным образом ожидаешь увидеть в ассемблере инструкцию, которая умножает переменную a
на двойку. Но компилятор знает, что сложение дешевле умножения. Поэтому он не умножает a
на двойку, а складывает ее с самой собой.
Больше того, глядя на b
, компилятор может счесть, что b
предпочтительнее, чем b*3
. Иногда тройное сложение быстрее умножения, иногда нет. А иногда компилятор приходит к выводу, что вместо исходного выражения быстрее будет вычислить (
. Или даже ((
.
А если x
используется лишь однократно — причем в связке с парой строк последующего кода, — компилятор может вообще не вычислять x
, а просто вставить a*2
вместо икса. Но даже если x
используется и компилятор видит что‑то вроде y
, он может исправить эти расчеты на y
, удивляясь твоей расточительности. Расточительности в плане вычислительной сложности.
Размышления подобного рода неизбежно заводят тебя в запутанный лабиринт альтернативных вариантов. Все их нужно просчитать, чтобы выбрать лучший. Но даже когда ты сделаешь это, вариант ассемблерного кода, сгенерированный компилятором, скорее всего, будет работать быстрее, чем твой.
Кстати, если используешь GCC или Clang, активируй опции оптимизации для SSE, AVX и всего остального, чем богат твой процессор. Затем откинься на спинку кресла и удивись, когда компилятор векторизует твой сишный код. Причем сделает это так, как тебе и не снилось.
Какие программы нельзя написать на ассемблере?
Нет таких. Все, что можно сделать на компьютере, можно сделать в том числе и на ассемблере. Ассемблер — это текстовое представление сырого машинного кода, в который переводятся все программы, запущенные на компьютере.
Ты при желании можешь написать на ассемблере даже веб‑сайт. В девяностые С был вполне разумным выбором для этой цели. Используя такую вещь, как CGI BIN, веб‑сервер мог вызывать программу, написанную на С. Через stdin
сайт получал запрос, а через stdout
отправлял результат в браузер. Ты можешь легко реализовать тот же принцип на ассемблере.
Но зачем? Ты должен быть мазохистом, чтобы проделывать такое. Потому что когда ты пишешь на ассемблере, то сталкиваешься вот с такими проблемами.
- У тебя более низкая продуктивность, чем если бы ты работал на языке высокого уровня.
- У твоего кода нет никакой структуры, поэтому другим разработчикам будет трудно читать его.
- Тебе придется писать много букв. А там, где больше букв, больше потенциальных багов.
- С Secure Coding здесь все очень печально. На ассемблере писать так, чтобы код был безопасным, сложнее всего. На С в этом плане ты чувствуешь себя куда более комфортно.
Да, все можно написать на ассемблере. Но сегодня это нецелесообразно. Лучше пиши на С. Скорее всего, будет безопаснее, быстрее и более лаконично.
От редакции
Автор статьи — большой поклонник С и настоятельно рекомендует этот язык. Мы не будем лишать его такой возможности. С — отличная штука и помогает как освоить основные концепции программирования, так и прочувствовать принципы работы компьютера. Однако при выборе языка для изучения ты можешь руководствоваться самыми разными соображениями. Например:
- Надо учить Python или Lua, чтобы моментально получать результаты. Это мотивирует!
- Надо учить Scheme или Haskell из тех же соображений, что в школе учат алгебру, а не, к примеру, автомеханику.
- Надо учить Go для того же, для чего C, но в 2020 году.
- Надо учить JavaScript и React.js, чтобы как можно быстрее найти работу.
- Надо учить Java, чтобы максимизировать заработок.
- Надо учить Swift, потому что почему нет?
- Надо учить HolyC, чтобы славить Господа.
- Надо учить Perl во имя Сатаны.
И так далее. Ответ на вопрос о том, с какого языка начать, зависит от многих факторов, и выбор — дело индивидуальное.
Конечно, когда ты знаешь ассемблер, у тебя будут значительные преимущества перед теми программистами, которые его не знают. Но прежде чем ознакомиться с этими преимуществами, запомни одну простую вещь: хорошие программисты знают ассемблер, но почти никогда не пишут на нем.
Какие преимущества ассемблер дает программисту?
Чтобы писать эффективные программы (в плане быстродействия и экономии ресурсов), тебе обязательно надо знать ассемблер того железа, для которого ты пишешь. Когда ты знаешь ассемблер, ты не обманываешься внешней простотой и краткостью высокоуровневых функций, а понимаешь, во что в итоге превращается каждая из них: в пару‑тройку ассемблерных инструкций или в длиннющую их последовательность, переплетенную циклами.
Если работаешь с языками высокого уровня, такими как С, научись хотя бы читать и понимать ассемблерный код. Даже если ты в обозримом будущем не видишь себя пишущим на ассемблере (на самом деле мало кто себя так видит), знание ассемблера тебе пригодится.
Если будешь с ассемблером на ты, он сослужит тебе хорошую службу в отладке. Освоив ассемблер, ты будешь понимать, что происходит под капотом языков высокого уровня, как компьютер делает то, что он делает, и почему высокоуровневый компилятор иногда работает не так, как ты ждешь от него. Ты сможешь видеть причину этого и понимать, как ее устранить.
Плюс иногда ты ну никак не можешь понять, что у тебя за баг, пока не пройдешься в отладчике в пошаговом режиме по ассемблерному коду.
И вот еще тонкий намек: некоторые работодатели хотели бы видеть в твоем резюме слово «ассемблер». Это говорит им, что ты не просто по верхам нахватался, а действительно интересуешься программированием, копаешь вглубь.
Стоит ли начинать изучать программирование с ассемблера?
Когда ты осваиваешь программирование, начиная с самых низов, в этом есть свои плюсы. Но ассемблер — это не самый низ. Если хочешь начать снизу, начни с логических вентилей и цифровой электроники. Затем поковыряйся с машинным кодом. И только потом приступай к ассемблеру.
Время от времени тебя будут посещать мысли, что ты занимаешься какой‑то ерундой. Но ты узнаешь много полезного для своей будущей работы, даже если она будет связана только с языками высокого уровня. Ты узнаешь, как именно компьютер делает те вещи, которые он делает.
Однако я бы не советовал начинать с ассемблера и более низких слоев. Во всем том, что перечислено в двух предыдущих абзацах, легче разобраться, когда ты начинаешь с какого‑нибудь языка высокого уровня. Так ты достигнешь желаемого результата быстрее, чем оно тебе наскучит.
Но в какой‑то момент тебе и правда обязательно надо познакомиться с ассемблером, особенно если программируешь на С. Я сомневаюсь, что ты сможешь стать полноценным программистом на С, не зная ассемблера. Но начинать с ассемблера не стоит.
Насколько легче учить другие языки, когда уже знаешь ассемблер?
Ассемблер совершенно не похож на языки высокого уровня. Поэтому народная мудрость «Тот опыт, который ты получил на одном языке, может быть легко сконвертирован на другой язык» с ассемблером не работает.
Если ты начнешь с ассемблера, то после того, как выучишь его и решишь освоить новый язык, тебе придется начинать как с чистого листа. Помню, мой однокашник еще в школе выучил ассемблер, написал на нем игрушку, с которой победил на конференции. Но при этом так и не смог хорошо освоиться в С, когда мы учились в универе.
Чем же ассемблер отличается от языков высокого уровня? Переменные в нем — это просто области памяти. Здесь нет ни int
, ни char
. Здесь нет массивов!
Есть только память. Причем ты работаешь с ней не так, как на языке высокого уровня. Ты можешь забыть, что в какую‑то область памяти поместил строку, и обратиться к ней как к числу. Программа все равно скомпилируется. Но только обрушится в рантайме. Причем обрушится жестко, без вежливого сообщения об ошибке.
В ассемблере нет do..
, нет for..
, нет if..
. Вместо них там есть только операции сравнения и условного перехода. Строго говоря, там даже функций нет.
Но! Изучив ассемблер, ты будешь понимать, как реализуются и функции, и циклы, и все остальное. А разница между передачей параметра «по значению» и «по ссылке» станет для тебя самоочевидной. Плюс если ты пишешь на С, но не можешь до конца разобраться, как работают указатели, то, когда ты узнаешь, что такое регистры и относительная адресация, увидишь, что понять указатели совсем нетрудно.
Лучше начинай с С. На нем удобно осваивать основы: переменные, условия, циклы, логические построения и остальное. Опыт, который ты получишь при изучении С, легко сконвертировать на любой другой язык высокого уровня, будь то Java, Python или какой‑то еще. Да и с ассемблером легче разобраться, когда ты уже освоил С.
Насколько доходно уметь программировать на ассемблере?
Если заглянешь на HH.ru, то, скорее всего, не найдешь ни одной вакансии, у которой в заголовке написано слово «ассемблер». Но время от времени какая‑нибудь контора лихорадочно ищет мага‑волшебника, который знает нутро компьютера настолько глубоко, что может полностью подчинить операционную систему своей воле. Мага‑волшебника, который умеет (1) латать систему, не имея на руках исходного кода, (2) перехватывать потоки данных на лету и вмешиваться в них.
Некоторая часть этой глубокой магии — а сейчас потребность в такой магии становится все более редкой — может быть воплощена только на языке очень низкого уровня.
Я слышал о конторе, которая ищет человека на разработку новой платформы для высокочастотного трейдинга. Там идея в том, что если ты получаешь информацию о котировках быстрее своих конкурентов и принимаешь решение быстрее их, то будешь грести баснословные суммы.
«Когда ты получаешь котировки, проходя через весь стек TCP/IP, это слишком медленно», — говорят парни из этой фирмы. Поэтому у них есть примочка, которая перехватывает трафик на уровне Ethernet, прямо внутри сетевой карты, куда залита кастомизированная прошивка.
Но эти ребята пошли еще дальше. Они собираются разработать девайс для фильтрации трафика Ethernet — на ПЛИС. Зачем? Чтобы ловить котировки на аппаратном уровне и тем самым экономить драгоценные микросекунды трейдингового времени и в итоге получать небольшое, очень небольшое преимущество перед конкурентами. Язык С им не подошел. Им даже ассемблер не подошел. Так что эти парни выцарапывают программу прямо на кремнии!
Что такое язык Ассемблера
Эти уроки предназначены для тех, кто вообще не знаком с Ассемблером, или
имеет весьма отдаленное представление о нем. Конечно, если вы имеете опыт
программирования на других языках (Basic, C/C++, Pascal. ..), то это вам
очень поможет.
Но даже если вы хорошо знаете Ассемблер, то просмотр этого документа вам
не помешает, так как здесь вы можете изучить синтаксис Emu8086.
Подразумевается, что вы имеете некоторое представление о системах счисления
(HEX/BIN). Ну а если нет, то рекомендуем вам изучить раздел
Системы счисления
перед тем, как вы продолжите ознакомление с этим документом.
Язык Ассемблера — это язык программирования низкого уровня. Для начала вы
должны ознакомиться с общей структурой компьютера, чтобы в дальнейшем
понимать, о чем идет речь. Упрощенная модель компьютера:
System bus — системная шина (окрашена желтым цветом) соединяет
различные компоненты компьютера.
CPU — центральный процессор — это сердце компьютера. Большинство вычислений
происходит в CPU.
RAM — оперативная память (ОЗУ). В оперативную память загружаются
программы для выполнения.
РЕГИСТРЫ ОБЩЕГО НАЗНАЧЕНИЯ
Процессор 8086 имеет 8 регистров общего назначения, каждый регистр имеет имя:
- AX — регистр-аккумулятор (разделен на два регистра: AH и AL).
- BX — регистр базового адреса (разделяется на BH / BL).
- CX — регистр-счетчик (разделяется на CH / CL).
- DX — регистр данных (разделяется на DH / DL).
- SI — регистр — индекс источника.
- DI — регистр — индекс назначения.
- BP — указатель базы.
- SP — указатель стека.
Несмотря на имя регистра, программист сам определяет, для каких целей использовать
регистры общего назначения. Основное назначение регистра — хранение числа (переменной).
Разрядность вышеописанных регистров 16 бит, т.е., например, 0011000000111001b (в двоичной системе)
или 12345 в десятичной (человеческой) системе.
4 регистра общего назначения (AX, BX, CX, DX) разделены на две части.
К каждой части можно обращаться как к отдельному регистру. Например, если AX=0011000000111001b,
то AH=00110000b,
а AL=00111001b.
Старший байт обозначается буквой «H», а младший байт — буквой «L».
Поскольку регистры расположены внутри процессора, то работают они
значительно быстрее, чем память. Обращение к памяти требует использования
системной шины, а на это уходит больше времени. Обращение к регистрам
вообще не отнимает время. Поэтому вы должны стараться хранить переменные
в регистрах. Количество регистров очень небольшое и многие регистры
имеют специальное назначение, которое не позволяет использовать их для
хранения переменных, но все же они являются наилучшим местом для
записи временных данных и вычислений.
СЕГМЕНТНЫЕ РЕГИСТРЫ
- CS — указывает на сегмент, содержащий начальный адрес текущей программы.
- DS — обычно указывает на начальный адрес сегмента данных (переменных).
- ES — дополнительный сегментный регистр.
- SS — содержит начальный адрес сегмента стека.
Хотя в сегментных регистрах можно хранить любые данные, делать это
неразумно. Сегментные регистры имеют строго определенное назначение — обеспечение
доступа к блокам памяти.
Сегментные регистры работают совместно с регистрами общего назначения
для доступа к памяти. Например, если мы хотим получить доступ к памяти
с физическим адресом 12345h (в шестнадцатиричном исчислении),
мы должны установить DS = 1230h и SI = 0045h.
И это правильно, потому что таким образом мы можем получить доступ к памяти,
физический адрес которой больше, чем значение, которое может поместиться
в одиночном регистре.
Процессор вычисляет физический адрес, умножая значение сегментного регистра
на 10h и прибавляя к полученному результату значение регистра общего
назначения (1230h * 10h + 45h = 12345h):
Адрес, сформированный с помощью двух регистров, называется реальным адресом.
По умолчанию регистры BX, SI и DI работают с сегментным
регистром DS; регистры BP и SP работают с SS.
Другие регистры общего назначения не могут формировать реальный адрес!
Также, хотя BX может формировать реальный адрес, BH и BL не могут!
РЕГИСТРЫ СПЕЦИАЛЬНОГО НАЗНАЧЕНИЯ
- IP — командный указатель.
- Флаговый регистр — определяет текущее состояние процессора.
Регистр IP всегда работает совместно с сегментным регистром CS
и указывает на выполняемую в данный момент команду.
Флаговый регистр автоматически изменяется процессором после
математических операций. Он позволяет определять тип результата и передавать
управление другим участкам программы.
Вообще вы не можете напрямую обращаться к этим регистрам.
>>> Следующая часть >>>
Дневники чайника
Дневники чайника
— Так кто вы всё-таки будете?
— Асм есть Царь!
(Из кинофильма «Иван Васильевич меняет профессию»)
Благодарность
Я действительно благодарен всем моим читателям, особенно активным, вы мне очень помогли. Если бы не вы, этих уроков не было бы.
Также уроков могло не быть без Плохиша (Bad_guy, извини, что так назвал :). Он посадил зерно crackl@b’a на просторы инета и
ухаживал за ним все эти годы, пока проект превращался в дерево знаний. Спасибо zer0 за управление разделом статей.
Спасибо всем участникам нашего форума и «wasm.ru/forum» за помощь и науку, особенно: Leo, S_T_A_S_,Staier, The Svin.
Ну и, конечно, отдельное спасибо Седому (SeDoYHg или SeDoY) за огромную помощь в написании Чтивы 0 и за критику первых статей.
Я даже могу сказать, что почти все главы здесь под редакцией Седого.
Да, чуть не забыл, без моей мамы текст был бы полон «обшибак и слеганца бесграматен» :).
А без содействия папы вообще бы не стал заниматься Ассемблером
(в бизнес бы ударился, стал бы авторитетом, шлёпнули бы где-нибудь у входа в казино — и контрольный выстрел…
А так максимум, что светит, — это потёртые данные на винте и радикулит :).
Короче говоря, всем, кто помог, — спасибо.
Пустословие
Как был предусмотрителен Джордж Лукас, когда снял 4-й эпизод «Звёздных Войн».
Я понятия не имел, что возникнет потребность написать предчасть. А вот пришлось.
После того, как я написал «Чтиву III», прошло 4 месяца.
Дело в том, что первая часть начинается примерно c такой фразы: «Прочтите Рассылку Калашникова и возвращайтесь читать Дневники чайника».
Сам дочитал эту рассылку только до десятого урока, дальше идёт морально устаревшая информация.
Надеюсь, что большинство из тех, кто созрел для Асма, поймёт мой рассказ (от 9 до 110 лет :). Если не поймёте, не отчаивайтесь, есть другие дороги.
Давно существуют подобные курсы элементарного ликбеза, например:
- Уже упомянутая рассылка Олега Калашникова «Ассемблер? Это просто!» (устарела, зато сразу практика).
Кстати, эта же рассылка на всякий случай лежит и здесь, на Краклабе. - «Низкоуровневое программирование для дZенствующих».
Сейчас считаю, что это хорошая дорога для начинающих, но когда сам ничего не знал, эти статьи мне не понравились.
Решайте сами, подойдут ли они вам сразу.
На том же сайте вы найдёте море материала по теме. Искренне благодарен всем, кто трудится над этим ресурсом. - Советую в первую очередь обратить внимание на статьи Кибер Маньяка (CyberManiac)
из серии «Теоретические основы крэкинга» в разделе статей здесь на Краклабе или на Wasm’e в этом разделе.
В любом случае советую прочесть все известные уроки. В каждом источнике автор по-своему раскладывает тему. Есть много мнений о том, какие аспекты самые важные, и каждая точка зрения для новичка — золото.
Остальные интересные ссылки я уже поместил в следующих статьях, так что если вы пожелаете сначала завалиться литературой, а потом разгребать её, можете смело смотреть Чтиву 1,2,3.
Для кого пишу
Предполагается, что читатель не программист вообще, но опытный пользователь и у него есть желание стать настоящим хакером.
Совсм недавно не было никакого Битфрая, я вообще был далёк от программирования. Конечно, проводил много времени за компом и стал толковым юзверем, но я не знаю математики, даже на уровне школы.
Год назад я совсем не представлял, что такое написать программу.
Ещё хочу сказать, что не встречал ни одного человека, который разделил бы мою позицию:
самый лучший старт для программиста — это Ассемблер.
Хотя вру, такую точку зрения поддерживают некоторые уважаемые люди. Но явной мысли «начинать надо с Асма» нигде так и не увидил.
Других языков программирования не знаю, и от вас этого требовать не буду. Будет даже лучше, если вы ещё не испорчены такими вещами, как:
Print "Здесь был Вася"
В Ассемблере нет оператора «PRINT» и нет даже его подобия. Этот язык может показаться вам странным (как мне другие), если вы привыкли к логике высокоуровневых языков.
В данной статье за главный объект изучения будет принят язык Ассемблер для Intel-совместимых процессоров.
В принципе совершенно неважно, с чего начинать, когда объект полностью неизвестен, всё равно придётся ещё не раз возвращаться к первой выбранной теме.
Возможно, кто-то из вас сразу же предпочтёт прочитать большой учебник. Например:
В.И. Юров
«ASSEMBLER. 2-е издание. Учебник для вузов»
и учебник Зубкова в качестве интересных примеров для программирования (на форуме есть ссылки).
Не нужно искать в моей статье глубокие тайны программирования, и уж совсем не стоит считать Чтиву 0 истиной в последней инстанции.
Но если вы любите обрастать знаниями по ходу экспериментов (как Bitfry), добро пожаловать в мир ассемблера через мою «калитку».
Метод обучения
«Чтива 0» имеет мало общего со своими предками (Чтивы I,II,III), хотя бы потому, что это не мой дневник.
Скорее, «Чтива 0» будет Ваш дневник, Ваши ошибки и Ваши уроки ;).
Говорят, «умный учится, глупый учит»,
если к этой поговорке прибавить мой скромный багаж знаний — я совсем дурак :).
Только что начал и уже хочу научить вас думать логикой ассемблера. Ребячество — скажут многие.
Но если бы я не верил в успешность предприятия (при некотором усилии с вашей стороны), даже и не стал бы тратить время.
Вы, наверное, согласитесь, что все знания в этой жизни приходят витками.
Старые догадки и поступки кажутся ошибочными после каждого такого витка (в чтивах I,II,III полно ошибок).
Человеку для первого, невооружённого, осмотра местности, лучше думать, что земля плоская (поверьте, так будет лучше).
Затем он осваивает всё больше и больше, а в какой-то момент до него вдруг доходит:
чтобы сложить карты и сопоставить с положением звёзд на небе, нужно представить невероятное — земля, оказывается, шар.
Но и это не есть истина, на самом деле земля очень сложной формы,
и чтобы описать её более-менее точно, нужно использовать все ресурсы науки и техники.
Конца этому процессу не предвидится. То же самое можно сказать и о компьютере. Несмотря на то,
что он всего лишь юное творение человека, мы умудрились запутать в нём столько всяких абстракций (которые ему, кстати, мешают),
что Ассемблер можно уже воспринимать как насмешку над корнем этого слова.
Сделаю всё возможное, чтоб избежать сложных понятий, также обещаю не допускать тупостей вроде «земля круглая»,
так как это больше всего сбивает с толку, уж лучше думать, что она плоская, чем круглая :),
по крайней мере, я буду стараться так не писать.
Но вернёмся к виткам познаний.
В Чтиве 0 мы с вами постараемся смоделировать два таких витка (пока мне так кажется, может быть, их будет больше).
Нулевой виток будет содержать много практики и некоторое количество утверждений.
Первый будет состоять из ответов на главные вопросы, которые, надеюсь, у вас возникнут.
Но это не значит, что там не будет практических примеров, наоборот, все самые интересные фокусы прячутся во втором витке.
Таким образом, обе части нулевой чтивы будут иметь одинаковые темы глав.
Вступление в суть День первый Системы счисления и устройство памяти День второй Регистры процессора День третий Практикация всего мозга День четвёртый О словах и двойных словах (форматы данных) День пятый Циклы, ветвления и регистр Флагов День шестой Знакомство с Win32-программированием День седьмой Стек День восьмой Структурирование программы День девятый
Пару слов об оформлении
Статья получилась длинная и пёстрая, поэтому вам лучше сразу знать что как будет выглядеть.
Кроме основного текста, вы здесь встретите:
Выделения, как обычно — суть из массы
— Сноски в конце главы
Код программ
Код исходников программ
Действия примера |
Cравка о командах процессора |
Ну и в этих серых блоках будет развлекуха, её читать совсем необязательно, поэтому с неё и начнём :).
Эй, малыш! Да, ты… Можешь раздобыть некоторый скарб для моего корабля?…
Инструменты, которые нам пригодятся
…Ну, что ж, спасибо за помощь. Ты вроде здесь просто так околачиваешься, а у меня на борту как раз юнги не хватает…
Перед отправлением в дальний поход необходимо как следует проверить укомплектованность нашего космического корабля.
Поскольку миссия разведывательная, а корабль лёгкого класса, приспособления мы будем подбирать тщательно, чтобы сократить лишнй вес и расходы.
Всё наше снаряжение очень скромное по размеру, но могучее по возможностям.
Для начала посмотрите приложенные файлы: need.rar, prax0.rar, prax1.rar, общий размер ~500Kb. Там лежат примеры для проверки их работоспособности и кое-что ещё.
Hiew
Сайт программы, размер ~0,5Mb. Программа платная.
Версия должна быть для форточек не ниже 6.8 (я использую 7.01).
Если у вас нет этой программы, то в сети вы без проблем найдете её.
Heiw — это консольный шестнадцатиричный редактор с возможностью ассемблировать/дизассемблировать.
Незаменимая для исследователей и ассемблерщиков вещь.
FAR manager
Сайт программы, размер ~3Mb. Программа бесплатная для русскоязычных пользователей.
Подойдёт и новая x64-версия 2.0 и 32-битная. Короче – любая. Порекомендовал бы использовать именно FAR, так как он тоже консольный. Сам я пользуюсь двумя файловыми менеджерами: Total Commander и Far. По опыту могу сказать, что Far можно настроить по сочетанию клавиш один в один с TC, было бы желание. Внешний вид настраивается до мелочей, просто на это надо потратить некоторое время. Far будет приятным и удобным если вы этого захотите, поверьте. Меня, например, дико раздражают мелкие шрифты и кислотные краски стандартной консоли (что Hiew, что Far, что любая другая цветная консольная программа), однако, всегда можно создать ярлычок в котором будут настройки шрифтов и палитра приятная для глаза. Ярлык для Far’a с моими любимыми цветами я прикрепил в файл need.rar. Кроме того можно настроить цветовую схему. Hiew и Far имеют богатые возможности в этом плане. Пробуйте. Однако если вам совсем не нравятся консоли, можете использовать что-то типа TC или обычный проводник.
CodeView (CV)
Сайт программы: microsoft.com. В принципе программа доступна для бесплатного скачивания где-то в дебрях Майкрософта,
однако она является лишь придатком к довольно большому ненужному пакету, который входит в дополнение (не помню к чему).
Отыскать её там будет непросто. Я выложил эту довольно старую программу у себя (в том же архиве need.rar).
Ещё CV входит в старый MASM (v5x,v6x) который входит в VisualC++ (версии не знаю).
CodeView — программа-отладчик (по-ихнему debugger — исправлятель ошибок).
Отладчики помогают программистам понять, что делает их программа. 🙂 Когда этот светлый миг наступает, становится понятно, где ошибка.
Немалую часть времени написания программы программист проводит в отладчике, поэтому выбор дебагера — очень больной вопрос.
Я остановился на CodeView, потому что не смог подобрать другого отладчика для первых шести примеров.
Однако слишком погружаться в CV не стоит, так как он устарел и в реальной практике вряд ли вам пригодится.
OllyDbg
Сайт программы, размер ~1Mb. Программой можно пользоваться бесплатно с разрешения автора.
На 07.12.2011 последняя версия Oлли — 2.01 alpha 4, но можно использовать и старую стабильную 1.10.
А вот этот отладчик на сегодняшний день самый актуальный на платформах вплоть до Win7 x64 на уровне 32-битных приложений. OllyDbg — самый многофункциональный отладчик прикладных программ Win32. Но как только появится хороший подходящий для нас отладчик x64, сразу возьмусь переписывать уроки под него.
MASM32 SDK
Сайт программы, размер ~4Mb. Программа бесплатная.
Проект Стива Хатчисона (Steve Hutchesson). MASM32 – это современный пакет языка Ассемблер, собранный на основе компилятора MicroSoft.
Существует ещё пакет MASM (Macro Assembler) — это древний DOS’овый пакет от самой MS. Нам он не нужен, так же как и NASM, TASM, TASM32 и т.д.
На сегодняшний день единственной разумной альтернативой MASM32 является FASM. Сам я использую и FASM, и MASM32, но тему FASM’a затрагивать пока не будем.
Что такое «пакет языка Ассемблер»?
В стандартный пакет языка программирования входят:
- компилятор и линковщик (чтоб превращать исходные файлы в программу),
- документация (чтоб описать возможности пакета, собственные директивы, макросредства и т.д.),
- редактор исходных частей программы (как правило, вещь бесполезная, все пользуются любимыми текстовыми редакторами),
- различные дополнения и заготовки (чтоб облегчить рутинный труд),
- ну и, конечно, примеры.
Всё это нам понадобится не сразу, а постепенно, по мере необходимости. Поэтому не бросайтесь сейчас же изучать и осваивать все вышеперечисленные приборы.
Однако Hiew и CodeView нужны будут сразу же после вылета с базовой станции.
На Windows версии x64 (7/Vista/XP или Server) в первые дни вам понадобится какой-нибудь эмулятор DOS-режима для запуска com-программ. Можно использовать громоздкий Virtual PC от MS или VMWare, но я предлагаю (спасибо Григорию за подсказку) маленький удобный эмулятор:
DOSbox
Сайт программы, размер ~1,5Mb. Программа бесплатная.
Без этой программы можно обойтись на 32-битной WinXP. На Висте и Семёрке x86 лично не проверял, но говорят, можно обойтись режимом совместимости (пробуйте и отпишитесь в гостевой по результатам).
Не смущайтесь, что версия называется «Win32 installer», она поможет и на системе x86, и на x64 эмулировать режим старой-доброй DOS для наших первых примеров. DOSbox устанавливается за пару секунд, и его очень легко настроить. Нужно всего лишь смонтировать папку с com-примерами и туда же кинуть все файлы отладчика CV. Монтаж выполняется одной командой. Например:
mount с d:\prax
где «d:\prax » – это папка на реальном диске D, в которой должны быть свалены воедино ваши com-примеры и файлы отладчика CV. А «c» – это уже виртуальный диск внутри dosbox’a.
Далее переходим на новый виртуальный диск командой
с:
Что потом – читайте уже в следующей главе. Можно, кстати, батничек сделать… Разумеется, надо знать основы языка команд DOS и DOSbox (на сайте программы есть русская документация). Сразу рекомендую главу специально для пользователей, впервые очутившихся в DOS-мире.
Инструменты, которые нам НЕ пригодятся.
Молоток, кувалда, бензопила и другие приспособления, которые, возможно, вы захотите применить в первые дни полёта.
Адаптация к условиям невесомости проходит у многих крайне тяжело. Возможны потеря ориентации, головокружения и прочие побочные эффекты.
Уберите подальше от компьютера тяжёлые и твёрдые предметы — компьютер не виноват, это всего лишь машина.
Кажется, можно отправляться.
Ещё раз повторю, виток0 нужен только для того, чтоб у вас возникли вопросы, я вовсе не предполагаю, что вы поймёте всё и сразу.
Можно сравнить эту часть с детским мультиком — все бегают-прыгают, яркие картинки, сплошные перегибы и упрощения.
Bitfry
Ассемблер с нуля — просто о сложном языке программирования.
Просто о сложном.
Для начала уясним цели и задачи, которые будут рассматриваться в цикле статей в рамках рубрики «Ассемблер с нуля», определим потенциальную аудиторию.
«Ассемблер с нуля» заинтересует тех, кто желает научиться программировать на языке ассемблер, не будучи профессиональным математиком.
Информация излагается понятной для любого начинающего, не обладающего никакими (совершенно никакими) дополнительными знаниями выше уровня школьника седьмого — восьмого класса среднеобразовательной школы.
Дополнительная, но не менее важная цель — наработать общий подход к изучению любого языка программирования. Показать, насколько просто научиться программировать самостоятельно при наличии времени и желания.
Статьи заинтересуют преподавателей программирования с практической направленностью изложения материала.
Несомненную пользу в излагаемом материале найдут студенты, изучающие ассемблер — лишними знания не бывают, к тому же форма изложения материала проста и общедоступна.
Опытных гуру программирования может возмутить наш подход к форме подачи материала. Ох как любят программисты считать себя избранными, обладающими недоступными для других способностями. Ох как любят усложнять простые вещи, чтобы пустить пыль в глаза и набить себе цену! Призываю всех не становиться на тёмную сторону силы — знаниями нужно делиться, рассказывая просто о сложном и избегая усложнения простых вещей!
Ассемблер с нуля — практический подход.
Чтобы не показаться полными теоретиками, оторванными от практического применения знаний и умений, мы постараемся не отходить от конкретики, создавать и изучать конкретный код. Будут приводиться ссылки на литературу, позволяющую более глубоко проникнуть в конкретные языки, на примере которых мы стараемся изложить наш подход к программированию. При этом основы современного программирования будут играть роль своеобразного скелета, на который будут накладываться отдельные строки программного кода.
В качестве примеров будет рассмотрено написание конкретных простейших программ «хакерской» направленности, а также изучены основы крекинга (взлома программных защит), использования дизассемблированного кода в сторонних программах.
Заранее оговоримся, что информация будет излагаться в ознакомительных целях. Чтобы обеспечивать компьютерную безопасность, защищать свой код, предотвращать возможные риски утраты интеллектуальной собственности, необходимо знать потенциальные угрозы, а также способы их реализации.
Наш план действий.
Изучать ассемблер мы будем по следующему плану :
1. Суть программирования.
2. Понятие кода и данных на примере разработки простейших MS-DOS программы на Ассемблере с учётом возможностей простой, с точки зрения современности, операционной системы.
3. Программирование Windows приложений на ассемблере и Си.
4. Основы вирусологии — просто о сложном. Создание простейшего вируса и антивируса для Windows.
5. Основы крэкинга. Исследование программ.
6. Дизассемблирование — ассемблирование. Сложно ли «украсть» чужой код.
7. Применение ассемблера и Си для создания современных Windows приложений.
8. Итоги, выводы, применение полученных знаний и умений на практике.
Как вы видите, мы уделим внимание не только ассемблеру, но и языкам программирования Си и С++, как наиболее близким по сути и форме. Вы помните, одна из целей цикла статей — дать заинтересованному читателю основы современного программирования, которые позволят изучить любой язык с нуля за достаточно сжатые сроки.
Архивы Ассемблер с нуля — Ассемблерный код
Прощай ассемблер MS-DOS и здравствуй Windows!
Мы закончили изучать 16 битный ассемблер MS-DOS и приступаем к изучению программирования на 32 битном ассемблере для Windows.
Нужно ли было копаться в коде мёртвой операционной системы, вместо того, чтобы сразу перейти к основам современного программирования? Для последующего успеха в изучении программирования — это необходимо. Практическое применение знаниям 16 битного ассемблера вы вряд ли найдёте в наше время. Пройденный нами этап — это основа теоретических знаний и практического понимания сути программирования через его основополагающее начало. Подробнее «MS-DOS и TASM 2.0. Часть 19. Прощай ассемблер MS-DOS!»
Указатель в программировании.
В статье MS-DOS и TASM 2.0. Часть 9. Указатель просто и понятно было рассмотрено, что такое указатель в программировании (pointer). Сейчас мы перейдём к вопросу практического использования указателя. Ещё раз напомним, что указатель в ассемблере — более широкое понятие, чем в Си и С++, где указатель определён как переменная, значением которой является адрес ячейки памяти. Указатель — не только переменная. Указатель в программировании на ассемблере — адрес определённой ячейки памяти. Жёсткой привязки к понятию «переменной» нет.
Преимущество указателя — простая возможность обращаться к определённой части исполняемого кода либо данных, избегая их дублирования. Например, один раз написав код функции, мы можем обращаться к нему неоднократно, осуществляя вызов указанной функции. Кстати, вызов функции — это переход исполнения кода по указателю, который для удобства «обозвали» понятным для человека названием (ну, например, «MyBestFunc»). Подробнее «MS-DOS и TASM 2.0. Часть 18. Ещё раз об указателе.»
Организация данных в ассемблере.
Прежде, чем переходить к рассмотрению вопроса что такое константа, массив, структура в ассемблере, поговорим о понятии абстракции.
Для упрощения написания кода необходимо преобразовать его в понятный для человека вид, желательно не в ущерб для машины. Для этого используют условности и обобщения — определённую степень абстракции. Один из простейших способов абстракции — разбивка кода и данных на части — блоки по определённым правилам и с определёнными особенностями. Затем эти блоки обзывают понятным для человека языком. Подробнее «MS-DOS и TASM 2.0. Часть 17. Константы, массивы, структуры и т.д.»
Ядро операционной системы — набор системных функций.
Основу операционной системы Windows 95 — Windows XP составляет набор системных функций, содержащихся в файлах с расширением *.DLL, которые располагаются в системных дирректориях … Windows\System, System32, SysWOW64 (для 64 битных версий операционок) — так называемый Win API. К слову, в Windows 10 поддержка Win API реализована практически в полном объёме, хотя ядро системы несколько изменилось). В MS-DOS ядро также состоит из системных функций, которые называются прерывания DOS. Ну, если точно, то есть прерывания DOS, а есть прерывания BIOS (связаны с управлением компьютерным железом, определённые прерывания DOS можно реализовать через прерывания BIOS), да и понятие ядра системы можно расширить… Для наших целей и на данный момент отбросим усложнения в сторону! Далее мы будем использовать общее понятие для всех прерываний: прерывания DOS. Подробнее «MS-DOS и TASM 2.0. Часть 16. Прерывания DOS.»
Макрос — макрокоманда, макроопределение.
У большинства популярных ассемблеров (TASM, MASM, FASM), имеется определённая «вкусность», которая помогает писать более читабельный и понятный код, а также уменьшает вероятность ошибок. Мы имеем ввиду макросы. Макрос — миникод, который определяет алгоритм действий основных команд ассемблера. Этот код либо уже создан и входит в комплект ассемблера, либо пишется пользователем самостоятельно. В данной статье мы выясним, как использовать макрос функции (процедуры), встроенный в TASM. Подробнее «MS-DOS и TASM 2.0. Часть 15. Упрощаем вызов функции в TASM.»
Параметры функции.
Функции в ассемблере — это часть кода, которая решает конкретную задачу или несколько, объединённых одной целью задач. Функция может вызываться без дополнительного дублирования кода. Человек способен помнить, воспринимать и использовать ограниченное число информации. Для облегчения понимания и создания кода его структурируют — дробят на определенные части. Подробнее «MS-DOS и TASM 2.0. Часть 14. Конвенции вызова функции.»
Стек в ассемблере.
Работа процедур тесно связана со стеком. Стеком называется область программы для временного хранения данных. Стек в ассемблере работает по правилу «Первым зашёл — последним вышел, последним зашёл — первым вышел». В любой период времени в стеке доступен только первый элемент, то есть элемент, загруженный в стек последним. Выгрузка из стека верхнего элемента делает доступным следующий элемент. Это напоминает ящик, в который поочерёдно ложатся книги. Чтобы получить доступ к книге, которую положили первой, необходимо достать поочерёдно все книги, лежащие сверху. Подробнее «MS-DOS и TASM 2.0. Часть 13. Стек.»
Процедуры в ассемблере.
Процедуры в ассемблере будут рассмотрены в четырёх статьях, в которых мы изучим общие понятия и определения процедур, использование стека для передачи параметров, а также использование прерываний DOS — как разновидности функций ядра операционки (статьи 15-19: «Процедуры (функции)», «Стек», «Конвенции вызова функции», «Упрощаем вызов функции в TASM», «Прерывания DOS»).
Подробнее «MS-DOS и TASM 2.0. Часть 12. Процедуры (функции).»
Отладчик ассемблера Turbo Debugger.
Применим усвоенные понятия на практике — прогоним нашу крохотную программу prg.com через отладчик ассемблера Turbo Debugger (TD). Именноо TD мы будем использовать в изучении 16 битного ассемблера. Для 32 и 64 битного программирования имеется свое програмное обеспечение. Вместе с тем, для своих целей Turbo Debugger очень хорош. Работать с программой просто и понятно — ничего лишнего — то, что нужно для начинающих.
Подробнее «MS-DOS и TASM 2.0. Часть 11. Turbo Debugger.»
Команды ассемблера и команды процессора.
Стоит пояснить, что если к вопросу подойти формально строго, то команды процессора и команды ассемблера — это не одно и то же. Ассеммблер — хоть и низкоуровневый язык программирования, но иногда он без спроса программиста «корректирует код под себя». Причём у каждого ассемблера (masm, tasm, fasm) это может быть по-разному. Самый яркий пример — команда ret. В ассемблерном коде мы запишем ret, а реальный ассемблер ассемблирует её как retf или retn 8. Может также изменяться код, добавлением в качестве выравнивания кода команды процессора nop (об этом ниже в статье) и т.п. Чтобы не усложнять суть вопроса, под понятиями команды процессора и команды ассемблера мы будем подразумевать одно и то же.
Подробнее «MS-DOS и TASM 2.0. Часть 10. Команды ассемблера.»
НОУ ИНТУИТ | Лекция | Ассемблер
Аннотация: Рассматривается парадигма низкоуровневого программирования на ассемблере. Эта парадигма нацелена на учет основных особенностей компьютерных архитектур.
Описаны основные методы адресации памяти. Дано определение языково-ориентированной абстрактной машины. Изучается понятие абстрактной машины (secd) для определения операционной семантики языка программирования по Венской методике
Низкоуровневое программирование успешно при детальном знакомстве с архитектурой компьютера, что в конечном счете приводит к ее пониманию. Принципы и способы программирования в общем не зависят от языка. Главным требованием является умение мыслить логически.
Ассемблер отличается от компилятора меньшей сложностью исходного языка, перевод с которого в машинный язык можно выполнить «один-в-один». Ассемблер часто сопровождается возможностью дизассемблирования, что отличает его от большинства других языков программирования. Изучить язык ассемблера проще, чем любой язык высокого уровня. Знание ассемблера помогает понимать код программы, подготовленной на других языках.
Архитектура компьютера часто определяется как множество ресурсов, доступных пользователю. Это система команд, общие регистры, слово состояния процессора и адресное пространство. Процесс перевода программы с языка ассемблера в язык машинных команд называют ассемблированием.
Процесс ассемблирования заключается в следующим:
- Резервирование памяти для последовательности команд, образующих ассемблируемую программу.
- Сопоставление используемых идентификаторов с адресами в памяти.
- Отображение ассемблерных команд и идентификаторов в их машинные эквиваленты.
Для реализации такого процесса требуется счетчик адресов и таблица идентификаторов.
Программист не знает абсолютных адресов ячеек памяти, занятых для хранения констант, команд и промежуточных результатов вычислений, но обычно предполагается, что последовательно написанные команды будут расположены в последовательных ячейках памяти.
Кроме символических представлений команд ассемблерная программа содержит описания распределяемой памяти и директивы управления ассемблированием. Обычно выделена точка входа в программу из операционной системы.
Программирование на ассемблере подразумевает знание специфики системы команд процессора, методов обслуживания устройств и обработки прерываний. Система команд может быть расширена микропрограммами и системными вызовами в зависимости от комплектации оборудования и операционной системы. Это влияет на решения по адресации памяти и коммутации комплекта доступных устройств. Но есть и достаточно общие соглашения о представлении и реализации средств обработки информации на уровне машинного кода [
[
1
]
,
[
20
]
,
[
36
]
,
[
55
]
,
[
56
]
,
[
71
]
,
[
72
]
].
Структура кода программы и его свойства:
- Перемещаемость. Удобно, чтобы код программы был устроен так, что его можно расположить по любому абсолютному адресу.
- Листание страниц памяти. Соотношение между адресуемой и реально доступной памятью может требовать пересмотра в процессе выполнения программы.
- Зависимость от данных. Программа должна учитывать готовность и обновление данных, особенно в случае обмена информацией через порты или буферы устройств.
- Динамика размещения. Программа может размещаться в памяти пошаговым образом, методом раскрутки, с использованием динамической оптимизации, учитывающей статистику реального использования ее составляющих.
Обычно независимо от системы команд ассемблер обеспечивает средства управления распределением памяти и управления компиляцией кода, что позволяет программисту принимать точные решения на уровне машинного языка. Имеются средства отладочного исполнения и распечатки листингов. При необходимости уровень языка может быть повышен с помощью макросов.
Язык ассемблера оперирует такими данными как адреса и значения. Нередко для наглядности в записи операндов команд вводится внешнее различие @адресов и #значений с помощью префиксных символов. Возможны специальные формы записи для блоков данных и литералов.
При записи команд на ассемблере принято структурировать строки на поля, предназначенные для последовательного размещения метки, кода команды, операндов и комментария. Наибольшее разнообразие возможных решений связано с формами адресации операндов на уровне машинного языка, о которых будет речь далее.
Число слов, отводимое ассемблером под одну символическую команду, зависит не только от собственно кода команды, но и от метода адресации операндов, а возможно и от других аспектов кодирования программ и данных, обсуждение которых здесь не предусмотрено. Достаточно констатировать, что программа при ассемблировании распадается на конечные последовательности команд K1 … Kn, которым сопоставляются конечные интервалы машинных слов W1 … Wm(a) в зависимости от а — системы аспектов кодирования.
[K1 ... Kn] -> [W1 ... Wm(a)]
Фактически операндная часть команды — это адреса, специальные регистры, сумматоры, значения в общей памяти, шкала прерываний и состояний или что-нибудь другое, специфичное для конкретной архитектуры.
В зависимости от команды используются разные методы адресации операндов:
- неявная — команда сама «знает», где и что она обрабатывает, где берет данные и куда разместит результат;
- непосредственная — операнд расположен непосредственно в команде;
- прямые адреса — код адреса размещен в поле операнда;
- индексируемые адреса — один из операндов используется как индекс при вычислении адреса других операндов;
- базируемых (по регистру) — указан базовый регистр для пересчета адресов операндов;
- относительные (по текущей позиции) — адресация учитывает адрес размещения команды;
- косвенные (через промежуточное слово) — операнд указывает на слово, хранящее адрес значения;
- модифициуемые (по значению-регистру) — один операнд указывает на слово, хранящее значение, модифицирующее адрес другого операнда;
- стек — операнд, доступ к которому подчинен дисциплине стека — «первый пришел — последний ушел».
Учебные пособия по программированию на языке ассемблера
Mips
Учебники по MIPS ЗАПОЛНИТЕ СОДЕРЖАНИЕ
# | ТЕМА | Введение |
---|---|---|
1 | Набор инструкций MIPS | Этот раздел включает таблицы и детали кодов операций, используемых в сборке кодов операций, используемых в операциях. |
2 | Синтаксис MIPS | Изучите основной синтаксис программы MIPS.Как структурировать программу MIPS. |
3 | Какие комментарии используются в MIPS и почему они используются, также узнайте их преимущества. | |
4 | Типы данных MIPS | Полный список типов данных, используемых в сборке MIPS, также узнайте об их использовании в различных ситуациях. |
5 | Регистры MIPS | В MIPS ISA используется множество регистров.Каждый из них имеет собственное применение. Различайте типы регистров. |
6 | Форматы набора команд MIPS | MIPS использует разные форматы команд для отдельных типов команд. В основном их три на широком уровне. |
7 | MIPS Syscall Services | Изучите использование инструкции SYSCALL в программе. Это очень простая инструкция, используемая для служб, необходимых для ОС. |
8 | Печать и чтение целого числа | Узнайте, как читать и печатать целое число в MIPS на базовом уровне с подробными примерами. |
9 | Добавление MIPS | Очень простая арифметическая операция в программировании. Узнайте, как складывать числа в MIPS. |
10 | Вычитание MIPS | Аналогично сложению, изучите использование кода операции SUB. |
11 | Умножение MIPS | Узнайте, как умножать числа в MIPS с подробными объяснениями. |
12 | Циклы MIPS | Введение и объяснение циклов на ассемблере с примерами. |
| ||||||
441K |
|
02 | |||||
|
34K | ||
Язык ассемблера | 30 ноября Митко Мутаров |
20K |
|
66K |
|
20K |
|
193K |
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Языковые переводчики и языки программирования высокого уровня | Примечания, видео, контроль качества и тесты | 11 класс> Информатика> Концепции и логика программированияПереводчики языков и языки программирования высокого уровняПереводчик языков:Введение:Рис.Переводчик Переводчик языка — это программа, которая используется для перевода инструкций, написанных в исходном коде, в объектный код, то есть с языка высокого уровня или языка ассемблера на машинный язык. Есть 3 типа языковых переводчиков. Это:
Рис. Ассемблер
Рис. Компилятор
Различия между компилятором и интерпретатором:
Список языков программирования высокого уровня:
Источник: www.ptpartners.co.uk
Рис. Программирование на COBOL
Фиг.Логотип C Источник: cplus.beamed.com
Источник: airweb.cse.lehigh.edu
Рис. Программирование LISP
Soruce: www.quora.com
Fig. Net Logo Источник: www.khanalsab.com.np
PERL: PERL — один из 1 st языков сценариев в системе UNIX для веб-разработки.PERL (Practical Extraction and Reporting Language) — это язык сценариев с открытым исходным кодом, который можно найти на сервере на базе UNIX / Linux. PERL также поддерживается Windows Server. (Koirala & Shrestha, 2015) Fig. Perl Programming Библиография Bhusal, R., Khanal, R., & Manandhar С. (2013). Computer Essentials I. Putalisadak, Kathmandu: Publication Asmita. Коирала Х. и Шреста Р. К. (2015). Компьютерные науки I. Анамнагар, Катманду: публикация Будды. Приключений на языке ассемблера: Полный курс
Microsoft Marketing 06 Rasp | 06 Rasp React Native | Microsoft Marketing 06 Rasp | 06 Rasp React Native | Все курсы • Учебники по языку ассемблера 12 октября 2019 г. 3972 просмотров Язык ассемблераЯзык ассемблера Motorola MC6800 Ассемблер — это язык программирования низкого уровня для компьютеров, микропроцессоров, микроконтроллеров и других программируемых устройств. Он реализует символическое представление машинных кодов и других констант, необходимых для программирования данной архитектуры ЦП. Это представление обычно определяется производителем оборудования и основано на мнемонике, которая символизирует этапы обработки (инструкции), регистры процессора, ячейки памяти и другие языковые особенности.Таким образом, язык ассемблера специфичен для определенной физической (или виртуальной) компьютерной архитектуры. Это контрастирует с большинством языков программирования высокого уровня, которые в идеале являются переносимыми. Служебная программа, называемая ассемблером , используется для перевода операторов языка ассемблера в машинный код целевого компьютера. Ассемблер выполняет более или менее изоморфный перевод (отображение один-к-одному) из мнемонических операторов в машинные инструкции и данные. Это контрастирует с языками высокого уровня, в которых один оператор обычно приводит к множеству машинных инструкций. Многие продвинутые ассемблеры предлагают дополнительные механизмы для облегчения разработки программ, управления процессом сборки и помощи при отладке. В частности, большинство современных ассемблеров включают макро-средства (описанные ниже) и называются макросборщиками . Ключевые концепцииЗачем нужен ассемблер? Простой ассемблер преобразует каждый оператор ассемблера в соответствующий оператор машинного языка, поэтому на первый взгляд кажется незначительным удобством, заменяя непонятные машинные инструкции легко запоминающимися именами.Однако рассмотрим программу на машинном языке, загруженную в память из ячейки 0, которая имеет инструкцию, эквивалентную машинному коду АссемблерОбычно современный ассемблер создает объектный код, переводя мнемонику инструкций сборки в коды операций и разрешая символические имена для ячеек памяти и других объектов. [1] Использование символьных ссылок — ключевая особенность ассемблеров, позволяющая избежать утомительных вычислений и обновлений адресов вручную после модификации программы. Большинство ассемблеров также включают макросы для выполнения текстовой подстановки — например, для генерации общих коротких последовательностей инструкций как встроенных вместо , называемых подпрограммами . Ассемблеры, как правило, проще писать, чем компиляторы для языков высокого уровня, [ требуется ссылка ] и доступны с 1950-х годов.Современные ассемблеры, особенно для архитектур RISC, таких как SPARC или POWER, а также x86 и x86-64, оптимизируют планирование выполнения инструкций для более эффективного использования конвейера процессора. [ необходима ссылка ] Количество проходовСуществует два типа ассемблеров в зависимости от того, сколько проходов через исходный код необходимо для создания исполняемой программы. Первоначальной причиной использования однопроходных сборщиков была скорость сборки; однако современные компьютеры выполняют двухпроходную сборку без недопустимой задержки. Преимущество двухпроходного ассемблера заключается в том, что отсутствие необходимости в исправлении ошибок делает компоновщик (или загрузчик, если ассемблер напрямую создает исполняемый код) проще и быстрее. [2] Монтажники высокого уровняБолее сложные ассемблеры высокого уровня предоставляют языковые абстракции, такие как: Дополнительные сведения см. В разделе «Языковой дизайн» ниже. Использование терминаОбратите внимание, что в обычном профессиональном использовании термин ассемблер используется для обозначения как языка ассемблера, так и программного обеспечения, которое собирает программу на языке ассемблера. Таким образом: «CP / CMS был написан на ассемблере S / 360», а также «ASM-H был широко используемым ассемблером S / 370». [ необходима ссылка ] АссемблерПрограмма, написанная на языке ассемблера, состоит из серии (мнемонических) инструкций процессора и мета-операторов (известных также как директивы, псевдо-инструкции и псевдооперации), комментариев и данных.Инструкции на языке ассемблера обычно состоят из мнемоники кода операции, за которой следует список данных, аргументов или параметров, разделенных запятыми. [4] Ассемблер переводит их в поток исполняемых инструкций, которые могут быть загружены в память и выполнены. Ассемблеры также могут использоваться для создания блоков данных из отформатированного и прокомментированного исходного кода, которые будут использоваться другим кодом. Возьмем, к примеру, инструкцию, которая сообщает процессору x86 / IA-32 немедленно переместить 8-битное значение в регистр.Двоичный код этой инструкции — 10110, за которым следует 3-битный идентификатор регистра, который следует использовать. Идентификатор регистра AL — 000, поэтому следующий машинный код загружает регистр AL данными 01100001. [5] 10110000 01100001 Этот двоичный компьютерный код можно сделать более удобочитаемым, выразив его в шестнадцатеричном виде следующим образом B0 61 Здесь MOV AL, 61ч; Загрузить AL с 97 десятичным (61 шестнадцатеричным) Когда-то многие мнемоники языка ассемблера представляли собой трехбуквенные сокращения, такие как JMP для jump , INC для приращения и т. Д.Современные процессоры имеют гораздо больший набор инструкций, и многие мнемоники стали длиннее, например FPATAN для « частичный арктангенс с плавающей запятой » и BOUND для « проверить индекс массива на соответствие границам ». Тот же мнемонический MOV относится к семейству связанных кодов операций, связанных с загрузкой, копированием и перемещением данных, будь то непосредственные значения, значения в регистрах или ячейки памяти, на которые указывают значения в регистрах. Код операции 10110000 ( MOV AL, 1ч; Загрузить AL с немедленным значением 1 MOV CL, 2ч; Загрузить CL немедленным значением 2 MOV DL, 3ч; Загрузить DL немедленным значением 3 Синтаксис MOV также может быть более сложным, как показывают следующие примеры. [6] MOV EAX, [EBX]; Переместите 4 байта памяти по адресу, содержащемуся в EBX, в EAX MOV [ESI + EAX], CL; Переместить содержимое CL в байт по адресу ESI + EAX В каждом случае мнемоника MOV транслируется ассемблером непосредственно в код операции в диапазонах 88-8E, A0-A3, B0-B8, C6 или C7, и программисту не нужно знать или запоминать какой. [5] Преобразование языка ассемблера в машинный код — это работа ассемблера, а обратное, по крайней мере частично, может быть достигнуто с помощью дизассемблера. В отличие от языков высокого уровня, между простыми операторами ассемблера и инструкциями машинного языка обычно существует взаимно однозначное соответствие. Однако в некоторых случаях ассемблер может предоставить псевдоинструкций (по сути, макросы), которые расширяются до нескольких команд машинного языка для обеспечения обычно необходимых функций.Например, для машины, в которой отсутствует команда «переходить, если больше или равно», ассемблер может предоставить псевдоинструкцию, которая расширяется до «установить, если меньше, чем» и «перейти, если будет ноль (по результату установки инструкции)» . Большинство полнофункциональных ассемблеров также предоставляют богатый макроязык (обсуждается ниже), который используется поставщиками и программистами для генерации более сложного кода и последовательностей данных. Каждая архитектура компьютера и архитектура процессора обычно имеют собственный машинный язык.На этом уровне каждая инструкция достаточно проста для выполнения с использованием относительно небольшого количества электронных схем. Компьютеры различаются количеством и типом поддерживаемых ими операций. Например, машина с 64-битной длиной слова будет иметь схему, отличную от 32-битной машины. Они также могут иметь разные размеры и количество регистров, а также разные представления типов данных в хранилище. Хотя большинство компьютеров общего назначения могут выполнять в основном одни и те же функции, способы их выполнения различаются; соответствующие языки ассемблера могут отражать эти различия. Для одного набора инструкций может существовать несколько наборов мнемоник или синтаксиса языка ассемблера, как правило, экземпляры которых создаются в разных программах на ассемблере. В этих случаях наиболее популярным обычно является тот, который поставляется производителем и используется в его документации. Языковой дизайнОсновные элементыСуществует большая степень разнообразия в том, как авторы ассемблеров категоризируют утверждения, и в используемой ими номенклатуре. В частности, некоторые описывают что-либо, кроме машинной мнемоники или расширенной мнемоники, как псевдооперацию (псевдооперацию).Типичный язык ассемблера состоит из 3 типов инструкций, которые используются для определения программных операций: Мнемоника кода операции и расширенная мнемоникаИнструкции (инструкции) на языке ассемблера, как правило, очень просты, в отличие от инструкций на языке высокого уровня. Как правило, мнемоника — это символическое имя для одной исполняемой инструкции на машинном языке (код операции), и для каждой инструкции на машинном языке определена по крайней мере одна мнемоника кода операции.Каждая инструкция обычно состоит из операции , кода операции или , плюс ноль или более операндов . Большинство инструкций относятся к одному значению или паре значений. Операнды могут быть немедленными (обычно однобайтовыми значениями, закодированными в самой инструкции), регистрами, указанными в инструкции, подразумеваемыми или адресами данных, расположенными в другом месте в хранилище. Это определяется базовой архитектурой процессора: ассемблер просто отражает, как эта архитектура работает. Расширенная мнемоника часто используется для указания комбинации кода операции с конкретным операндом, например, ассемблеры System / 360 используют B в качестве расширенной мнемоники для BC с маской 15 и NOP для до нашей эры. с маской 0. Расширенная мнемоника часто используется для поддержки специального использования инструкций, часто для целей, не очевидных из названия инструкции. Например, многие процессоры не имеют явной инструкции NOP, но имеют инструкции, которые можно использовать для этой цели.В процессорах 8086 инструкция xchg ax, ax используется для nop , при этом nop является псевдо-кодом операции для кодирования инструкции xchg ax, ax . Некоторые дизассемблеры распознают это и декодируют инструкцию xchg ax, ax как nop . Точно так же ассемблеры IBM для System / 360 и System / 370 используют расширенную мнемонику NOP и NOPR для BC и BCR с нулевыми масками. Некоторые ассемблеры также поддерживают простые встроенные макрокоманды, которые генерируют две или более машинных инструкции.Например, с некоторыми ассемблерами Z80 команда ld hl, bc распознается для генерации ld l, c , за которой следует ld h, b . [7] Иногда их называют псевдоопкодами . Разделы данныхСуществуют инструкции, используемые для определения элементов данных для хранения данных и переменных. Они определяют тип данных, длину и выравнивание данных. Эти инструкции также могут определять, будут ли данные доступны для внешних программ (программ, собранных отдельно) или только для программы, в которой определен раздел данных.Некоторые ассемблеры классифицируют их как псевдооперации. Директивы по монтажуДирективы ассемблера, также называемые псевдо-кодами операций, псевдооперациями или псевдооперациями, представляют собой инструкции, которые выполняются ассемблером во время сборки, а не процессором во время выполнения. Они могут сделать сборку программы зависимой от параметров, вводимых программистом, так что одна программа может быть собрана разными способами, возможно, для разных приложений. Их также можно использовать для управления представлением программы, чтобы ее было легче читать и поддерживать. (Например, директивы могут использоваться для резервирования областей памяти и, необязательно, их начального содержимого.) Имена директив часто начинаются с точки, чтобы отличать их от машинных инструкций. Символьные ассемблеры позволяют программистам связывать произвольные имена ( метки, или символа ) с ячейками памяти. Обычно каждой константе и переменной присваивается имя, чтобы инструкции могли ссылаться на эти местоположения по имени, тем самым продвигая самодокументированный код.В исполняемом коде имя каждой подпрограммы связано с ее точкой входа, поэтому любые вызовы подпрограммы могут использовать ее имя. Внутри подпрограмм адресатам GOTO присваиваются метки. Некоторые ассемблеры поддерживают локальных символа , которые лексически отличаются от обычных символов (например, использование «10 $» в качестве пункта назначения GOTO). Некоторые [ какие? ] Ассемблеры обеспечивают гибкое управление символами, позволяя программистам управлять различными пространствами имен, автоматически вычислять смещения в структурах данных и назначать метки, которые относятся к буквальным значениям или результатам простых вычислений, выполненных ассемблером.Метки также могут использоваться для инициализации констант и переменных с перемещаемыми адресами. Языки ассемблера, как и большинство других компьютерных языков, позволяют добавлять комментарии к исходному коду ассемблера, игнорируемые ассемблером. Хорошее использование комментариев даже более важно для ассемблерного кода, чем для языков более высокого уровня, поскольку смысл и цель последовательности инструкций труднее расшифровать из самого кода. Разумное использование этих возможностей может значительно упростить проблемы кодирования и поддержки низкоуровневого кода. Необработанный исходный код сборки , сгенерированный компиляторами или дизассемблерами — код без каких-либо комментариев, значимых символов или определений данных — довольно трудно читать, когда необходимо внести изменения. МакросыМногие ассемблеры поддерживают предопределенных макросов , а другие поддерживают определяемых программистом (и многократно повторно определяемых) макросов, включающих последовательности текстовых строк, в которые встроены переменные и константы. Эта последовательность текстовых строк может включать коды операций или директивы.После определения макроса его имя может использоваться вместо мнемоники. Когда ассемблер обрабатывает такой оператор, он заменяет его текстовыми строками, связанными с этим макросом, а затем обрабатывает их, как если бы они существовали в файле исходного кода (включая, в некоторых ассемблерах, раскрытие любых макросов, существующих в тексте замены) . Поскольку макросы могут иметь «короткие» имена, но расширяться до нескольких или даже многих строк кода, их можно использовать для того, чтобы программы на языке ассемблера казались намного короче, требуя меньшего количества строк исходного кода, как в языках более высокого уровня.Их также можно использовать для добавления более высоких уровней структуры к программам сборки, опционально для введения встроенного кода отладки с помощью параметров и других аналогичных функций. Многие ассемблеры имеют встроенные (или предопределенные ) макросы для системных вызовов и других специальных кодовых последовательностей, таких как генерация и хранение данных, реализованных с помощью расширенных побитовых и логических операций, используемых в играх, безопасности программного обеспечения, управлении данными и криптографии. . Макроассемблеры часто позволяют макросам принимать параметры.Некоторые ассемблеры включают в себя довольно сложные макроязыки, включающие такие элементы языка высокого уровня, как необязательные параметры, символьные переменные, условные выражения, манипуляции со строками и арифметические операции, которые можно использовать во время выполнения данного макроса и позволяющие макросам сохранять контекст или обмениваться информацией. . Таким образом, макрос может генерировать большое количество инструкций на языке ассемблера или определений данных на основе аргументов макроса. Это может быть использовано, например, для генерации структур данных в стиле записи или «развернутых» циклов, или может генерировать целые алгоритмы на основе сложных параметров.Организация, использующая язык ассемблера, который был сильно расширен с помощью такого набора макросов, может считаться работающей на языке более высокого уровня, поскольку такие программисты не работают с концептуальными элементами нижнего уровня компьютера. Макросы использовались для настройки крупномасштабных программных систем для конкретных клиентов в эпоху мэйнфреймов, а также использовались персоналом клиентов для удовлетворения потребностей своих работодателей путем создания конкретных версий операционных систем производителя.Это было сделано, например, системными программистами, работающими с IBM Conversational Monitor System / Virtual Machine (CMS / VM) и с надстройками IBM для «обработки транзакций в реальном времени», CICS, Customer Information Control System и ACP / TPF, Авиакомпания / финансовая система, начавшаяся в 1970-х годах и до сих пор использующая многие крупные компьютерные системы бронирования (CRS) и системы кредитных карт. Также было возможно использовать исключительно возможности обработки макросов ассемблера для генерации кода, написанного на совершенно разных языках, например, для генерации версии программы на COBOL с использованием программы чистого макроса ассемблера, содержащей строки кода COBOL во время сборки. операторы, указывающие ассемблеру генерировать произвольный код. Это произошло потому, что, как было реализовано в 1960-х годах, концепция «обработки макросов» не зависит от концепции «сборки», первая из которых в современных терминах представляет собой больше текстовую обработку, обработку текста, чем создание объектного кода. Концепция обработки макросов появилась и появляется в языке программирования C, который поддерживает «инструкции препроцессора» для установки переменных и выполнения условных тестов на их значениях. Обратите внимание, что в отличие от некоторых предыдущих макропроцессоров внутри ассемблеров, препроцессор C не был завершенным по Тьюрингу, потому что ему не хватало возможности либо зацикливаться, либо «переходить к», что позволяет программам зацикливаться. Несмотря на мощь обработки макросов, он вышел из употребления во многих языках высокого уровня (основными исключениями являются C / C ++ и PL / I), но оставался неизменным для ассемблеров. Подстановка параметров макроса строго по имени: во время обработки макроса значение параметра заменяется текстом на его имя. Самым известным классом возникающих ошибок было использование параметра, который сам был выражением, а не простым именем, когда писатель макроса ожидал имя. В макросе: foo: macro a load a * b намерение состояло в том, что вызывающий объект должен предоставить имя переменной, а «глобальная» переменная или константа b будет использоваться для умножения «a».Если foo вызывается с параметром a-c, происходит расширение макроса load a-c * b. Чтобы избежать любой возможной двусмысленности, пользователи макропроцессоров могут заключать в скобки формальные параметры внутри определений макросов, или вызывающие программы могут заключать в скобки входные параметры. [8] PL / I и C / C ++ содержат макросы, но это средство может только управлять текстом. С другой стороны, гомоиконные языки, такие как Lisp, Prolog и Forth, сохраняют силу макросов языка ассемблера, поскольку они могут манипулировать своим собственным кодом как данными. Поддержка структурного программированияНекоторые ассемблеры включают элементы структурированного программирования для кодирования потока выполнения. Самый ранний пример этого подхода был в наборе макросов Concept-14, первоначально предложенном доктором Х.Д. Миллса (март 1970 г.) и реализован Марвином Кесслером из подразделения IBM Federal Systems Division, который расширил макроассемблер S / 360 с помощью IF / ELSE / ENDIF и аналогичных блоков потока управления. [9] Это был способ уменьшить или исключить использование операций GOTO в коде ассемблера, что является одним из основных факторов, вызывающих спагетти-код в ассемблере.Этот подход был широко принят в начале 80-х (последние дни широкомасштабного использования языка ассемблера). Любопытным проектом был A-natural, «ориентированный на поток» ассемблер для процессоров 8080 / Z80 [ цитата требуется ] от Whitesmiths Ltd. (разработчики Unix-подобной операционной системы Idris, и то, что, как сообщается, первый коммерческий компилятор C). Язык был классифицирован как ассемблер, потому что он работал с необработанными машинными элементами, такими как коды операций, регистры и ссылки на память; но он включил синтаксис выражения, чтобы указать порядок выполнения.Скобки и другие специальные символы, наряду с конструкциями блочно-ориентированного структурного программирования, управляют последовательностью генерируемых инструкций. A-natural был создан как объектный язык компилятора C, а не для ручного кодирования, но его логический синтаксис завоевал некоторых поклонников. После упадка крупномасштабной разработки языков ассемблера очевидного спроса на более сложные ассемблеры не было. [10] Несмотря на это, они все еще разрабатываются и применяются в случаях, когда ограничения ресурсов или особенности в архитектуре целевой системы препятствуют эффективному использованию языков более высокого уровня. [11] Использование ассемблераИсторическая перспективаАссемблерные языки были впервые разработаны в 1950-х годах, когда их называли языками программирования второго поколения. Натаниэль Рочестер написал первый ассемблер для IBM 701. Например, SOAP (Symbolic Optimal Assembly Program) был ассемблером 1957 года для компьютера IBM 650. Языки ассемблера устранили большую часть подверженного ошибкам и трудоемкого программирования первого поколения, необходимого для самых ранних компьютеров, освобождая программистов от утомительной работы, такой как запоминание числовых кодов и вычисление адресов.Когда-то они широко использовались для всех видов программирования. Однако к 1980-м годам (1990-е годы на микрокомпьютерах) их использование было в значительной степени вытеснено языками высокого уровня [ цитата требуется ] в поисках повышения производительности программирования. Сегодня, хотя ассемблер почти всегда обрабатывается и генерируется компиляторами, он по-прежнему используется для прямого управления оборудованием, доступа к специализированным инструкциям процессора или для решения критических проблем производительности. Обычно используются драйверы устройств, встраиваемые системы низкого уровня и системы реального времени. Исторически сложилось так, что большое количество программ было написано полностью на языке ассемблера. Операционные системы были написаны почти исключительно на ассемблере до широкого распространения C в 1970-х и начале 1980-х годов. Многие коммерческие приложения также были написаны на языке ассемблера, включая большое количество программного обеспечения для мэйнфреймов IBM, написанного крупными корпорациями. COBOL и FORTRAN в конечном итоге вытеснили большую часть этой работы, хотя ряд крупных организаций сохраняли инфраструктуры приложений на ассемблере вплоть до 90-х годов. Большинство ранних микрокомпьютеров полагались на кодируемый вручную ассемблер, включая большинство операционных систем и больших приложений. Это было связано с тем, что эти системы имели жесткие ограничения ресурсов, требовали особой архитектуры памяти и дисплеев, а также предоставляли ограниченные системные службы с ошибками. Возможно, более важным было отсутствие первоклассных компиляторов языков высокого уровня, подходящих для использования на микрокомпьютерах. Психологический фактор, возможно, также сыграл свою роль: первое поколение программистов микрокомпьютеров сохраняло увлеченность, «проволоку и плоскогубцы». В более коммерческом контексте основными причинами использования языка ассемблера были минимальный раздут (размер), минимальные накладные расходы, большая скорость и надежность. Типичными примерами крупных программ на языке ассемблера того времени являются операционные системы IBM PC DOS и ранние приложения, такие как программа электронных таблиц Lotus 1-2-3. Даже в 1990-е годы большинство консольных видеоигр было написано на ассемблере, в том числе большинство игр для Mega Drive / Genesis и Super Nintendo Entertainment System [ цитата требуется ] .По мнению некоторых инсайдеров отрасли, язык ассемблера был лучшим компьютерным языком для использования с максимальной производительностью Sega Saturn, консоли, для которой, как известно, было сложно разрабатывать и программировать игры. [12] Популярная аркадная игра NBA Jam (1993) — еще один пример. Ассемблер долгое время был основным языком разработки для многих популярных домашних компьютеров 1980-х и 1990-х годов (таких как Sinclair ZX Spectrum, Commodore 64, Commodore Amiga и Atari ST).В значительной степени это было связано с тем, что диалекты BASIC в этих системах предлагали недостаточную скорость выполнения, а также недостаточные возможности для использования всех преимуществ доступного оборудования в этих системах. Некоторые системы, в первую очередь Amiga, даже имеют IDE с высокоразвитыми средствами отладки и макросами, такими как бесплатный ассемблер ASM-One, сравнимый с средствами Microsoft Visual Studio (ASM-One предшествует Microsoft Visual Studio). Ассемблер для VIC-20 был написан Доном Френчем и опубликован French Silk .Его длина составляет 1639 байт, и автор считает, что это самый маленький из когда-либо написанных символических ассемблеров. Ассемблер поддерживает обычную символьную адресацию и определение символьных или шестнадцатеричных строк. Это также позволило использовать адресные выражения, которые можно было комбинировать с операторами сложения, вычитания, умножения, деления, логического И, логического ИЛИ и возведения в степень. [13] Текущее использованиеВсегда велись споры о полезности и производительности языка ассемблера по сравнению с языками высокого уровня.У ассемблера есть особые ниши, где он важен; увидеть ниже. Но в целом современные оптимизирующие компиляторы заявлены [ цитирования ] для преобразования языков высокого уровня в код, который может работать так же быстро, как рукописная сборка, несмотря на контрпримеры, которые можно найти. [14] [15] [16] Сложность современных процессоров и подсистемы памяти делает эффективную оптимизацию все более сложной задачей для компиляторов, а также программистов на ассемблере. [17] [18] Более того, и, к ужасу любителей эффективности, увеличение производительности процессоров привело к тому, что большинство процессоров большую часть времени простаивают, [ цитата необходима ] с задержками, вызванными предсказуемыми узкими местами, такими как как операции ввода-вывода и подкачки. Это сделало скорость выполнения исходного кода не проблемой для многих программистов. Есть несколько ситуаций, в которых практикующие могут выбрать язык ассемблера, например, когда: Ассемблер по-прежнему преподается в большинстве программ по информатике и электронной инженерии. Хотя сегодня немногие программисты регулярно работают с языком ассемблера в качестве инструмента, основные концепции остаются очень важными. Такие фундаментальные темы, как двоичная арифметика, выделение памяти, обработка стека, кодирование набора символов, обработка прерываний и дизайн компилятора, было бы трудно изучать подробно, не имея представления о том, как компьютер работает на аппаратном уровне. Поскольку поведение компьютера в основном определяется его набором инструкций, логическим способом изучения таких концепций является изучение языка ассемблера.Большинство современных компьютеров имеют аналогичные наборы команд. Следовательно, изучения единственного языка ассемблера достаточно, чтобы усвоить: I) основные понятия; II) распознавать ситуации, когда использование ассемблера может быть уместным; и III) чтобы увидеть, как эффективный исполняемый код может быть создан из языков высокого уровня. [22] Это аналогично тому, как детям необходимо изучить основные арифметические операции (например, деление в столбик), хотя калькуляторы широко используются для всех, кроме самых тривиальных вычислений. Типовые области примененияЖестко запрограммированный язык ассемблера обычно используется в загрузочном ПЗУ системы (BIOS в IBM-совместимых системах ПК). Этот низкоуровневый код используется, среди прочего, для инициализации и тестирования системного оборудования перед загрузкой ОС и сохраняется в ПЗУ. После определенного уровня инициализации оборудования выполнение переходит к другому коду, обычно написанному на языках более высокого уровня; но код, запускаемый сразу после включения питания, обычно написан на языке ассемблера.То же самое и с большинством загрузчиков. Многие компиляторы преобразуют языки высокого уровня в сборку перед полной компиляцией, что позволяет просматривать код сборки для целей отладки и оптимизации. Относительно низкоуровневые языки, такие как C, часто предоставляют специальный синтаксис для встраивания языка ассемблера непосредственно в исходный код. Программы, использующие такие средства, как ядро Linux, могут затем создавать абстракции с использованием разных языков ассемблера на каждой аппаратной платформе. Затем переносимый код системы может использовать эти зависящие от процессора компоненты через единый интерфейс. Язык ассемблера также полезен для обратного проектирования, поскольку многие программы распространяются только в форме машинного кода, а машинный код обычно легко перевести на язык ассемблера и внимательно изучить в этой форме, но очень сложно перевести на язык более высокого уровня. . Такие инструменты, как Interactive Disassembler, широко используют разборку для этой цели. Одна из ниш, использующих язык ассемблера, — это демосцена. Некоторые соревнования требуют, чтобы участники ограничивали свои творения очень маленькими размерами (например,грамм. 256 Б, 1 КБ, 4 КБ или 64 КБ), а язык ассемблера является предпочтительным языком для достижения этой цели. [23] Когда ресурсы, особенно системы с ограниченными процессорами, такие как ранние модели Amiga и Commodore 64, вызывают беспокойство, кодирование на ассемблере является обязательным. Оптимизированный ассемблерный код пишется «вручную», и программисты вручную упорядочивают инструкции в попытке минимизировать количество используемых циклов ЦП. Ограничения ЦП настолько велики, что на счету каждый цикл ЦП. Однако использование таких методов позволило таким системам, как Commodore 64, создавать трехмерную графику в реальном времени с расширенными эффектами, что может считаться маловероятным или даже невозможным для системы с 1.Процессор 02MHz. [ необходима ссылка ] Связанная терминологияСписок ассемблеров для разных архитектур компьютеровНа следующей странице приведен список различных ассемблеров для различных компьютерных архитектур, а также вся соответствующая информация для этого конкретного ассемблера: Дополнительная информацияДля любого данного персонального компьютера, мэйнфрейма, встроенной системы и игровой консоли, как в прошлом, так и в настоящем, был написан по крайней мере один — возможно, десятки — ассемблеров. Некоторые примеры см. В списке ассемблеров. В системах Unix ассемблер традиционно называется, так как, хотя это не единый код, обычно пишется заново для каждого порта. В ряде вариантов Unix используется GAS. Внутри процессорных групп каждый ассемблер имеет свой диалект. Иногда некоторые ассемблеры могут читать диалект другого ассемблера, например, TASM может читать старый код MASM, но не наоборот. FASM и NASM имеют схожий синтаксис, но каждый из них поддерживает разные макросы, что может затруднить их преобразование друг в друга.Основы все те же, но расширенные функции будут отличаться. [27] Кроме того, иногда сборку можно переносить в разные операционные системы на один и тот же тип процессора. Соглашения о вызовах между операционными системами часто немного различаются или совсем не различаются, и при осторожности можно добиться некоторой переносимости на языке ассемблера, обычно путем связывания с библиотекой C, которая не меняется между операционными системами. Имитатор набора команд (который в идеале был бы написан на языке ассемблера) теоретически может обрабатывать объектный код / двоичный код любого ассемблера для достижения переносимости даже между платформами (с накладными расходами, не превышающими типичный интерпретатор байт-кода).По сути, это то, чего достигает микрокод, когда аппаратная платформа изменяется внутри. Например, многие вещи в libc зависят от того, как препроцессор выполняет специфичные для ОС и C-специфичные для программы вещи перед компиляцией. Фактически, существование некоторых функций и символов вне препроцессора даже не гарантируется. Хуже того, размер и порядок полей структур, а также размер определенных определений типов, таких как off_t, полностью недоступны на языке ассемблера без помощи скрипта настройки и различаются даже между версиями Linux, что делает невозможным перенос функций вызова. в libc, кроме тех, которые принимают в качестве параметров только простые целые числа и указатели.Чтобы решить эту проблему, проект FASMLIB предоставляет переносимую библиотеку сборки для платформ Win32 и Linux, но она еще очень неполная. [28] Некоторые компьютерные языки более высокого уровня, такие как C и Borland Pascal, поддерживают встроенную ассемблерную систему, при которой участки ассемблерного кода, на практике обычно короткие, могут быть встроены в код языка высокого уровня. Язык Forth обычно содержит ассемблер, используемый в словах CODE. Эмулятор можно использовать для отладки программ на языке ассемблера. Пример листинга исходного кода на ассемблере
|