Как стать автором
Обновить

Комментарии 26

Странная статья, какие-то вещи написаны будто бы для тех, кто никогда раньше не притрагивался к ассеблеру, в то же время о других важных вещах вроде архитектуры памяти и способах адресации ничего не сказано.
Проблема в том, что обучение ассемблеру — это либо курс на семерст (а то и два), либо книжка страниц так на 200-300.

Попытка ужать это до размеров одной статьи… рождает вот эту вот сову…

Очень бодренько! Спасибо!)

Только это, Крис Сойер вроде бы не на асме писал RollerCoaster Tycoon. На асме Transport Tycoon. И благодаря этому его получилось эпически отреверсить.
Разве CDECL для локальных подпрограмм популярен у программистов на ассемблере? С fastcall вроде возни гораздо меньше.
Видимо, для единообразия.

Увлекательно, может порекомендуете какие-либо курсы по ассемблеру?

Курс не курс, но вот, например, Авва недавно рекомендовал книжку:
В целом, адекватное введение в основы 64-битного ассемблера x86-систем для тех, кто знает какой-то язык программирования высшего уровня.
Статья должна называться «Руководство по ассемблеру x86 под Linux для начинающих»
Ожидал увидеть старый добрый асм под ДОС, а как глянул — волосы слегка зашевелились на затылке. Не знаю как сейчас, но когда я активно писал на асме в студенческие времена (конец 90х), асм под *nix это был нонсенс, ибо изначально *nix мультиплатформенный. К тому же еще смешали мух с котлетами — «Приведённый код не работает в Windows или Mac OS X» — винда это другая ОС, мак — другая платформа.

Возникла мысль — а можно ли Вашу программу переписать так, чтобы скомпилированный бинарник запускался под любой ОС на x86. Немного поразмыслив, пришел к выводу, что ваша — нет по двум причинам, а вообще любая (аналогичной сложности) — нет, по одной, самой главной, причине.
Домашнее задание — что за причины? :)
НЛО прилетело и опубликовало эту надпись здесь
Программа может посмотреть структуру своего бинарника, и на основе этого определить ОС.
Правда, с Windows будут проблемы, так как у него недокументированное и непостоянное API системных вызовов.
НЛО прилетело и опубликовало эту надпись здесь
Мак уже много лет, как не другая платформа. Вы, наверное, подумали о PowerPC?
И это еще называется для начинающих? Для начинающих в начале поясняю, терминологию, что означает тот или иной оператор, а тут сразу «на амбразуру»
Статья не имеет ничего общего с программированием на ассемблере кроме честного ассемблерного heloworld в первом абзаце… Все остальное — рассказ о том, как работает хреновый C компилятор, на базе анализа его ассемблерного листинга. Почему хреновый? — потому, что хороший не создает стековый кадр под локальные переменные, пока может хранить их в регистрах (а это довольно приличное число переменных).

Ассемблер это прежде всего контроль над тем, что происходит. У автора никакого контроля нет, у него паранойя — «сохраняй все, и даже то, что не используется и вообще не нужно», в реальном мире он забудет где нибудь стек восстановить после вызова и долго будет искать это место, потому что код будет падать естественно не на нем — а чуть попозже. А если повезет — сильно так чуть попозже…

Передача параметров через стек = возможность передачи слишком большого числа параметров. Возможность передачи слишком большого числа параметров = отсутствие контроля! Функции на ассемблере так не пишутся. Как правило регистров вполне достаточно, передачу же через стек используют для стыка с библиотеками на других языках, но не внутри ассемблерных программ. Все эти enter-leave конструкции — мусорные конструкции компиляторов. Если надо передать в процедуру единственный параметр 'число' — очевидно, что он передается через EAX! (Счетчик — через ECX, указатели — EBX-EDX-ESI-EDI...) итп…

Т.е. процедура _push будет выглядеть так:
;eax- сохраняемое в стеке значение.
_push:
push ebx
mov ebx, [stack_size]
mov [stack + 4*ebx], eax
inc dword [stack_size]
pop ebx
ret
т.е. Никаких стековых кадров и сохранения непонятно чего и непонятно зачем ни перед _push ни внутри него… Сохранили строго то, что испортили. Единственный параметр приняли в EAX. Ассемблер — это как то вот так.

Подобный стиль пригоден лишь для рождения мифов типа «пишу на асм но компилятор С все еще делает код компактнее и быстрее меня....»

_print_msg изменяет ebp и не сохраняет его. Вроде по вашим словам вызываемая функция обязана восстановить как было?

Нет. Enter-Leave конструкция сохраняет и восстанавливает ebp.
Заглянул, надеясь предаться ностальгии по старому доброму асму под ДОС, а тут… даже нотация не та. Кто бы мог подумать, что расово верные 04h или 80h превратятся в 0x04 и 0x80?

Честно дочитал до «Инструкция call — это по сути просто jmp (goto) в другой адрес памяти» и остановился.
А как же ret/retf?
Кто бы мог подумать, что расово верные 04h или 80h превратятся в 0x04 и 0x80?
NASM, кстати, 04h и 80h тоже понимает. Но вообще — непонятно чего хотели показать этой статьёй, это самая большая беда.

То есть, условно говоря, я не могу себе представить человека, который смог бы понять как писать на ассемблере исходя из подобного «рисования совы»… а человеку, который и так умеет — подобная статья ни к чему…
Мне статья понравилась. Я в принципе понимаю, что такое ассемблер, и как оно работает, но всегда было жалко времени в нем детально разбираться, тем более, еще и не понятно, под какую платформу разбираться.
Эта статья не то, чтобы глаза открыла, конечно, но в очень сжатой форме сообщила о некотороых деталях, которые, конечно, я бы узнал и сам… если бы захотел целенаправленно потратить время. А так — вот оно, готовое.
Комментарии не менее ценны, чем сама статья, тем, что дают еще дополнительные крохи. Типа передачи параметров в регистрах и т.п.
В общем, статья не для тех, кто хочет понять ассемблер (для них имхо лучше всего понять, как функционирует процессор, а там и ассебмлер будет в целом понятен), и не для тех, кто знает ассемблер и ищет новых знаний, а для таких как я… Для кого в принципе, понятно, но деталями никогда не интересовался… При этом, детали интересны )
Кто бы мог подумать, что расово верные 04h или 80h превратятся в 0x04 и 0x80?

Вам знакомы буквы AT&T в контексте ассемблера?

Честно дочитал до «Инструкция call — это по сути просто jmp (goto) в другой адрес памяти» и остановился.
А как же ret/retf?

Если вы посмотрите на контекст, то увидите, что речь идет о передаче параметров. Команда вызова процедуры в ЯВУ явно указывает передаваемые параметры, команда call в x86 — нет, только изменение control flow.

Если мне не изменяет память, то в контексте AT&T это бы выглядело как mov %bx,$100, нет?


А про контекст описания call, я увидел только про помещение в стек регистров и параметров, а где про адрес возврата? Почему я и напомнил про ret))

Если мне не изменяет память, то в контексте AT&T это бы выглядело как mov %bx,$100, нет?
Таки изменяет. Это всё-таки выглядело бы как mov $0x80, %ebx. А то у вас регистр в константу засовывается…
В контексте передачи параметров возврат — несущественная деталь. Там про параметры, а не control flow.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории