LINUX.ORG.RU

Изучение ассемблера: суть и с чего начать?

 ,


4

3

Доброго времени суток всем ЛОРовцам!

Начну немного с предистории. Живу под «гордым» названием веб-разработчик. Для клиентов маг и бездарь одновременно (хотя, второе чаще). Для понимающих просто очередной фронтендщик, который пишет велосипеды на ванильке. Помимо JS знаю, наверное, ниже среднего PHP, BASH и Lua. Когда-то учил Basic, Pascal, C и Python. И тут понятно, что не могу я назвать себя программистом - левел не тот. Вот по этой причине и для души хочу начать изучать ассемблер.

А теперь к сути. Почитал немного информации, понял, что есть команды процессора, используя которые мы создаем программу. Эти команды у разных процессоров/архитектур разные. Но как с этим всем работать пока не понял. Исходя из этого у меня есть ряд вопросов:

  1. Я так понимаю, что текст программы на ассемблере необходимо компилировать, да? Есть какой-нить предустановленный компилятор в GNU/Linux?
  2. Есть какие-то общие правила написания программ? Что-то вроде var arr; function(){};. Как-то же необходимо связывать меж собой команды процессора. Что это за WASM или TASM?
  3. Сборка программы на ассемблере возможна не на устройстве, для которого пишется программа? Если сравнивать с компиляцией ядра Linux.
  4. Я так понимаю, что для «переменных» необходимо жестко указывать ячейку памяти процессора и ОЗУ, да? Что на счет этого стоит учить? Необходимо для старта читать кучу материала о страницах памяти и т.д.?

Планирую начать с чего-то простого, например, Z80 или MC6800. Думаю, завтра у меня еще вопросы будут :) .

В общем, кто что посоветует, с чего начать, где эти основы брать? А то я как по среди моря не вижу куда плыть.

P.S. За ранее всем спасибо!

★★★★

Последнее исправление: Klymedy (всего исправлений: 2)
Ответ на: комментарий от Eddy_Em

Если в ассемблер не лезть, не читать бред, порождаемый компилятором и не репортить его, разрабы компиляторов окончательно разленятся, компиляторы начнут генерить тормозной неоптимальный код, что приведет к дополнительным затратам электричества, да и к тому же машинное время тратится, и вообще. Без ковыряния в ассемблере я б вот эти https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66152 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68027 баги не нашел

SZT ★★★★★
()
Ответ на: комментарий от SZT

GCC

Я не про GCC, а про компилятор ассемблера.

Какие оптимизации можно по-твоему сделать на уровне ассемблера?

такие же как и на уровне любого другого языка, учитывая специфику.

callbackhell
()
Ответ на: комментарий от callbackhell

Вот и перечисли мне эти возможные оптимизации. Мне пока в голову приходит только лишь расстановка long или short jump в зависимости от расстояния до метки перехода.

SZT ★★★★★
()
Ответ на: комментарий от targitaj

Решается на низком уровне просто элементарно, если знаешь как работает машина.

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

Это было бы элементарно для тех, кто сталкивается с геймдевом или комп. графикой.

foror ★★★★★
()
Ответ на: комментарий от SZT

Вот и перечисли

Оно мне надо? Достаточно того, что они возможны, и это опровергает твое изначальное утверждение. но ты опять от своих слов откажешься, так что разговор этот для меня бессмсленный.

callbackhell
()
Ответ на: комментарий от callbackhell

Там по ссылке говрят о ручной оптимизаии на ассемблере. Если ты на ассемблере написал mov rcx, rcx - по смыслу как nop - ассемблер должен ее именно так и ассемблировать, а не выкидывать т.к. она ничего не делает. А если выкидывает - это уже не ассемблер.

И вообще, изучать то что по ссылке нет смысла т.к. это под дос в реальном режиме.

SZT ★★★★★
()
Последнее исправление: SZT (всего исправлений: 1)
Ответ на: комментарий от SZT

Очевидно, что часть ручных оптимизаций может взять на себя оптимизатор при компиляции, и наверняка так оно и делается. В асме есть аналог переменных? Хотя бы запись и чтение из регистров. Так почему бы компилятору не вынести неизменяемые выражения из цикла, чтобы на каждой итерации не получать их заново?

callbackhell
()
Ответ на: комментарий от callbackhell

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

Нет, к ассемблеру это не относится. В ассемблере оптимизатора вообще нет.

В асме есть аналог переменных? Хотя бы запись и чтение из регистров.

В ассемблере у тебя есть регистры, память, флаги состояния. Переменных в привычном понимании там нет.

Так почему бы компилятору не вынести неизменяемые выражения из цикла, чтобы на каждой итерации не получать их заново?

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

Кроме того, в ассемблере вообще нет цикла как стандартной языковой конструкции. Там для этого используются всякие метки с условными переходами, примерно как как if(условие) goto метка в С

SZT ★★★★★
()
Ответ на: комментарий от SZT

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

пруф будет?

Кроме того, в ассемблере вообще нет цикла как стандартной языковой конструкции. Там для этого используются всякие метки с условными переходами, примерно как как if(условие) goto метка в С

Какая нахрен разница. Цикл это и есть условие и переход на метку, то что для этого есть «специальный» синтаксис на суть происходящего никак не влияет, кроме того, что метка всегда стоит в начале, и выше ее ты не прыгнешь.

callbackhell
()

А теперь к сути.

Суть в том что знание ассемблера никак не коррелирует с «уровнем» программиста. Скорее наоборот. Привлекают микрооптимизации и чистая алгоритмизация? Дык, поверь мне, на хаскеле такими вещами заниматься намного прикольнее.

Программист на ассемблере в первую очередь обязан знать аппаратную архитектуру и архитектуру ОС «своей» системы. Без этого даже начинать не стоит.

Почему, например, ассемблер был популярен во времена DOS? Тогда каждая первая книжка «Самоучитель по ... DOS» была пособием начинающего вирусописателя.

Ну, во-первых, потому что помимо сервисов собственно DOS, существовали (и широко использовались) сервисы BIOS. Во-вторых, использование сисколлов было широкоупотребительной (да и единственной) практикой получения сервисов ОС. В-третьих, комипиляторы ЯВУ тех лет были крайне сасовые, как по качеству генерируемого кода, так и по качеству языкового рантайма. В-четвёртых, под досом существовало два формата исполняемых файлов, и чтобы уложиться в com с его одним сегментом размера 64к, нужно было хорошо знать режимы работы компилятора. На ассемблере было *намного* проще. В-пятых, исполняемая модель была намного проще. Хочешь, вешайся на прерывание, хочешь врубай фалг трассировки. Хочешь — проси у доса, хочешь — проси то же самое у биоса, хочешь — проси то же самое у оборудования напрямую.

В современных ОС такой подход не работает. Хочешь чего-то — проси как и все через прикладные интерфейсы. Под линуксом, можно использовать сисколлы. Под вендой номера сисколлов меняются при каждой версии. Попытка «обойти», ни к чему хорошему кроме системных сбоев не приведёт: современные ОС больше занимаются мультиплексированием аппаратных ресурсов (как на системном, так и на прикладном уровне), чем чем-то иным.

В любом случае, предстоит сначала выбрать под какой аппаратной архитектурой придётся работать, тогда станут ясны ответы на твои вопросы 1-4.

что это за WASM или TASM

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

WASM — Watcom Open Assembler. Тоже была/есть такая контора, никогда не лезла в разборки между Квиком/Турбо и Билдером+Дельфи/Визуалом, но всегда пользовалась определённой популярностью в узких кругах (например, у IDSoftware).

Ещё WASM (ты скорее всего имеешь в виду именно его) одно время называли Win32Assembler приратский дистрибутив MASM (МакроАссемблер, Микрософт). В комплекте шли заголовочные файлы из WindowsSDK, преобразованные в совеместимый формат и набор туториалов Iczelion'а (под Win95/98) за что и знаменит.

TASM — ТурбоАссемблер (Борланд). Хотя и есть версия, способная работать под Винду/PE, потерял всякую актуальность. В настоящий момент должен находиться в составе активнов почившего Борланда у компании Embarcadero. Развивается, судя по всему, но всякую актуальность на данный момент потерял.

Macil ★★★★★
()
Ответ на: комментарий от Macil

Дык, поверь мне, на хаскеле такими вещами заниматься намного прикольнее.

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

callbackhell
()
Ответ на: комментарий от callbackhell

пруф будет?

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

Задача ассемблера - перевести мнемоники в машинный код. И если ты на ассемблере написал какой-то бред, значит так и надо. Может быть это обфускация такая, чтоб потом твой код было трудно разобрать. Или может ты решил измерить время выполнения этих мусорных инструкций, и написал вот такой цикл.

SZT ★★★★★
()
Ответ на: комментарий от callbackhell

На хаскеле как раз такими вещами заниматься скучно

Извини, но ты совершенно не понимаешь о чём говоришь. Да и на хаскеле ничего сложнее хелловордов не писал (если писал вообще).

Macil ★★★★★
()

Иппать, котаны! wasm.ru починили. Я аж прослезился.

Macil ★★★★★
()
Ответ на: комментарий от callbackhell

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

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

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

Macil ★★★★★
()
Ответ на: комментарий от Macil

Для этого, достаточно было бы показать, как хаскель модифицирует исходный код функции в рантайме, а затем исполняет эту модифицированную функцию. Или, как он меняет тип в рантайме. Но так как хаскель ничего этого не может, то доказывать что-либо действительно бесмысленно.

callbackhell
()
Ответ на: комментарий от targitaj

Как можно писать код, если ты не понимаешь что именно делает машина?

Как можно писать код, если ты не понимаешь процессов, происходящих в транзисторе!

Братиш, 2016 год на дворе, уже много лет индустрия делает всё, чтобы скрыть как можно больше, чтобы программист не расписывал каждый чих руками, а писал «алгоритм» в том виде, в котором он в голове. Если у тебя в 2016 году для любой задачи в голове возникает решение на asm-е (да и даже на сишке), что-то тут не так.

Задавали соискателям задачку. Есть 4 млрд + 1 число, из которых 4 млрд - парные и 1 непарное. Надо найти это самое единственное непарное число.

и часто у вас такие задачи в продакшне?

lazyklimm ★★★★★
()
Ответ на: комментарий от Macil

И да, время потраченное на изучение ортогонально пониманию. Время требуется только для изучения синтаксиса и API, программирование везде одинаково. Если знаешь программирование, считай, что знаешь семантику любого языка. А знание языков не дает понимания программирования.

callbackhell
()

Немного личного опыта: изучал asm так: брал какую-то книгу сначала, вроде это был учебник юрова. Брал компилятор, вроде это был tasm сначала. И пытался писать что-то на асм, связывая это с кодом на С с помощью turboc. Очень хорошо прокачивается понимание того, во что превращается С и как с этим работает. То есть практическое понимание того как ассемблер используется, реально используется, во что превращяются Сшные и иные структуры. Нужно именно передавать из сишного кода структуры, чтобы поработать с указателями из ассемблера, ощутить разницу в работе со стеком, сегментами данных и прочим. Очень быстро приходит понимание, достаточно написать на асме какую-нибудь библиотеку списков, которую можно использовать из С.

Затем пробовал masм, плюнул и перешёл на flatassembler. Сейчас если приходится конечно использую gas, в реальных проектах таки приходится иметь с разными архитектурами дело.

Думаю начинать писать чисто на АСМ, например для контроллеров можно всегда, но сначала нужно поработать с реальным окружением, прокачать навыки использования неАСМ кода из АСМ и наоборот. И все твои вопросы отпадут очень скоро, ну то есть через пару месяцев:)

ixrws ★★★
()
Ответ на: комментарий от Eddy_Em

Вот только бы кодогенерацию простую добавить в gcc прямо, вот было бы прекрасно. Моя мечта С + рантайм эквивалент макросов, выкинул бы жабаскрипт нахрен.

ixrws ★★★
()
Ответ на: комментарий от callbackhell

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

как тут не вспомнить бессмертное

«Functional programming is like describing your problem to a mathematician. Imperative programming is like giving instructions to an idiot.»

lazyklimm ★★★★★
()
Ответ на: комментарий от ixrws

Вот только бы кодогенерацию простую добавить в gcc прямо, вот было бы прекрасно. Моя мечта С + рантайм эквивалент макросов

Ты сам то понял что сказал?:) Это несочемаемое, как можно добавить в GCC рантайм-кодогенерацию, если в рантайме нет никакого GCC?

callbackhell
()
Ответ на: комментарий от lazyklimm

Абстракции - это хорошо, это устранение кучи рутинной работы, но все-таки следует понимать суть проиходящего в машине. А задача эта, как мне сказали, - классика поиска ошибок при передаче данных.

targitaj ★★★★★
()
Ответ на: комментарий от lazyklimm

Идиотом(причем безграмотным) является как раз автор этой цитаты, поскольку императивное противопоставляется (грамотными людьми) декларативному, а функциональное тут ортогонально.

callbackhell
()
Ответ на: комментарий от targitaj

но все-таки следует понимать суть проиходящего в машине.

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

lazyklimm ★★★★★
()
Ответ на: комментарий от lazyklimm

для того, чтобы не плодить идиотских решений простых задач

targitaj ★★★★★
()
Ответ на: комментарий от ixrws

Или ты предлагаешь всякий раз взывать изнутри рантайма GCC? Это все равно не даст желаемого эффекта, поскольку кодогенерация будет происходить изолированно от текущего окружения. Проще новый язык запилить, чем осуществить то, что ты хочешь.

Собственно, objective c запилили, ЕМНИП, как раз во-многом из похожих соображений. Но опять же, если позволить рантайм-кодогенерацию, то си потеряет скорость, и получится, хрен нахрен, JS еще быстрей будет.

callbackhell
()

Не знаю, предлагали ли уже это, но попробуй скачать vmips (или там в интернетах помню есть какой-то учебный эмулятор MIPS - погугли (на англ.)) и попытаться понять сначала ассемблер MIPS.

На таких эмуляторах можно поучиться программировать, например, RS232, понять регистры, память, прерывания.

А так, конечно, google x86 assembler hello world.

anonymous
()

Планирую начать с чего-то простого

Когда-то учил Basic, Pascal, C и Python

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

Даже в ядре линукса мощи Си хватает, ЕМНИП, где-то для 99% кода, и только оставшийся процент - ассемблер. Я на ассемблере писал, когда мне было 20 лет. Наигрался, стало лениво. Это действительно очень мощное оружие, которое реально требуется крайне редко. К тому же, в 2015 году писать код, намертво прибитый гвоздями к архитектуре x86, больно и обидно. Есть армы, есть ещё всякая экзотика (а вдруг, эльбрусы, которые не на спарке, к примеру, таки взлетят, или ещё кто-то из аутсайдеров...).

hobbit ★★★★★
()
Последнее исправление: hobbit (всего исправлений: 1)

Для новичка лучше подойдёт MASM.

Deathstalker ★★★★★
()
Ответ на: комментарий от d

Спасибо!

То есть получается, что если начать изучать tasm, то при переходе на masm придется переучиваться при сохранении железа?

А что с разрешениями (.8xp, .z80 etc) исходников? У каждого контроллера и ассемблера они свои?

Думаю, сегодня еще немного почитаю, а завтра вечером начну ковырять helloworld'ы :) .

Нашел по Z80 такой helloworld:

.NOLIST
#define   EQU   .equ
#define   equ   .equ
#define   END   .end
#define   end   .end
#include "ti83plus.inc"
.LIST

     .org 9D93h
     .db $BB,$6D
      ld a,0
      ld (CURCOL),a
      ld (CURROW),a
      ld hl,text
      B_CALL(_PutS)
      ret
text:
      .db "Hello, World!",0

.end
end

На 8080 или x86 он будет совсем другим?

Условия пишутся примерно так, если в учат брать то, что одна строка = одна команда?

if a>b
then a=0
endif

EmgrtE ★★★★
() автор топика
Ответ на: комментарий от anTaRes

За Калашникова спасибо! Две книги нашел у него. А сайтец тот читаю уже второй день :) .

EmgrtE ★★★★
() автор топика
Ответ на: комментарий от EmgrtE

На 8080 или x86 он будет совсем другим?

Да, совсем.

Возьми сразу родной ассемблер для x86 и линукса и натаскай мануалов по нему. Выше тебе называли fasm и nasm, и объясняли чем они отличаются.

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

hobbit ★★★★★
()
Последнее исправление: hobbit (всего исправлений: 2)
Ответ на: комментарий от arturpub

То есть еще могут быть проблемы с скажем #include, #!/bin/sh или src='../images/img.png'? Ого...

EmgrtE ★★★★
() автор топика
Ответ на: комментарий от beastie

Замечание по кодировке сообщений на ЛОР уместно, да. Но я так часто тут пишу, что кроме url и code с ходу ничего не вспомню.

EmgrtE ★★★★
() автор топика
Последнее исправление: EmgrtE (всего исправлений: 1)
Ответ на: комментарий от FeyFre

Ммм, спасибо! Особенно за пункты.

На счет бумаги. Есть один местный работодатель для фрилансеров, так он определяет уровень кандидата на листке бумаги :) .

EmgrtE ★★★★
() автор топика
Ответ на: комментарий от callbackhell

почему бы компилятору не вынести неизменяемые выражения из цикла, чтобы на каждой итерации не получать их заново?

Потому что ассемблер как раз таки предназначан для того, чтобы транслировать мнемоники в машинный код или данные, не меняя при этом их структуры. Несмотря на то, что обычно в трансляторе есть макросы, они всего лишь текстовые и не позволяют структурных изменений. Одноименность мнемоник разной ширины тоже однозначна и никаких оптимизаций тут не притянешь (кроме уже упомянутой ширины джампа). Ни один ассемблер не формирует ssa для анализа, чтобы дать ее макросам. Эта лужа уже намочила твои штанишки, как бы ты не упирался. Просто не лезь в следующий раз с заявлениями, в которых ничерта не смыслишь.

arturpub ★★
()
Ответ на: комментарий от targitaj

Я собираюсь параллельно учить. Но некотрое понимание механики процессора и p-n-перехода у меня есть. Знаю, что 1 - это около 3-5 В, а 0 - 1-1,5 В. Знаю о тактовом генераторе, который в старых компьютерах выполнялся отдельной деталью от процессора. И все в таком духе.

Лет 5 назад занимался расчетами ламповых усилителей и их конструированием. Правда, трансы ни разу не мотал :) . Это мне дало понимание того, что транзистор есть всего лишь модулятором частоты. Да и многое я тогда из электорники узнал.

EmgrtE ★★★★
() автор топика
Ответ на: комментарий от SZT

Спасибо за ответы и советы!

В старом доме полно железа всякого завалялось, а с собой есть штуки три геймбоя с модифицированными Z80. Можно на них попробовать, но нужно будет купить для этого что-то вроде LSDJ.

Наверное, это травма дестства. Первый компьютер на котором мне удалось потыкать кнопочки оказался ЭВМ М-5100. Я как раз застал его обновление с перфокарт на магнитные ленты. Тогда я был слишком мал, чтобы хоть что-то понимать, но увиденное мною оставило в голове незабываемые кадры! Сейчас я часто использую текстовую консоль в повседневной работе и мне сложно описать эти ощущения. Звучит как извращение :/ .

EmgrtE ★★★★
() автор топика
Ответ на: комментарий от anonymous

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

arturpub ★★
()
Ответ на: комментарий от callbackhell

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

Мне без разницы на новые архитектуры. По крайней мере сейчас. Я это хочу сделать просто для души. Может дальше каких-то экспериментов с Z80 или Arduino у меня не пойдет, но я получу тоже, что и при работе с консолью. Здесь то ничкто не говорит, что текстовая консоль - это прошлый век и давайте использовать только «пальцетыкалку» :) .

EmgrtE ★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.