Pull to refresh

Comments 26

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

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

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

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

Возникла мысль — а можно ли Вашу программу переписать так, чтобы скомпилированный бинарник запускался под любой ОС на x86. Немного поразмыслив, пришел к выводу, что ваша — нет по двум причинам, а вообще любая (аналогичной сложности) — нет, по одной, самой главной, причине.
Домашнее задание — что за причины? :)
UFO just landed and posted this here
Программа может посмотреть структуру своего бинарника, и на основе этого определить ОС.
Правда, с Windows будут проблемы, так как у него недокументированное и непостоянное API системных вызовов.
UFO just landed and posted this here
Мак уже много лет, как не другая платформа. Вы, наверное, подумали о 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.
Sign up to leave a comment.

Articles