Язык ассемблера — различия между версиями
NeKit (обсуждение | вклад) м (Замена текста — «Информация по хакингу» на «Хакинг и фанатские игры») |
Red TF (обсуждение | вклад) м (Замена текста — «bit» на «бит») |
||
Строка 18: | Строка 18: | ||
* вычисление | * вычисление | ||
** прибавить, вычесть, умножить, или разделить значения двух регистров, помещая результат в регистр | ** прибавить, вычесть, умножить, или разделить значения двух регистров, помещая результат в регистр | ||
− | ** выполнить [[wikipedia:ru:битовые операции|побитовые операции]], taking the conjunction/disjunction (and/or) of corresponding | + | ** выполнить [[wikipedia:ru:битовые операции|побитовые операции]], taking the conjunction/disjunction (and/or) of corresponding битs in a pair of registers, or the negation (not) of each бит in a register |
** сравнить два значения в регистрах (например, чтобы проверить, меньше ли одно другого, или они равны) | ** сравнить два значения в регистрах (например, чтобы проверить, меньше ли одно другого, или они равны) | ||
* повлиять на поток программы | * повлиять на поток программы |
Версия 08:32, 2 апреля 2014
Язык ассемблера или просто ассемблер - понятное человеку представление машинного языка, используемого определенной архитектурой компьютера. Машинный язык, шаблон битов кодирующих машинные операции, делается читабельным заменой сырых значения так называемой "мнемоникой".
Например, компьютер с соответствующим процессором поймет эту машинную инструкцию x86/IA-32: ::10110000 01100001 Однако програмистам легче запомнить эквивалентное представление на ассемблере: ::mov al, 0x61 что означает переместить шестадцатеричное значение 61 (97 - десятичное) в процессорный регистр с именем 'al'. Мнемоническое "mov" сокращение для "move," (переместить), и за ним следует разделяемый запятой список аргументов или параметров; это типичное выражение на языке ассемблера.
В отличии от языков высокого уровня, обычно имеется точное соответствие между простыми выражениями ассемблера и инструкциями на машинном языке. Превращение ассемблера в машинный язык делается ассемблером и обратное дизассемблером.
У каждой компьютерной архитектуры есть сообственный машинный язык, а значит и язык ассемблера. Компьютерные архитектуры отличаются количеством и тпипом операций, поддерживаемых ими. Они также могут иметь различный размер, количество регисторов и различные представления типов данных в памяти. Тогда как все компьютеры для общих целей имеют в целом одну и ту же функциональность, способ её реализации отличается, и все эти отличия неизбежно отражаются на языке ассемблера.
В дополнение, могут существовать различные варианты мнемоники или синтаксиса для одного набора инструкций. В таких случаях, обычно в документации производителем указывается самый популярный вариант.
Машинные инструкции
Инструкции в языке ассемблера обычно очень простые, в отличии от языков высокого уровня. Любая инструкция, обращающаяся к памяти (за данными или за целью прыжка) будет также иметь режим адресации для определения того, как высчитать требуемый адрес памяти. Более сложные операции должны быть построены из этих простых. Некоторые из операций, доступные в большинстве наборе инструкций:
- перемещения
- задают регистр (временная "сверхоперативная память" в самом CPU) в определённое постоянное значение
- переместить данные из памяти в регистр или наоборот. Это делается для того, чтобы получить данные и позже выполнить по ним вычисление, или сохранить результат вычисления.
- считывание и запись данных с оборудования
- вычисление
- прибавить, вычесть, умножить, или разделить значения двух регистров, помещая результат в регистр
- выполнить побитовые операции, taking the conjunction/disjunction (and/or) of corresponding битs in a pair of registers, or the negation (not) of each бит in a register
- сравнить два значения в регистрах (например, чтобы проверить, меньше ли одно другого, или они равны)
- повлиять на поток программы
- прыгнуть на другое местоположение в программе и исполнить инструкции там
- прыгнуть на другое местоположение при определённом условии
- прыгнуть на другое местоположение, но сохранить местоположение следующей инструкции как точку возврата (вызов)
Определённые наборы инструкций часто будут иметь одну или несколько инструкций для обычных операций, для чего иначе потребуется множество инструкций. Примеры:
- сохранить много регисторов в стеке за раз
- переместить большие блоки памяти
- сложная арифметика и/или операции с плавающей точкой (синус, косинус, квадратный корень и т. д.)
- применить простую операцию (к примеру, прибавление) к вектору значений
Директивы языка ассемблера
В дополнение к кодам машинных инструкций, у языков ассемблера есть дополнительные директивы для сборки блоков данных и присвоения адресов инструкциям или коду.
У них есть обычно простая возможность определять значения символьными выражениями, которые превращаются в машинные во время ассемблирования, делая возможным написание кода, более лёгкого для чтения и понимания.
Как и в большинстве компьютерных языков, возможно добавление комментариев, которые игнорируются ассемблером.
Также обычно используется встроенный макро-язык для облегчения генерациии сложных кусков кода или данных.
На практике, отсутствие комментариев и замена символов настоящими цифрами делает понимание человеком диассамблированного кода определённо более сложным, чем был бы оригинальный исходник.
Использование языка ассемблера
Ведутся обсуждения по поводу полезности языка ассемблера. Часто говорится, что современные компиляторы могу превращать языки высокого уровня в код, который может выполняться так быстро, как и код на ассемблере, написанный вручную, но приведенны могут быть считанные примеры, и поэтому по этой теме до сих пор не достигнут консенус. Однако точно ясно, учитывая увеливающуюся сложность соврменных процессоров, эффективная оптимизация врунчую становится все сложнее и сложнее и требует немало знаний и опыта.
Тем не менее, некоторые сложные вычисления ассеблером превращаются в куда более быстрый исполняемый код, и некоторое программирование низкого уровня на ассемблере легче. Некоторые системно-зависимые задачи, выполняемые операционными системами просто не могут быть выражены в языках высокого уровня. В частности, ассемблер часто используется для низкоуровнего взаимодействия между операционной системой и оборудованием, к примеру для драйверов устройств. Немало компиляторов также сначала преобразуют языки высокого уровня в ассемблер перед тем, как скомпилировать полностью, позволяя просмотреть код на ассемблере в целях отладки и оптизации.
Нередко, особенно в языках относительно низкого уровня, таких как C, возможно встраивание языка ассемблера в исходный код особым синтаксисом. Программы, использующие такие возможности, например ядро Linux, часто составляют абстракции, где используется различный код на ассемблере для всех поддерживаемых платформ, но он вызывается через переносимый код.
Много встраиваемых систем также программируются на ассемблере для получения максимальной функциональности из часто очень ограниченных вычислительных ресурсов, хотя это встречается всё реже в некоторых областях, так как более мощные чипы становятся доступны за ту же минимальную цену.
Другая сфера использования языка ассемблера - системный BIOS компьютера. Этот низкоуровневый код используется для инициализации и тестирования системного оборудования перед загрузкой OS и хранится в ROM. После прохождения определённого уровня инициализации оборудования, может использоваться и код написанный на языка более высокого уровня, но почти всегда код, исполняемый сразу после включения написан на языке ассемблера. Это обычно по причине того, что системный RAM может быть ещё не инициализирован, а ассемблер может исполняться без явного использования памяти, особенно в форме стека.
Язык ассемблера также очень полезен в обратном инжиниринге, поскольку много программ распространяются только в форме машинного кода, а машинный код обычно легко перевести в язык ассемблера и тщательно изучать в этой форме, но очень трудно перевести в язык более высокого уровня. Такие утилиты, как Interactive Disassembler для такой цели широко используют диассемблирование.