Ассемблер основы: Основы Ассемблера

Содержание

Ассемблер для начинающих / Хабр

В любом деле главное — начать. Или вот еще хорошая поговорка: «Начало — половина дела». Но иногда даже не знаешь как подступиться к интересующему вопросу. В связи с тем, что воспоминания мои еще свежи, спешу поделиться своими соображениями с интересующимися.

Скажу сразу, что лично я ассемблирую не под PC, а под микроконтроллеры. Но это не имеет большого значения, ибо (в отличие от микроконтроллеров AVR) система команд данных микроконтроллеров с PC крайне схожа. Да и, собственно говоря, ассемблер он и в Африке ассемблер.

Конечно, я не ставлю своей целью описать в этой статье всё необходимое от начала и до конца. Благо, по ассемблеру написано уже невообразимое число литературы. И да, мой опыт может отличаться от опыта других программистов, но я считаю не лишним изложить основную концепцию этого вопроса в моем понимании.

Для начала успокою любознательных новобранцев: ассемблер — это совсем не сложно, вопреки стереотипному мнению.

Просто он ближе к «земле», то бишь к архитектуре. На самом деле, он очень прост, если ухватить основную идею. В отличие от языков высокого уровня и разнообразных специализированных платформ для программирования (под всем перечисленным я понимаю всякое вроде C++, MatLAB и прочих подобных штук, где требуются программерские навыки), команд тут раз-два и обчелся. По началу даже, когда мне нужно было посчитать двойной интеграл, эта задача вызывала лишь недоумение: как при помощи такого скудного количества операций можно совершить подобную процедуру? Ведь образно говоря, на ассемблере можно разве что складывать, вычитать и сдвигать числа. Но с помощью ассемблера можно совершать сколь угодно сложные операции, а код будет выходить крайне лёгкий. Вот даже для примера, нужно вам зажечь светодиод, который подключен, например, к нулевому контакту порта номер 2, вы просто пишете:
bset P2.0
И, как говорится, никаких проблем. Нужно включить сразу штуки четыре, подключенных последовательно? Да запросто:
mov P2, #000fh
Да, тут я подразумеваю, что начинающий боец уже знаком хотя бы со системами счисления. Ну хотя бы с десятичной. 😉

Итак, для достижения успеха в деле ассемблирования, следует разбираться в архитектуре (в моем случае) микроконтроллера. Это раз.

Кстати, одно из больных мест в познании архитектуры — это организация памяти. Тут на Хабре я видела соответствующую статью: habrahabr.ru/blogs/programming/128991. Еще могу упомянуть ключевые болевые точки: прерывания. Штука не сложная, но по началу (почему-то) тяжелая для восприятия.

Если перед вами стоит сложная задача и вы даже не знаете как по началу к ней подступиться, лучше всего написать алгоритм. Это воистину спасает. А по началу, даже если программа совершенно не сложная, лучше всё же начать с алгоритма, ибо этот процесс помогает разложить всё в голове по местам. Возвращаясь к примеру с вычислением двойного интеграла по экспериментальным данным, обдумывала алгоритм я весь день, но зато потом программку по нему написала всего за 20 минут. Плюс алгоритм будет полезен при дальнейшей модернизации и/или эксплуатации программы, а то ассемблерный код, временами, если и будет понятен построчно, то чтобы разобраться в чем же общая идея, придется немало потрудиться.

Итак, второй ключ к успеху — подробно написанный и хорошо продуманный алгоритм. Настоятельно рекомендую не садиться сразу за аппарат и писать программу. Ничего дельного вы с ходу не напишете. Это два.

Собственно, хотелось бы как Фандорин написать: «Это т-т-три»… Но, боюсь, на этом пока можно остановиться. Хотя хотелось бы добавить еще несколько рекомендаций и пряников.

Подводя итог моему несколько сумбурному монологу, ключевые моменты в программировании на ассемблере — это знание архитектуры и связное построение мыслей. Конечно, не обязательно сразу с головой кидаться в штудировании литературы с описанием внутренностей того же PC, но общее представление (повторюсь, хотя бы для начала) будет очень нужно.

А теперь обещанные пряники! Вот я тут распинаюсь о каком-то непонятном ассемблере, а что же в нем, собственно говоря, хорошего? Да много всего! Во-первых, конечно, не нужно запоминать много команд, используемых библиотек и прочей сопутствующей дребедени. Всего парочка команд и, считайте, вы во всеоружии. Во-вторых, в связи с крайней близостью к машинным кодам, вы можете делать практически всё, что душе угодно (в отличие от тех же языков высокого уровня)! В-третьих, ассемблерный код, по причине максимальной лаконичности в формулировках, выполняется крайне быстро.

В общем, сплошные плюсы. На этой оптимистической ноте разрешите откланяться.

Основы языка ассемблера — презентация онлайн

1. Основы языка ассемблера

2. План лекции

Основные понятия
• Ассемблер – транслятор исходного кода
программы, на языке ассемблера в
машинный код
• Дизассемблер
• Машинный код
• Машинное слово

3. Основные понятия

Фон-неймановская архитектура
Принцип однородности памяти
Принцип адресности
Принцип программного управления
Принцип двоичного кодирования

4. Фон-неймановская архитектура

Архитектура компьютера
• ЦПУ
• Оперативная память (ОЗУ)
• Северный мост
• Южный мост
• BIOS (ППЗУ)
• Периферийные устройства
• Системная шина
(адреса, данных, управления)

5.

Архитектура компьютераУстройство персонального
компьютера

6. Устройство персонального компьютера

Процессор
• Регистры
• АЛУ
RSB
Кэш-память (кода и данных)
TLB
L1, L2, L3

7. Процессор

Материнская плата

8. Материнская плата

Режимы работы процессора
Реальный режим (real mode)
Защищенный режим (protected mode)
Режим виртуального 8086
Режим системного управления (SMM)

9. Режимы работы процессора

Кольца защиты (Ring)
• Ring -2 (Режим системного управления, System
Management Mode)
• Ring -1 (режим гипервизора, Hypervisor mode)
• Ring 0 (режим ядра, супервизора – ring mode,
supervisor mode)
• Ring 1
• Ring 2
• Ring 3
(режим пользователя,
user mode)

10. Кольца защиты (Ring)

Реальный режим
• Физические адреса от 0 до 1 Мб
• Макс размер сегмента 64 Кб (16 разр)
• Использование сегментной адресации

11. Реальный режим

Регистры процессора
• Регистры общего назначения (EAX, EBX, ECX,
EDX)
• Адресные регистры (ESI, EDI, EBP)
• Управляющие регистры (ESP, EIP, EFLAGS)
• Сегментные регистры (CS, DS, SS, ES, GS, FS)
• Регистры управления памятью (GDTR, LDTR,
IDTR)
• Регистры управления (CR0-CR4)
• Отладочные регистры (DR0-DR7)
• Машинно-зависимые регистры (MSR)

12.

Типы данныхРегистры общего назначения

13. Регистры процессора

Адресные регистры
• ESI – индекса источника
• EDI — регистр индекса результата
• EBP — регистр указатель стековой базы

14. Регистры общего назначения

Регистры состояния
• ESP — Указатель на вершину стека
• EIP — Cчетчик команд
• EFLAGS — Регистр флагов

15. Адресные регистры

Регистры управления
CR0
CR1
CR2
CR3
CR4

16. Регистры состояния

Регистр EFLAGS / FLAGS

17. Регистры управления

Сегментные регистры
16-битные регистры для хранения селекторов
сегмента
• CS – сегмент кода
• DS – сегмент данных
• SS – сегмент стека
Дополнительные сегменты:
• ES
• GS
• FS

18. Регистр EFLAGS / FLAGS

Системные регистры
GDTR
LDTR
IDTR
TR

19. Сегментные регистры

Регистры x64

20. Системные регистры

Порты ввода/вывода (I/O Ports)
Используются для взаимодействия с
утройствами
• IN eax, port_num (DX) – чтение из порта
• OUT port_num(DX), eax- запись в порт

21.

Регистры x64MSR–регистры
(Model-Specific Registers)
• Зависят от модели процессора
• Вызываются только из режима ядра
• RDMSR – чтение, ECX –номер MSR
Результат — EDX:EAX
• WRMSR
Примеры:
RDTSC – читает MSR-регистр IA32_TIME_STAMP_COUNTER (0x10)
SYSENTER/SYSEXIT, SYSCALL/SYSRET

22. Порты ввода/вывода (I/O Ports)

Расширения инструкций процессора
Работа с аудио- и видео-данными
• FPU / NPX
• MMX
• MMX Extended
• 3dNow!
• 3dNow! Extended
• SSE
• SSE2
• SSE3
• SSSE3
• SSE4
• AVX

23. MSR–регистры (Model-Specific Registers)

Стек
ESP – хранит адрес вершины стека
EBP – хранит адрес начала стекового фрейма
SS – регистр, хранит селектор стека
Стек – растет от старших адресов к младшим

24. Расширения инструкций процессора

Языки ассемблера
Команды языка соответствуют инструкциям
процессора
Синтаксисы:
• Intel
• AT&T
Ассемблеры:
• MASM
• NASM
• FASM
• TASM
• GAS
Типы команд
Арифметические
Логические
Передачи данных
Перехода
Пропуска
Вызова подпрограммы
Возврата из подпрограммы
Смешанные

26.

Языки ассемблераФормат команды
• Поле префиксов
– Замена сегмента
– Изменение размерности адреса
– Изменение размерности операнда
– Необходимость повторения команды
• Поле кода операции
• Поле операндов (от 0 до 2)

27. Типы команд

Пример
• Префикс
• Команда
• Операнды

28. Формат команды

Типы операндов
Байт
Слово
Десятичный операнд
Разряд
Число
Составной операнд

29. Пример

Способы адресации [1]
• Регистровая адресация
mov ax, bx
• Непосредственная адресация
mov ax, 2
• Прямая адресация
mov ax, es:0001
mov ax, ds:word_var (ds – по умолчанию)
• Косвенная адресация
mov ax, [bx]
• Адресация по базе со сдвигом
mov ax, [bx+2]
mov eax, [ebp]+2 / mov eax, 2[ebp]

30. Типы операндов

Способы адресации [2]
• Косвенная адресация с масштабированием
mov eax, [esi*3]+2
• Адресация по базе с индексированием
mov ax, [bx+si+2]
mov ax, [bx][si]+2
• Адресация по базе с индексированием и
масштабированием
• mov edx, es:[eax+ecx*2+4]

31.

Способы адресации [1]Порядок байт
• big-endian, от старшего к младшему (SPARC,
TCP/IP)
• little-endian, от младшего к старшему (x86)
• bi-endian – переключаемый порядок
• middle-endian – смешанный порядок

32. Способы адресации [2]

Формат хранения переменных

33. Порядок байт

ASCII

34. Формат хранения переменных

Команды пересылки
1. MOV DST,SRC; переслать (SRC) в (DST).
2. PUSH RP; поместить на вершину стека содержимое пары
регистров RP (например push bx).
3. POP RP; снять с вершины стека два байта и поместить в пару RP
(например pop ax).
4. XCHG DST, SRC; поменять местами содержимое (DST) и (SRC). Оба
операнда не могут быть одновременно содержимым ячеек
памяти.
5. XLAT SRC; извлечь из таблицы с начальным адресом SRC байт
данных имеющий номер от начала таблицы = (AL), и поместить его
в AL. Адрес SRC должен находиться в регистре BX. Другой вариант:
XLATB.
6. LEA RP,M; загрузить в регистр RP эффективный адрес (смещение)
ячейки памяти с символическим адресом M.
Арифметические команды
1. ADD DST, SRC; сложить содержимое SRC и DST и результат
переслать в DST.
add al, [mem_byte]; mem_byte однобайтовая ячейка памяти
add [mem_word], dx; mem_word двухбайтовая ячейка памяти
add ch,10001010b;
2. INC DST; увеличить (DST) на 1 (инкремент (DST)).
3. SUB DST, SRC; вычесть (SRC) из (DST) и результат поместить в
DST.
4. DEC DST; декремент (DST).
5. CMP DST, SRC; сравнить содержимое DST и SRC. Эта команда
выполняет вычитание (SRC) из (DST) но разность не помещает в DST
и по результату операции воздействует на флаги.

36. Команды пересылки

Логические команды и команды
сдвига
1. AND DST, SRC; поразрядное логическое «И».
2. OR DST, SRC; поразрядное логическое «ИЛИ».
4. NOT DST; инверсия всех битов приемника.
5. TEST DST, SRC; выполняет операцию AND над операндами, но
воздействует только на флаги и не изменяет самих операндов.
6. SHR DST, CNT; логический сдвиг вправо, освобождающиеся
слева биты заполняются нулем, крайний правый бит
выталкивается во флаг CF. Операнд DST может быть ячейкой
7. SHL DST, CNT; логический сдвиг влево.
8. RLC DST, CNT; циклический сдвиг влево через перенос
9. RRC DST, CNT;циклический сдвиг вправо через перенос
10. ROR DST, CNT;циклический сдвиг влево
11. ROL DST, CNT;циклический сдвиг вправо

37. Арифметические команды

Использование сдвигов
• Умножение
• Деление
• Работа с 64 переменными

38. Логические команды и команды сдвига

Команды передачи управления
1. CALL SUBR; вызов подпрограммы с адресом SUBR;
2. RET; возврат из подпрограммы к оператору следующему непосредственно за
CALL, то есть в приведенном выше примере к MOV ..
3. JMP NAME; безусловный переход к команде с символическим адресом NAME.
4. JA NAME или JNBE NAME; условный переход, если, например, в результате
сравнения CMP DST, SRC приемник по абсолютной величине больше источника,
то перейти к метке name.
5. JB NAME или JNAE NAME; условный переход, если, например, в результате
сравнения CMP DST, SRC приемник по абсолютной величине меньше источника,
то перейти к метке name (команды п4 и п5 выполняются по результатам
выполнения операций над беззнаковыми числами).
6. JZ NAME или JE NAME; перейти, если результат операции влияющей на флаг
нуля — нулевой (переход по «нулю»).
7. JNZ NAME или JNE NAME; переход по «не нулю». (команды п6 и п7
выполняются по результатам выполнения операций над числами cо знаком).

39. Использование сдвигов

Основные команды
CALL / RET
JMP
PUSH / POP
JE / JNE
XOR
MOV
CMP
NOP

40. Команды передачи управления

Команды условного перехода

41. 2.6 Instruction types Data transfer instructions

Безусловный переход (JMP)

42. 2.6 Instruction types Arithmetic instructions

NOP
• No OPeration
• 0x90

43. 2.6 Instruction types Bit manipulation instructions

Пример
E8 – опкод call
8E FE FF FF – аргумент, little-endian
ff ff fe 8e = -0x172 (-370)
check_pass = 0x40126D – 0x172 + 5 (размер
инструкции) = 0x401100

44. 2.6 Instruction types String instructions

Управляющие структуры: IF-ELSE
• if <A!=B> then <C=3> else <C=5>
mov eax, A
cmp eax, B
jne then
mov C, 5
jmp end
then:
mov C, 3
end:

45.

Основные командыУправляющие структуры:switch-case
mov eax, I
shl bx, 1
jmp cs:jump_table[bx]
jump_table dw foo0, foo1, foo2
foo0: call case0
jmp endcase
foo1:
call case1
jmp endcase
foo2:
call case2
jmp endcase

46. Команды условного перехода

Передача параметров: механизм
По значению
По ссылке
По возвращаемому значению
По результату
По имени
Отложенным вычислением

47. Безусловный переход (JMP)

Передача параметров: место
хранения
В регистрах
В глобальных переменных
В стеке
В потоке кода
В блоке параметров
Процесс компиляции

49. Пример

Адресное пространство процесса:
Windows

50. Опкоды инструкций

Адресное пространство процесса:
Linux

51. Основные инструкции

Структура стека

52. Управляющие структуры: IF-ELSE

Стековый кадр
• Вызов функции
call = { “push eip”, jmp func }
ret = { “pop eip”, “jmp eip” }
• Пролог функции
push ebp
mov ebp, esp
• Эпилог функции
mov esp, ebp
pop ebp
enter / leave

53.

Управляющие структуры:switch-caseСтековый кадр

54. Передача параметров: механизм

Стековый кадр: пример

55. Передача параметров: место хранения

Соглашения о вызове
(calling convention)
cdecl
Вызывающая
функция
Параметры помещаются в стек в обратном порядке
(справа налево)
clrcall
Н/Д
Параметры загружаются в стек выражений CLR попорядку (слева направо).
stdcall /
winapi
Вызываемая
функция
Параметры помещаются в стек в обратном порядке
(справа налево)
fastcall
Вызываемая
функция
Хранятся в регистрах, затем помещаются в стек
(RCX, RDX, R8, R9)
thiscall
Вызываемая
Помещаются в стек; указатель this хранится в регистре ECX
функция
vectorcall
Вызываемая
функция
Хранятся в регистрах, затем помещаются в стек в
обратном порядке (справа налево)

56. Структура исполняемого файла

Thread Environment Block (TEB)
Wow64 процессы в Windows имеют два PEB и
два TEB. TEB создается функцией
MmCreateTeb, PEB создается функцией
MmCreatePeb
TEB — структура которая используется для
хранения информации о потоках в текущем
процессе, каждый поток имеет свой TEB.

57. Процесс компиляции

Thread Environment Block (TEB)
• [TEB+0] Указатель на первый SEH на стэке.
• [TEB+4] Указатель на конец области памяти,
выделенных на стеке.
• [TEB+8] Указатель на начало области памяти
выделенных на стеке, для контроля исключений
переполнения стека.
• [TEB+18] Адрес текущей TEB.
• [TEB+30] Адрес PEB.

58. Средства отладки

PEB
PEB содержит все параметры пользовательского
процесса:
• местоположение главной выполняемой
программы
• указатель/загрузчик данных (может
использоваться, для перечисления всех
dll/модулей, которые были/могут быть
загруженными в процесс)
• указатель на информацию о динамической
памяти (heap — куче)

59. Средства разработки

PEB
• Находится в TIB[0x30], fs:[0x30]
Для x64:

60.

Адресное пространство процесса: Windows

61. Адресное пространство процесса: Linux

Литература
• Зубков С.В. Assembler для DOS, Windows и
Unix
• Касперски К., Рокко Е. Искусство
дизассемблирования
• Юричев Д. Reverse Engineering для
начинающих

Сборка

. Часть 1. Изучаем сборку! | Программа инженерного образования (EngEd)

Вначале были перфокарты. В конце концов, кому-то пришла в голову блестящая идея сделать компьютер программируемым. Просто введите шестнадцатеричный код и запустите его. Проблема в том, что очень сложно посмотреть на шестнадцатеричный код и понять, что он делает.

Войдите в сборку

Сборка по-прежнему очень проста, и каждая деталь того, как компьютер выполняет свою задачу, должна быть указана. Разница в том, что ассемблер делает эти инструкции удобочитаемыми для человека.

Следующим шагом выше будет использование языка программирования, такого как C, Java или Typescript. Это, безусловно, проще, чем использование ассемблера, но и по сей день все еще существуют задачи, которые не могут решить языки системного программирования. Вот некоторые примеры:

  • Агрессивная оптимизация (C и Rust уже очень быстры, но не идеальны)
  • Сборка
  • упрощает расчет точного времени выполнения программы
  • Программы, которые должны работать напрямую с оборудованием, например драйверы
  • Загрузка операционной системы

Требования

К сожалению, сборка не одинакова для всех систем. Разным компьютерам для работы нужен разный код. Вот что вам нужно для этого урока:

  • Компьютер x86 (например, он не будет работать на Raspberry Pi)
  • 32-битная или 64-битная операционная система (предпочтительно Linux)
  • Ассемблер (NASM в Linux или MASM в Windows)
  • Опыт низкоуровневого программирования (C, C++, Rust и Go — хорошие языки для изучения)

Разделы

Исполняемые программы можно разделить на три раздела (вы можете использовать больше, но в этом руководстве мы будем придерживаться трех). Вот они:

  • текст — Этот раздел содержит фактические инструкции, которые будет выполнять ваш код.
  • bss — Здесь хранятся все глобальные переменные. Сюда помещается любая статическая переменная
    .
  • data — Этот раздел используется для постоянных глобальных переменных.

Разделы объявляются простым вводом section .name . Например, раздел данных будет объявлен с использованием:

 section .data
 

Переменные

Переменные, как мы уже говорили, хранятся в секции bss . Мы не можем просто объявить их значение, как в обычном языке. Вместо этого мы можем точно сказать ассемблеру, сколько байтов нужно зарезервировать.

 раздел .bss
вар резб 4
 

Это создает переменную с именем var и резервирует для него четыре байта. Если бы мы хотели зарезервировать два байта, мы бы поставили в конце 2 . Чтобы получить доступ к значению var , мы заключаем его имя в квадратные скобки: [var] .

Операторы

Операторы на ассемблере имеют следующий формат:

 Мнемоника [операнды] [;комментарий]
 

Давайте разберемся.

Мнемоника является фактической для запуска. Некоторые операции принимают один параметр. Некоторые берут несколько. В ассемблере много инструкций, но мы остановимся на следующих.

Мнемоника Операнд 1 Операнд 2 Описание
мов местоположение значение Устанавливает операнд 1 в операнд 2
вкл. местоположение Добавляет единицу к местоположению
дек местоположение Вычитает единицу из местоположения
добавить местоположение значение Добавляет значение в ячейку
суб местоположение значение Вычитает значение из местоположения
джмп этикетка Переход к части программы
смп значение1 значение2 Сравнивает два значения
и этикетка Переход к части программы, если два значения равны
целое число прерывание Создает программное прерывание

Комментарии в ассемблере — это все, что идет после точки с запятой ( ; ). Вы уже должны быть знакомы с тем, что они делают — они помогают объяснить ваш код другим людям, которые его читают.

Подробнее об этих инструкциях мы поговорим позже. А пока вот несколько примеров:

 mov [var], 5 ; переменная = 5
дек [вар] ; вар --
добавить [вар], 3 ; переменная += 3
; Посмотрим, сможешь ли ты придумать свое!
 

Метки

Рассмотрим следующий код C

 void main() {
интервал переменная = 0;
в то время как (1) {
вар++;
}
}
 

Этот код использует цикл while для бесконечного повторения. Однако в сборке нет таких простых циклов. В сборке вам нужно сделать что-то более похожее на следующее

 void main() {
    интервал переменная = 0;
    петля:
        вар++;
        перейти в петлю;
}
 

Простите, если вы не знаете, что это допустимый код C. (Это довольно плохая практика.) Но в ассемблере это все, что у вас есть. Попробуем перевести это на Ассемблер.

Давайте настроим нашу программу. Нам нужен раздел text для хранения инструкций программы и раздел bss

для хранения нашей переменной.

 раздел .текст
раздел .bss
 

Мы еще не говорили об этом, но нам нужно сказать программе, с чего начать в нашей программе. Мы создадим метку с именем _start и начнем с нее. Мы можем указать компоновщику, с чего начать, используя global _start .

 раздел .текст
глобальный _start
_начинать:
 

Теперь нам нужно создать нашу переменную. Мы будем использовать 32-битное целое число, для которого требуется четыре байта.

 раздел .bss
вар резб 4
 

Теперь нам нужно инициализировать переменную. Именно для этого и предназначена инструкция mov .

 _старт:
mov двойное слово [вар], 0 ; Здесь у нас есть «dword», потому что это 32-битная операция.
 

Теперь нам нужен цикл. Мы создадим метку, назовем ее loop и безоговорочно перейдем к ней.

 _старт:
mov двойное слово [вар], 0
петля:
джмп петля
 

Наконец, нам нужно увеличить нашу переменную.

 раздел .текст
глобальный _start
_начинать:
mov двойное слово [вар], 0
петля:
inc двойное слово [var]
джмп петля
раздел .bss
вар резб 4
 

Вероятно, я должен упомянуть, как вы можете запустить это. Предположим, что файл называется incrementor.asm и вы используете NASM:

 nasm -f elf incrementor.asm
ld -m elf_i386 -s -o инкрементатор incrementor.o
./инкрементор
 

Регистры

Знаете ли вы, что ваш процессор имеет встроенную память? 😲 Регистры — это память, встроенная в ЦП. Из-за этого можно молниеносно использовать регистры вместо хранения значений в оперативной памяти.

Так почему бы нам просто не использовать регистры для всего? Вот в чем проблема. У нас не так много регистров. В этом уроке будут использоваться только четыре. Это станет проблемой позже, но пока нам нужно меньше четырех переменных, это должно работать для нас. Мы будем использовать четыре: eax , ebx , ecx и edx . Мы будем использовать эти четыре, потому что их очень легко запомнить. Все они имеют формат e_x . Каждый из этих регистров может хранить одно 32-битное число.

Мы можем переписать наш бесконечный цикл, чтобы использовать раздел регистра

 .text
глобальный _start
_начинать:
движение акс, 0
петля:
вкл.
джмп петля
 

Теперь нам вообще не нужна оперативная память!… кроме как для хранения фактической программы в памяти. Нам также не нужно указывать размер операции. Размер eax всегда равен четырем байтам.

Заключение

На этом основы сборки закончены. Прочтите мою следующую статью о том, как написать настоящую программу с помощью ассемблера.

Основы языка ассемблера | Cybrary

Язык ассемблера — это язык программирования низкого уровня, предназначенный для прямого взаимодействия с аппаратным обеспечением машины. Языки компьютерного программирования могут быть языками высокого или низкого уровня. Основное отличие состоит в том, что язык программирования высокого уровня более удобен для программиста, а это означает, что его гораздо легче понять, чем язык низкого уровня. Однако он также менее эффективен с точки зрения использования памяти, поскольку работает на более высоком уровне абстракции. Он не предназначен для прямого взаимодействия с аппаратным обеспечением компьютера и требует компилятора или интерпретатора для перевода.

Для сравнения, язык ассемблера более удобен для машин; его труднее понять людям, но он предлагает больше контроля, позволяя более эффективно использовать память. Для перевода нужен ассемблер, а не компилятор или интерпретатор. Сегодня языки программирования высокого уровня пользуются гораздо большей популярностью. Тем не менее, кибербезопасность — это несколько областей, где изучение языка низкого уровня, такого как язык ассемблера, по-прежнему чрезвычайно ценно. В первую очередь это касается анализа вредоносных программ. Именно здесь специалисты по кибербезопасности берут образцы вредоносных программ и разбивают их на язык ассемблера, чтобы определить, что делает вредоносное ПО, и, надеюсь, как вы можете его остановить.

Почему язык ассемблера важен для анализа вредоносных программ?

Всякий раз, когда создается вредоносное ПО, автор обычно использует процесс, называемый запутыванием, чтобы другие люди не могли прочитать код вредоносного ПО и понять, как оно работает. При обнаружении образца вредоносного ПО аналитики используют ollydbg или IDA pro, чтобы разбить программу на компоненты на языке ассемблера. С этого момента вы поймете, что делает программа и, в конце концов, как вы можете остановить ее распространение или обнаружить ее на машине. Это делается путем определения индикаторы компрометации (IOC), которые являются важными способами обнаружения вируса, уникального для этой программы. Примерами IOC являются имена файлов, IP-адреса, к которым обращается программа, каталоги файлов, которые она сама сохраняет и т. д.

Начните с онлайн-курса «Ассемблирование» сегодня >>

Как работает язык ассемблера?

Ранее было заявлено, что языки низкого уровня предоставляют мало абстракций или вообще не предоставляют их вообще. Это означает абстракцию от процессора. Когда вы пишете что-то на языке ассемблера, вы отдаете команды непосредственно процессору компьютера. Современные языки ассемблера обычно кодируют программы на ассемблере, которые преобразуются в машинный код, который является единственным типом языка программирования, который машина понимает без обработки. Вот пример того, как выглядит машинный код в двоичной форме:

Источник @ secjuice

Давайте посмотрим на некоторые компоненты языка ассемблера и на то, как они преобразуются в машинный код.

Что такое мнемоника?

Мнемоника — это имя, присвоенное машинной функции или аббревиатуре операции на языке ассемблера . Каждая мнемоника представляет машинную инструкцию на ассемблере. В приведенном выше примере add является примером одной из этих машинных инструкций. Некоторые другие примеры включают mul, lea, CMP, и и .

Что такое регистры?

Регистры в ассемблере можно сравнить с глобальными переменными, используемыми в языках программирования более высокого уровня, таких как Python или C . Существует три основных типа регистров:

  • Общего назначения: Eax, Ebx, Esp, Ebp
  • Сегмент: CS, CD
  • Управление: EIP

Эти регистры могут хранить определенный объем данных и определенный тип данных. Например:

EAX — регистр-накопитель — используется для хранения операндов и данных результатов. Он может хранить 32 бита данных.

EBX- Базовый регистр — Указывает на данные. Может хранить 32 бита данных.

ECX — регистр счетчика — операции цикла. Может хранить 32 бита данных.

Что происходит с данными, которые не помещаются в регистры?

В языке ассемблера любые данные, которые не помещаются в регистры, хранятся в памяти компьютера. Это происходит потому, что регистры позволяют наиболее быстро извлекать данные. Следовательно, вы хотите хранить как можно больше данных в регистрах и хранить только то, что осталось в памяти, где скорость извлечения будет медленнее. Ниже приведена диаграмма, изображающая иерархию памяти компьютера:

Источник @ secjuice

Как видите, самое быстрое место для хранения находится вверху, но оно также и самое маленькое, когда дело доходит до емкости. Размер резко увеличивается, продвигаясь вниз по иерархии, но и становится медленнее.

Обычно данные хранятся в памяти в двух типах данных: с прямым порядком байтов или с прямым порядком байтов. Хранилище данных с прямым порядком байтов обычно используется, когда основное внимание уделяется скорости обработки, а не количеству потребляемой мощности, что отлично подходит для ноутбуков и компьютеров и обычно используется для процессов Intel. Пока с прямым порядком байтов обычно используется в процессорах ARM, используемых для мобильных устройств, и отдает приоритет энергоэффективности.

Как выучить язык ассемблера

К сожалению, у языка ассемблера не так много ресурсов для изучения, как у языков программирования высокого уровня. Это просто потому, что большая часть программирования выполняется на языках более высокого уровня, поэтому нет большой потребности в изучении ассемблера за пределами узкоспециализированных специальностей. Если вы заинтересованы в изучении программирования на ассемблере, есть несколько хороших вариантов, в том числе Udemy, tutorialspoint и Курс программирования на языке ассемблера Cybrary . Как и в случае с большинством языков программирования, лучший способ учиться — это целенаправленная практика, чтение и изучение. Если вы заинтересованы в изучении ассемблера для обеспечения кибербезопасности, особенно в анализе вредоносных программ, вам следует ознакомиться с инструментами ollydbg и IDA pro . Это два ведущих инструмента для анализа вредоносных программ и преобразования файлов .exe в ассемблерный код. Вы можете загрузить эти инструменты по отдельности или загрузить дистрибутив Windows под названием 9.0260 Факел ВМ . Этот дистрибутив, ориентированный на безопасность, был создан FireEye и предназначен для реверсивных инженеров, аналитиков вредоносных программ, специалистов по реагированию на инциденты, судебных следователей и пентестеров. Что касается языка ассемблера, для начала я рекомендую X86, а затем ARM. Это два самых популярных языка ассемблера, X86 используется для процессоров Intel, а ARM в основном используется в мобильных устройствах, таких как сотовые телефоны.

Резюме

Язык ассемблера — это язык программирования низкого уровня, используемый для предоставления прямых инструкций процессорам устройства. Хотя языки низкого уровня обычно труднее изучать, они позволяют вам более эффективно использовать память, чем языки высокого уровня. Кроме того, это чрезвычайно полезно для анализа вредоносных программ, поскольку большинство файлов .exe можно преобразовать в язык ассемблера и изучить, чтобы найти индикаторы компрометации или другие средства защиты от этого штамма вредоносных программ.

Оставить комментарий

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *