Выделение памяти (ассемблер под Линукс)
До переезда блога на новый движок я писал аналог команды tee на ассемблере. Тогда передо мной стояла проблема выделения памяти — в команду может быть передано несколько имён файлов, я не знаю сколько, их нужно будет открыть, а под открытые файлы нужно место.
Программу я закончил,
Как я уже упоминал, есть два способа выделить память под Линуксом — sys_brk и sys_mmap. Второй способ используется, когда памяти надо выделить много, очевидно это не мой случай, поэтому я использовал вызов sys_brk. Этот вызов двигает границу так называемой «кучи» (Runtime heap на картинке) вверх (к старшим адресам) и в получившемся пространстве можно
Код выглядит так:
mov rax, 12 ; sys_brk
xor rdi, rdi ; в rdi записываем ноль (получить текущий адрес)
syscall
cmp rax, 0
jl memory_error ; обработка выделения памяти
; в rax у нас указатель на текущую границу кучи
; новый адрес нужно записать в регистр rdi
mov rcx, size ; количество хидеров файлов, которые надо хранить
lea rdi, [rcx * 8 + rax] ; каждый хидер занимает восемь байт
mov rax, 12 ; sys_brk
syscallТо есть получаем старый адрес, прибавляем сколько надо, устанавливаем новый адрес. Все менеджеры памяти Линукса (включая известнейший вызов malloc с Си), используют один из этих двух вызовов или их комбинацию.
Сложнейшие из них умеют сочетать различные стратегии выделения и управлять памятью внутри уже выделенных кусков, разбивая память на более мелкие регионы под нужды приложения, а так же бороться с фрагментацией, которая неизбежно появляется в процессе.
Правда выигрывает
Отличную игру подсмотрел у Сэма — в ней одиннадцать уровней, в каждом на экране функция, которая должна вернуть «true», аргумент функции вы пишете сами, причём его длина должна быть минимальной. На каждом уровне указан абсолютный минимум.
Мне пока не удалось победить уровнь №6 (30 символов против 22) и 10 (29 против 27), не хватило свободного времени на работе, чтобы додумать, попробую в выходные.
Решил все. №10 — утром, №6 — уже к полуночи. С номером шесть возился очень долго — пришлось через рефлексию отобрать все функции, которые не имеют обязательных параметров, просмотреть большинство и отбросить кучу интересных, но тупиковых идей.