Для чего используют программы ассемблеры
Почему Ассемблер — это круто, но сложно
Потому что это круто. Но сложно.
Есть высокоуровневые языки — это те, где вы говорите if — else, print, echo, function и так далее. «Высокий уровень» означает, что вы говорите с компьютером более-менее человеческим языком. Другой человек может не понять, что именно у вас написано в коде, но он хотя бы сможет прочитать слова.
Но сам компьютер не понимает человеческий язык. Компьютер — это регистры памяти, простые логические операции, единицы и нули. Поэтому прежде чем ваша программа будет исполнена процессором, ей нужен переводчик — программа, которая превратит высокоуровневый язык программирования в низкоуровневый машинный код.
Ассемблер — это собирательное название языков низкого уровня: код всё ещё пишет человек, но он уже гораздо ближе к принципам работы компьютера, чем к принципам мышления человека.
Вариантов Ассемблера довольно много. Но так как все они работают по одинаковому принципу и используют (в основном) одинаковый синтаксис, мы будем все подобные языки называть общим словом «Ассемблер».
Как мыслит процессор
Чтобы понять, как работает Ассемблер и почему он работает именно так, нам нужно немного разобраться с внутренним устройством процессора.
Кроме того, что процессор умеет выполнять математические операции, ему нужно где-то хранить промежуточные данные и служебную информацию. Для этого в самом процессоре есть специальные ячейки памяти — их называют регистрами.
Регистры бывают разного вида и назначения: одни служат, чтобы хранить информацию; другие сообщают о состоянии процессора; третьи используются как навигаторы, чтобы процессор знал, куда идти дальше, и так далее. Подробнее — в расхлопе ↓
Общего назначения. Это 8 регистров, каждый из которых может хранить всего 4 байта информации. Такой регистр можно разделить на 2 или 4 части и работать с ними как с отдельными ячейками.
Указатель команд. В этом регистре хранится только адрес следующей команды, которую должен выполнить процессор. Вручную его изменить нельзя, но можно на него повлиять различными командами переходов и процедур.
Регистр флагов. Флаг — какое-то свойство процессора. Например, если установлен флаг переполнения, значит процессор получил в итоге такое число, которое не помещается в нужную ячейку памяти. Он туда кладёт то, что помещается, и ставит в этот флаг цифру 1. Она — сигнал программисту, что что-то пошло не так.
Флагов в процессоре много, какие-то можно менять вручную, и они будут влиять на вычисления, а какие-то можно просто смотреть и делать выводы. Флаги — как сигнальные лампы на панели приборов в самолёте. Они что-то означают, но только самолёт и пилот знают, что именно.
Сегментные регистры. Нужны были для того, чтобы работать с оперативной памятью и получать доступ к любой ячейке. Сейчас такие регистры имеют по 32 бита, и этого достаточно, чтобы получить 4 гигабайта оперативки. Для программы на Ассемблере этого обычно хватает.
Так вот: всё, с чем работает Ассемблер, — это команды процессора, переменные и регистры.
Здесь нет привычных типов данных — у нас есть только байты памяти, в которых можно хранить что угодно. Даже если вы поместите в ячейку какой-то символ, а потом захотите работать с ним как с числом — у вас получится. А вместо привычных циклов можно просто прыгнуть в нужное место кода.
Команды Ассемблера
Каждая команда Ассемблера — это команда для процессора. Не операционной системе, не файловой системе, а именно процессору — то есть в самый низкий уровень, до которого может дотянуться программист.
Любая команда на этом языке выглядит так:
Метка — это имя для фрагмента кода. Например, вы хотите отдельно пометить место, где начинается работа с жёстким диском, чтобы было легче читать код. Ещё метка нужна, чтобы в другом участке программы можно было написать её имя и сразу перепрыгнуть к нужному куску кода.
Команда — служебное слово для процессора, которое он должен выполнить. Специальные компиляторы переводят такие команды в машинный код. Это сделано для того, чтобы не запоминать сами машинные команды, а использовать вместо них какие-то буквенные обозначения, которые проще запомнить. В этом, собственно, и выражается человечность Ассемблера: команды в нём хотя бы отдалённо напоминают человеческие слова.
Операнды отвечают за то, что именно будут делать команды: какие ячейки брать для вычислений, куда помещать результат и что сделать с ним дополнительно. Операндом могут быть названия регистров, ячейки памяти или служебные части команд.
Комментарий — это просто пояснение к коду. Его можно писать на любом языке, и на выполнение программы он не влияет. Примеры команд:
mov eax, ebx ; Пересылаем значение регистра EBX в регистр EAX mov x, 0 ; Записываем в переменную x значение 0 add eax, х ; Складываем значение регистра ЕАХ и переменной х, результат отправится в регистр ЕАХ
Здесь нет меток, первыми идут команды (mov или add), а за ними — операнды и комментарии.
Пример: возвести число в куб
Если нам понадобится вычислить х³, где х занимает ровно один байт, то на Ассемблере это будет выглядеть так.
Первый вариант
mov al, x ; Пересылаем x в регистр AL imul al ; Умножаем регистр AL на себя, AX = x * x movsx bx, x ; Пересылаем x в регистр BX со знаковым расширением imul bx ; Умножаем AX на BX. Результат разместится в DX:AX
Второй вариант
mov al, x ; Пересылаем x в регистр AL imul al ; Умножаем регистр AL на себя, AX = x * x cwde ; Расширяем AX до EAX movsx ebx, x ; Пересылаем x в регистр EBX со знаковым расширением imul ebx ; Умножаем EAX на EBX. Поскольку x – 1-байтовая переменная, результат благополучно помещается в EAX
На любом высокоуровневом языке возвести число в куб можно одной строкой. Например:
на худой конец x = x*x*x.
Хитрость в том, что когда каждая из этих строк будет сведена к машинному коду, этого кода может быть и 5 команд, и 10, и 50, и даже 100. Чего стоит вызов объекта Math и его метода pow: только на эту служебную операцию (ещё до самого возведения в куб) может уйти несколько сотен и даже тысяч машинных команд.
А на Ассемблере это гарантированно пять команд. Ну, или как реализуете.
Почему это круто
Ассемблер позволяет работать с процессором и памятью напрямую — и делать это очень быстро. Дело в том, что в Ассемблере почти не тратится зря процессорное время. Если процессор работает на частоте 3 гигагерца — а это примерно 3 миллиарда процессорных команд в секунду, — то очень хороший код на Ассемблере будет выполнять примерно 2,5 миллиарда команд в секунду. Для сравнения, JavaScript или Python выполнят в тысячу раз меньше команд за то же время.
Ещё программы на Ассемблере занимают очень мало места в памяти. Именно поэтому на этом языке пишут драйверы, которые встраивают прямо в устройства, или управляющие программы, которые занимают несколько килобайт. Например, программа, которая находится в брелоке сигнализации и управляет безопасностью всей машины, занимает всего пару десятков килобайт. А всё потому, что она написана для конкретного процессора и использует его возможности на сто процентов.
Справедливости ради отметим, что современные компиляторы С++ дают машинный код, близкий по быстродействию к Ассемблеру, но всё равно немного уступают ему.
Почему это сложно
Для того, чтобы писать программы на Ассемблере, нужно очень любить кремний:
Теперь добавьте к этому отсутствие большинства привычных библиотек для работы с чем угодно, сложность чтения текста программы, медленную скорость разработки — и вы получите полное представление о программировании на Ассемблере.
Для чего всё это
Ассемблер незаменим в таких вещах:
На самом деле на Ассемблере можно даже запилить свой сайт с форумом, если у программиста хватает квалификации. Но чаще всего Ассемблер используют там, где даже скорости и возможностей C++ недостаточно.
Язык ассемблера
Язык ассемблера (автокод) — язык программирования низкого уровня. В отличие от языка машинных кодов, позволяет использовать более удобные для человека мнемонические (символьные) обозначения команд. При этом для перевода с языка ассемблера в понимаемый процессором машинный код требуется специальная программа, называемая ассемблером.
Содержание
Содержание языка
Команды языка ассемблера один к одному соответствуют командам процессора, фактически, они представляют собой более удобную для человека символьную форму записи (мнемокод) команд и их аргументов.
Кроме того, язык ассемблера обеспечивает использование символических меток вместо адресов ячеек памяти, которые при ассемблировании заменяются на автоматически рассчитываемые абсолютные или относительные адреса, а также так называемых директив (команд, не переводящихся в процессорные инструкции, а выполняемых самим ассемблером).
Директивы ассемблера позволяют, в частности, включать блоки данных, задать ассемблирование фрагмента программы по условию, задать значения меток, использовать макроопределения с параметрами.
Каждая модель (или семейство) процессоров имеет свой набор команд и соответствующий ему язык ассемблера. Наиболее популярные синтаксисы: Intel-синтаксис и AT&T-синтаксис.
Существуют компьютеры, реализующие в качестве машинного язык программирования высокого уровня (Forth, Lisp, Эль-76), фактически в них он является «ассемблером».
Достоинства и недостатки
Достоинства
Недостатки
Применение
Исторически можно рассматривать ассемблер как второе поколение языков программирования ЭВМ (если первым считать машинный код). Недостатки ассемблера, сложность разработки на нем больших программных комплексов привели к появлению языков третьего поколения — языков программирования высокого уровня (Фортран, Лисп, Кобол, Паскаль, Си и др.). Именно языки программирования высокого уровня и их наследники в основном используются в настоящее время в индустрии информационных технологий. Однако, языки ассемблера сохраняют свою нишу, обуславливаемую их уникальными преимуществами в части эффективности и возможности полного использования специфических средств конкретной платформы.
На ассемблере пишутся программы или фрагменты программ, для которых критически важны:
С использованием программирования на ассемблере производятся:
Нелегальная сфера деятельности
Программирование на языке ассемблера характерно также для нелегальных сфер деятельности в ИТ, в частности, с использованием ассемблера производятся:
Связывание программ на разных языках
Поскольку на ассемблере часто разрабатываются только фрагменты программ, их необходимо связывать с остальными частями программной системы, написанными на других языках программирования.
Это достигается 2 основными способами:
Синтаксис
Синтаксис языка ассемблера определяется системой команд конкретного процессора.
Набор команд
Типичными командами языка ассемблера являются (большинство примеров даны для Intel-синтаксиса архитектуры x86):
Инструкции
Типичный формат записи команд: [метка:] опкод [операнды] [;комментарий]
где опкод (код операции) — непосредственно мнемоника инструкции процессору. К ней могут быть добавлены префиксы (повторения, изменения типа адресации и пр.).
В качестве операндов могут выступать константы, адреса регистров, адреса в оперативной памяти и пр.. Различия между стандартами Intel и AT&T касаются, в основном, порядка перечисления операндов и их синтаксиса при различных методах адресации.
Используемые мнемоники обычно одинаковы для всех процессоров одной архитектуры или семейства архитектур (среди широко известных — мнемоники процессоров и контроллеров x86, ARM, SPARC, PowerPC, M68k). Они описываются в спецификации процессоров. Возможные исключения:
Например, процессор Zilog Z80 наследовал систему команд Intel i8080, расширил ее и поменял мнемоники (и обозначения регистров) на свой лад. Процессоры Motorola Fireball наследовали систему команд Z80, несколько её урезав. Вместе с тем, Motorola официально вернулась к мнемоникам Intel. И в данный момент половина ассемблеров для Fireball работает с интеловскими мнемониками, а половина с мнемониками Zilog.
Директивы
Программа на ассемблере может содержать директивы: инструкции, не переводящиеся непосредственно в машинные команды, а управляющие работой компилятора. Набор и синтаксис их значительно разнятся и зависят не от аппаратной платформы, а от используемого транслятора (порождая диалекты языков в пределах одного семейства архитектур). В качестве «джентельменского набора» директив можно выделить следующие:
Пример программы
Примеры программы Hello, world! для разных платформ и разных диалектов: Шаблон:Hider hiding
Происхождение и критика термина «язык ассемблера»
Данный тип языков получил свое название от названия транслятора (компилятора) с этих языков — ассемблера (привет — сборщик). Название обусловлено тем, что программа «автоматически собиралась», а не вводилась вручную покомандно непосредственно в кодах. При этом наблюдается путаница терминов: ассемблером нередко называют не только транслятор, но и соответствующий язык программирования («программа на ассемблере»).
Использование термина «язык ассемблера» также может вызвать ошибочное мнение о существовании некоего единого языка низкого уровня, или хотя бы стандартов на такие языки. При именовании языка ассемблера желательно уточнять, ассемблер для какой архитектуры имеется в виду.
В СССР язык ассемблера ранее называли «автокод».
Что такое ассемблер и нужно ли его изучать
Этому языку уже за 70, но на пенсию он пока не собирается.
Полина Суворова для Skillbox Media
Есть традиция начинать изучение программирования с вывода на экран строки «Hello world!». На языке Python, например, это всего одна команда:
Всё просто, понятно и красиво! Но есть язык программирования, в котором, чтобы получить тот же результат, нужно написать солидный кусок кода:
Это ассемблер. Только не нужно думать, что он плох. Просто Python — это язык высокого уровня, а ассемблер — низкого. Одна команда Python при выполнении вызывает сразу несколько операций процессора, а каждая команда ассемблера — всего одну операцию.
Сложно? Давайте разбираться.
Программист, консультант, специалист по документированию. Легко и доступно рассказывает о сложных вещах в программировании и дизайне.
Немного о процессорах и машинном языке
Чтобы объяснить, что такое язык ассемблера, начнём с того, как вообще работает процессор и на каком языке с ним можно «разговаривать».
Процессор — это электронное устройство (сейчас крошечная микросхема, а раньше процессоры занимали целые залы), не понимающее слов и цифр. Он реагирует только на два уровня напряжения: высокий — единица, низкий — ноль. Поэтому каждая процессорная команда — это последовательность нулей и единиц: 1 — есть импульс, 0 — нет.
Для работы с процессором используется машинный язык. Он состоит из инструкций, записанных в двоичном коде. Каждая инструкция определяет одну простую машинную операцию: арифметическую над числами, логическую (поразрядную), ввода-вывода и так далее.
Например, для Intel 8088 инструкция 0000001111000011B — это операция сложения двух чисел, а 0010101111000011B — вычитания.
Программировать на машинном языке нелегко — приходится работать с огромными цепочками нулей и единиц. Трудно написать или проверить такую программу, а уж тем более разобраться в чужом коде.
Поэтому много лет назад был создан язык ассемблера, в котором коды операций обозначались буквами и сокращениями английских слов, отражающих суть команды. Например, команда mov ax, 6 означает: «переместить число 6 в ячейку памяти AX».
Когда и как был создан ассемблер?
Это произошло ещё в сороковых годах прошлого века. Ассемблер был создан для первых ЭВМ на электронных лампах, программы для которых писали на машинном языке. А так как памяти у компьютеров было мало, то команды вводили, переключая тумблеры и нажимая кнопки. Даже несложные вычисления занимали много времени.
Проблему решили, когда ЭВМ научились хранить программы в памяти. Уже в 1950 году была разработана первая программа-транслятор, которая переводила в машинный код программы, написанные на понятном человеку языке. Эту программу назвали программой-сборщиком, а язык — языком ассемблера (от англ. assembler — сборщик).
Появление ассемблера сильно облегчило жизнь программистов. Они смогли вместо двоичных кодов использовать команды, состоящие из близких к обычному языку условных обозначений. Кроме того, ассемблер позволил уменьшить размеры программ — для машин того времени это было важно.
Как устроен язык ассемблера?
Ассемблер можно считать языком второго поколения, если за первый принять машинный язык. Он работает непосредственно с процессором, и каждая его команда — это инструкция процессора, а не операционной или файловой системы. Перевод языка ассемблера в машинный код называется ассемблированием.
Коды операций в языке ассемблера мнемонические, то есть удобные для запоминания:
Регистрам и ячейкам памяти присваиваются символические имена, например:
EAX, EBX, AX, AH — имена для регистров;
meml — имя для ячейки памяти.
Например, так выглядит команда сложения чисел из регистров AX и BX:
А это команда вычитания чисел из регистров AX и BX:
Кроме инструкций, в языке ассемблера есть директивы — команды управления компилятором, то есть программой-ассемблером.
Вот некоторые из них:
Не думайте, что ассемблер — всего лишь набор инструкций процессора с удобной для программиста записью. Это полноценный язык программирования, на котором можно организовать циклы, условные переходы, процедуры и функции.
Вот, например, код, на ассемблере, выводящий на экран цифры от 1 до 10:
Здесь действие будет выполняться в цикле — как, например, в циклах for или do while в языках высокого уровня.
Единого стандарта для языков ассемблера нет. В работе с процессорами Intel разработчики придерживаются двух синтаксисов: Intel и AT&T. Ни у того ни у другого нет особых преимуществ: AT&T — стандартный синтаксис в Linux, а Intel используется в мире Microsoft.
Одна и та же команда в них выглядит по-разному.
Например, в синтаксисе Intel:
mov eax, ebx — команда перемещает данные из регистра eax в регистр ebx.
В синтаксисе AT&T эта команда выглядит так:
Почему для разных семейств процессоров нужен свой ассемблер?
Дело в том, что у каждого процессора есть набор характеристик — архитектура. Это его конструкция и принцип работы, а также регистры, адресация памяти и используемый набор команд. Если у процессоров одинаковая архитектура, то говорят, что они из одного семейства.
Так как наборы команд для разных архитектур процессоров отличаются друг от друга, то и программы на ассемблере, написанные для одних семейств, не будут работать на процессорах из других семейств. Поэтому ассемблер называют машинно-ориентированным языком.
Кому и зачем нужен язык ассемблера?
Даже из нашего примера «Hello, World!» видно, что ассемблер не так удобен в разработке, как языки высокого уровня. Больших программ на этом языке сейчас никто не пишет, но есть области, где он незаменим:
Если вы хотите разрабатывать новые микропроцессоры или стать реверс-инженером, то есть смысл серьёзно заняться изучением языка ассемблера.
Востребованы ли программисты на ассемблере сегодня?
Конечно. Хотя на сайтах по поиску работу вы вряд ли найдёте заявки от работодателей с заголовками: «Нужен программист на ассемблере», зато там много таких, где требуется знание ассемблера дополнительно к языкам высокого уровня: C, C++ или Python. Это вакансии реверс-инженеров, специалистов по компьютерной безопасности, разработчиков драйверов и программ для микроконтроллеров/микропроцессоров, системных программистов и другие.
Предлагаемая зарплата — обычная в сфере IT: 80–300 тысяч рублей в зависимости от квалификации и опыта. Вот, например, вакансия реверс-инженера на HeadHunter, где требуется знание ассемблера:
Стоит ли начинать изучение программирования с языка ассемблера?
Нет, так делать не нужно. Для этого есть несколько причин:
Поэтому, даже если вы решили заняться профессией, связанной с ассемблером, изучение программирования вам лучше начинать с языка высокого уровня. А уж ассемблер после него будет выучить несложно.
Микропроцессор, выпущенный компанией Intel в 1979 году. Использовался в оригинальных компьютерах IBM PC.
Данные, которые обрабатываются командой — грамматической конструкцией языка программирования, обозначающей аргумент операции.
Центральная часть операционной системы, координирующая доступ приложений к процессорному времени, памяти, внешним устройствам.
Программа, которая обеспечивает загрузку самой OC сразу после включения компьютера.
Для чего нужен ассемблер?
Скажем так: зачем уметь собирать-разбирать двигатель от машины и понимать как он работает?
99% людей это не нужно в принципе. Но если вы это знаете, вы можете легко диагностировать какую-то проблему, понять как её решить. При этом, каждый день вы не производите двигатели на станке.
То же самое с ассемблером: чтобы понимать как работает программа, как её отладить, диагностировать, понять, что не работает — для этого и нужен ассемблер. Писать на нём что-то конкретное и большое сейчас абсолютно бессмысленно. Его надо знать и понимать, этого достаточно.
К вашему сведению драйверы это часть ОС. Их как и всю ОС можно написать на СИ, можно на Assembler, а можно, например, на Pascal. Просто сейчас компьютеры настолько быстрые и имеют так много памяти, что оптимизация кода уходит на второй план. Хотя компиляторы современных языков программирования в плане оптимизации фору дадут большинству современных программистов.
Но все таки в серьезных программах есть много так называемых»узких мест» как правило это связано с нехваткой быстродействия, реже нехваткой памяти, тут на помощь приходит ассемблер.
Хотя чудику который говнокодит на PHP или JS этого не понять
PS Язык программирования это инструмент, а не стихотворение его учить не надо, на нем надо писать программы
Погружение в ассемблер. Зачем учить ассемблер в 2020 году
Содержание статьи
Погружение в ассемблер
Это вводная статья цикла «Погружение в ассемблер», которую мы публикуем в честь его завершения. Ее полный текст доступен без подписки. Прочитав ее, ты можешь переходить к другим статьям этого курса:
Ради чего стоит изучать ассемблер?
Стоит освоить ассемблер, если ты хочешь:
Не стоит осваивать ассемблер, если ты хочешь ускорить другие свои программы. Современные оптимизирующие компиляторы справляются с этой задачей очень хорошо. Ты вряд ли сможешь обогнать их.
Кто выдаст лучший ассемблерный код?
Почему обогнать компилятор практически невозможно? Смотри, для тебя же очевидно, что компьютер в шахматы не обыграть, даже если ты играешь лучше, чем создатель шахматной программы? С оптимизирующими компиляторами та же история. Только оптимизирующий компилятор играет не шахматными фигурами, а контекстными обстоятельствами.
В современных процессорах практически ничто из того, что влияет на производительность, нельзя обсуждать в отрыве от контекста. Одна и та же комбинация из десятка ассемблерных инструкций выполняется с резкими отличиями по скорости (в тысячи или даже миллионы раз), в зависимости от целой кучи самых разнообразных обстоятельств.
И все это только верхушка айсберга, малая часть того, что тебе придется учитывать и анализировать, когда будешь стараться переиграть компилятор.
Есть такой миф, что программы, написанные на ассемблере, работают в десять раз быстрее. Этот миф уходит корнями в семидесятые годы. Компиляторы в те далекие времена генерировали код настолько бездарно, что у каждого уважающего себя программиста был черный список запрещенных языковых конструкций.
Когда наши коллеги из прошлого писали программы, они либо держали в уме этот черный список и не давали своим пальцам набивать проблемные конструкции, либо настраивали специальный препроцессор, который конвертировал исходник в более низкоуровневое беспроблемное представление на том же языке. С тех пор минуло 50 лет. Компиляторы возмужали, но миф остался.
Конечно, даже сегодня можно изредка встретить уникума, который пишет более быстрый код, чем компилятор. Вот только времени у него на это уходит так много, что ни в какие ворота не лезет. Плюс для оптимизации от тебя требуется, чтобы ты назубок знал весь набор инструкций процессора.
Вдобавок, поскольку ты шлифуешь свой код вручную, никакой компилятор не подстрахует тебя, не поможет отловить баги, которые ты неизбежно плодишь, когда пишешь программу.
Кроме того, твой ассемблерный код будет непереносимым. То есть, если ты захочешь, чтобы твоя программа запускалась на другом типе процессора, тебе придется полностью переписать ее, чтобы создать модификацию, заточенную под набор инструкций этого другого процессора. Само собой, тебе эти инструкции тоже надо знать назубок.
В итоге ты потратишь в десятки и сотни раз больше времени, чем если бы доверился оптимизирующему компилятору, — но результат, скорее всего, окажется медленнее, а не быстрее.
При этом иногда оптимизирующий компилятор выплевывает ассемблерный код, логика которого ну совсем непонятна. Однако не спеши обвинять компилятор в глупости. Давай разберем пример.
Размышления подобного рода неизбежно заводят тебя в запутанный лабиринт альтернативных вариантов. Все их нужно просчитать, чтобы выбрать лучший. Но даже когда ты сделаешь это, вариант ассемблерного кода, сгенерированный компилятором, скорее всего, будет работать быстрее, чем твой.
Кстати, если используешь GCC или Clang, активируй опции оптимизации для SSE, AVX и всего остального, чем богат твой процессор. Затем откинься на спинку кресла и удивись, когда компилятор векторизует твой сишный код. Причем сделает это так, как тебе и не снилось.
Какие программы нельзя написать на ассемблере?
Нет таких. Все, что можно сделать на компьютере, можно сделать в том числе и на ассемблере. Ассемблер — это текстовое представление сырого машинного кода, в который переводятся все программы, запущенные на компьютере.
Ты при желании можешь написать на ассемблере даже веб‑сайт. В девяностые С был вполне разумным выбором для этой цели. Используя такую вещь, как CGI BIN, веб‑сервер мог вызывать программу, написанную на С. Через stdin сайт получал запрос, а через stdout отправлял результат в браузер. Ты можешь легко реализовать тот же принцип на ассемблере.
Но зачем? Ты должен быть мазохистом, чтобы проделывать такое. Потому что когда ты пишешь на ассемблере, то сталкиваешься вот с такими проблемами.
Да, все можно написать на ассемблере. Но сегодня это нецелесообразно. Лучше пиши на С. Скорее всего, будет безопаснее, быстрее и более лаконично.
От редакции
Автор статьи — большой поклонник С и настоятельно рекомендует этот язык. Мы не будем лишать его такой возможности. С — отличная штука и помогает как освоить основные концепции программирования, так и прочувствовать принципы работы компьютера. Однако при выборе языка для изучения ты можешь руководствоваться самыми разными соображениями. Например:
И так далее. Ответ на вопрос о том, с какого языка начать, зависит от многих факторов, и выбор — дело индивидуальное.
Конечно, когда ты знаешь ассемблер, у тебя будут значительные преимущества перед теми программистами, которые его не знают. Но прежде чем ознакомиться с этими преимуществами, запомни одну простую вещь: хорошие программисты знают ассемблер, но почти никогда не пишут на нем.
Какие преимущества ассемблер дает программисту?
Чтобы писать эффективные программы (в плане быстродействия и экономии ресурсов), тебе обязательно надо знать ассемблер того железа, для которого ты пишешь. Когда ты знаешь ассемблер, ты не обманываешься внешней простотой и краткостью высокоуровневых функций, а понимаешь, во что в итоге превращается каждая из них: в пару‑тройку ассемблерных инструкций или в длиннющую их последовательность, переплетенную циклами.
Если работаешь с языками высокого уровня, такими как С, научись хотя бы читать и понимать ассемблерный код. Даже если ты в обозримом будущем не видишь себя пишущим на ассемблере (на самом деле мало кто себя так видит), знание ассемблера тебе пригодится.
Если будешь с ассемблером на ты, он сослужит тебе хорошую службу в отладке. Освоив ассемблер, ты будешь понимать, что происходит под капотом языков высокого уровня, как компьютер делает то, что он делает, и почему высокоуровневый компилятор иногда работает не так, как ты ждешь от него. Ты сможешь видеть причину этого и понимать, как ее устранить.
Плюс иногда ты ну никак не можешь понять, что у тебя за баг, пока не пройдешься в отладчике в пошаговом режиме по ассемблерному коду.
И вот еще тонкий намек: некоторые работодатели хотели бы видеть в твоем резюме слово «ассемблер». Это говорит им, что ты не просто по верхам нахватался, а действительно интересуешься программированием, копаешь вглубь.
Стоит ли начинать изучать программирование с ассемблера?
Когда ты осваиваешь программирование, начиная с самых низов, в этом есть свои плюсы. Но ассемблер — это не самый низ. Если хочешь начать снизу, начни с логических вентилей и цифровой электроники. Затем поковыряйся с машинным кодом. И только потом приступай к ассемблеру.
Время от времени тебя будут посещать мысли, что ты занимаешься какой‑то ерундой. Но ты узнаешь много полезного для своей будущей работы, даже если она будет связана только с языками высокого уровня. Ты узнаешь, как именно компьютер делает те вещи, которые он делает.
Однако я бы не советовал начинать с ассемблера и более низких слоев. Во всем том, что перечислено в двух предыдущих абзацах, легче разобраться, когда ты начинаешь с какого‑нибудь языка высокого уровня. Так ты достигнешь желаемого результата быстрее, чем оно тебе наскучит.
Но в какой‑то момент тебе и правда обязательно надо познакомиться с ассемблером, особенно если программируешь на С. Я сомневаюсь, что ты сможешь стать полноценным программистом на С, не зная ассемблера. Но начинать с ассемблера не стоит.
Насколько легче учить другие языки, когда уже знаешь ассемблер?
Ассемблер совершенно не похож на языки высокого уровня. Поэтому народная мудрость «Тот опыт, который ты получил на одном языке, может быть легко сконвертирован на другой язык» с ассемблером не работает.
Если ты начнешь с ассемблера, то после того, как выучишь его и решишь освоить новый язык, тебе придется начинать как с чистого листа. Помню, мой однокашник еще в школе выучил ассемблер, написал на нем игрушку, с которой победил на конференции. Но при этом так и не смог хорошо освоиться в С, когда мы учились в универе.
Есть только память. Причем ты работаешь с ней не так, как на языке высокого уровня. Ты можешь забыть, что в какую‑то область памяти поместил строку, и обратиться к ней как к числу. Программа все равно скомпилируется. Но только обрушится в рантайме. Причем обрушится жестко, без вежливого сообщения об ошибке.
Но! Изучив ассемблер, ты будешь понимать, как реализуются и функции, и циклы, и все остальное. А разница между передачей параметра «по значению» и «по ссылке» станет для тебя самоочевидной. Плюс если ты пишешь на С, но не можешь до конца разобраться, как работают указатели, то, когда ты узнаешь, что такое регистры и относительная адресация, увидишь, что понять указатели совсем нетрудно.
Лучше начинай с С. На нем удобно осваивать основы: переменные, условия, циклы, логические построения и остальное. Опыт, который ты получишь при изучении С, легко сконвертировать на любой другой язык высокого уровня, будь то Java, Python или какой‑то еще. Да и с ассемблером легче разобраться, когда ты уже освоил С.
Насколько доходно уметь программировать на ассемблере?
Если заглянешь на HH.ru, то, скорее всего, не найдешь ни одной вакансии, у которой в заголовке написано слово «ассемблер». Но время от времени какая‑нибудь контора лихорадочно ищет мага‑волшебника, который знает нутро компьютера настолько глубоко, что может полностью подчинить операционную систему своей воле. Мага‑волшебника, который умеет (1) латать систему, не имея на руках исходного кода, (2) перехватывать потоки данных на лету и вмешиваться в них.
Некоторая часть этой глубокой магии — а сейчас потребность в такой магии становится все более редкой — может быть воплощена только на языке очень низкого уровня.
Я слышал о конторе, которая ищет человека на разработку новой платформы для высокочастотного трейдинга. Там идея в том, что если ты получаешь информацию о котировках быстрее своих конкурентов и принимаешь решение быстрее их, то будешь грести баснословные суммы.
«Когда ты получаешь котировки, проходя через весь стек TCP/IP, это слишком медленно», — говорят парни из этой фирмы. Поэтому у них есть примочка, которая перехватывает трафик на уровне Ethernet, прямо внутри сетевой карты, куда залита кастомизированная прошивка.
Но эти ребята пошли еще дальше. Они собираются разработать девайс для фильтрации трафика Ethernet — на ПЛИС. Зачем? Чтобы ловить котировки на аппаратном уровне и тем самым экономить драгоценные микросекунды трейдингового времени и в итоге получать небольшое, очень небольшое преимущество перед конкурентами. Язык С им не подошел. Им даже ассемблер не подошел. Так что эти парни выцарапывают программу прямо на кремнии!