- [Введение в низкоуровневое программирование
- Как выполняется программа?
- Что такое языки высокого уровня?
- Примеры языков программирования высокого уровня
- Примеры языков программирования низкого уровня
- Являются ли C и C++ языками высокого уровня?
- Что такое Ассамблея и как она работает?
- Генерация кода низкого уровня
- Заключение
[Введение в низкоуровневое программирование
Низкоуровневое программирование — это тип программирования, приближенный к аппаратному, то есть использующий языки программирования, очень близкие к машинному языку. Программирование на низкоуровневых языках позволяет полностью контролировать ресурсы машины; вы можете напрямую обращаться к регистрам, памяти и кэшу, а также выделять пространство в памяти.
Как выполняется программа?
Сначала код компилируется из языка высокого уровня в язык низкого уровня. После этого этот низкоуровневый код должен быть собран и скомпонован.
Учитывая эти шаги, код может быть выполнен, но выполнение также имеет некоторые шаги, а именно:
- Получить
- Декодировать
- Выполнить
- Переместите указатель на следующую инструкцию
- Вернитесь к первому шагу
Что такое языки высокого уровня?
Высокоуровневые языки программирования — это языки, которые, грубо говоря, ближе к человеческому языку, чем к машинному. Как правило, большинство терминов в них написано на английском языке и не требует прямого манипулирования памятью и регистрами.
Примеры языков программирования высокого уровня
Примеры языков программирования низкого уровня
Являются ли C и C++ языками высокого уровня?
Многие люди приходят в замешательство, когда слышат, что C и C++ — языки высокого уровня, это происходит потому, что эти языки считаются «сложными» и «трудными». Если рассматривать формальное определение, то да, они считаются языками высокого уровня, потому что они гораздо ближе к английскому языку, чем к ассемблеру, и не требуют прямого манипулирования памятью и регистрами; КАК БЫ то ни было, это возможно.
Однако если вы сравните, например, C или C++ с Python или JavaScript, то разница будет огромной настолько, что их можно будет считать языками низкого уровня. Однако если сравнить эти же языки с Ассемблером или двоичным кодом, то они считаются языками высокого уровня.
Официально эти языки относятся к языкам высокого уровня, но из-за этого вопроса перспективы я предпочитаю считать их языками промежуточного уровня.
Что такое Ассамблея и как она работает?
Ассемблер — это язык ассемблера, он классифицируется как язык низкого уровня. Ассемблер не компилируется и не интерпретируется, он ассемблируется. Когда мы говорим, что язык является «ассемблером» или «собранным», это означает, что для каждого слова в этом языке существует точный бинар, идентичный, поэтому нет перевода, только ассоциация между пневмоникой (словами) и соответствующим бинаром.
Ассемблер — это язык, однако он имеет множество разновидностей, поскольку, будучи языком, чрезвычайно близким к машине, он зависит от архитектуры компьютера. Существует множество типов Ассемблера для различных архитектур, 16 бит, 32 бит, 64 бит, Intel, ARM и т.д. Вот почему мы называем языки низкого уровня «непортативными».
Программа, отвечающая за сборку ассемблерного кода в двоичный, называется Ассемблером, и, как уже говорилось, каждый Ассемблер отличается в зависимости от архитектуры машины.
Генерация кода низкого уровня
Рассмотрим сравнительный пример низкоуровневого кода (Ассемблер) и кода на языке C. Очень простой алгоритм — пузырьковая сортировка, широко используемая для сортировки массивов. Код на языке Си для этого алгоритма выглядит следующим образом:
#include void print_array(int arr[], int arr_length) for (int k = 0; k arr_length; k++) printf("%d, ", arr[k]); > > void bubblesort(int arr[], int arr_length) int swap; for (int i = 0; i arr_length; i++) printf("n[%d] ", i+1); for (int j = 0; j arr_length; j++) if (arr[j] > arr[j+1]) swap = arr[j]; arr[j] = arr[j+1]; arr[j+1] = swap; > > print_array(arr, arr_length); > printf("n"); > int main() int arr[25] = -223, -12, -1000, -90, -3, 40, 55, 11, 32, 67, 5, 74, 89, 38, 66, 27, 36, 79, 99, 2, 0, 1, 100, 282, 370>; int arr_length = sizeof arr / sizeof *arr; bubblesort(arr, arr_length); return 0; >
Этот код C для многих уже не считается простым, но он по-прежнему очень нагляден и ближе к английскому, чем к машинному языку. Теперь выполним следующую команду:
gcc bubble_sort.c -o bubble_sort.o && objdump -S --disassemble bubble_sort.o > bubble_sort.asm
Приведенная выше команда компилирует C-код и генерирует исполняемый файл в машинном коде, вторая часть команды генерирует ассемблерный код из исполняемого файла. Откройте файл bubble_sort.asm и посмотрите, что произошло. Простой код алгоритма пузырьковой сортировки на Ассемблере содержит более 300 строк, а код на Си — всего 30 строк.
Заключение
Теперь вы знаете немного больше о низкоуровневом программировании, вы можете продолжить обучение в этой области или вернуться к языкам высокого уровня. Программирование на низком уровне гораздо сложнее и скучнее, чем программирование на высоком уровне, однако важно знать хотя бы основы, это позволит вам лучше понять, как работают компьютеры, компиляторы, интерпретаторы и различные архитектуры.