LINUX.ORG.RU

Написание свободной(Free as in Freedom) книги-самоучителя по программированию: планы, цели, задачи

 , , ,


17

9

Итак, я решил написать(или как вариант, собрать из кусочков) книгу-самоучилель по программированию, в которой бы не было глупых и нелепых ограничений на распространение. Однако копилефт я все же считаю приемлемым в данном случае. Общественным достоянием это не будет т.к. вполне могут найтись желающие использовать результат в своих проприетарных книгах, а проприетарные книги — плохо. Лицензия самого текста книги-учебника будет или Creative Commons Attribution-ShareAlike (что позволит без каких-либо проблем переиспользовать текст из википедии) или что-то вроде GNU Free Documentation License (без неизменяемых разделов естественно).

Лицензии всяких примитивных программок, написанных мной лично, будут вообще выложены под общественным достоянием, WTFPL или аналогичной лицензией т.к. являются тривиальными. Примерно вот так. Если я буду использовать чужие исходные тексты, они будут как включения, лицензируемые отдельно от всего остального. Проблем тут быть не должно.

Теперь к теме того, на кого книга ориентирована, какие начальные знания предполагаются, чему книга будет учить, какой первый ЯП взять и каков будет авторский самысел: С этим моментом я пока что не определился окончательно, и тут есть что обсудить. В частности, я не вижу особого смысла объяснять какие-то базовые понятия комбинаторики, об этом можно доступным языком прочитать из школьных учебников. Системы счисления(СС), перевод из одной СС в другую - вот это еще можно. One's и two's complement представления знаковых чисел — про это тоже можно написать. Если же человек не понимает комбинаторику, он ее быстро поймет на примере кода, который будет достаточно наглядно это показывать, и который всенепременно будет.
Пока что в качестве первого языка я склоняюсь к Си, и тому есть причины. Все прочие распространенные языки (кроме ассемблера, хотя его трудно назвать распространенным) не настолько близки к аппаратному уровню. Про нужность понимания на низком уровне написано тут http://russian.joelonsoftware.com/Articles/BacktoBasics.html https://habrahabr.ru/company/piter/blog/271347/ , не вижу смысла повторяться. Приведу лишь цитату:

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

Притом еще один важный момент: Си будет изучаться параллельно с ассемблером. Если речь идет об изучении ассемблера, необходимо четко зафиксировать то, на какой архитектуре это все происходит и в какой ОС. Так вот, ОС будет GNU/Linux а архитектура x86-64. Будут постоянно проводиться параллели между тем, что из себя представляет код на Си в текстовом виде, и тем, в какой текст на ассемблере его превращает компилятор. В связи с этим, первым делом будет рассказано о goto и конструкции if(условие) goto метка;. Про конструкции вида

if(условие)
{
  что-то_делаем;
}
else
{
  что-то_другое_делаем;
}
Будет рассказано немного позже, притом это будет рассказано и словами, и через написание эквивалентного кода через if(условие) goto метка;. Циклы, for(){} while{}, do{}while(), конструкция switch-case и break continue внутри них будут так же объясняться через все тот же if(условие) goto метка; притом будет делаться явный акцент на том, что намного лучше использовать нормальные циклы, чем лепить всюду этот условный goto. Кроме того, будет так же рассказано про Labels as Values. Почему так важна эта странная штука, if(условие) goto метка;? Потому что она имеет наипрямейшее отношение к тому, как работают ЭВМ, а всякие циклы СКРЫВАЮТ это. Рекурсия в Си будет объясняться только после того, как будет объяснено, что такое стекфрейм и соглашения вызова, будет сказано про оптимизацию хвостовой рекурсии, и о проблеме забивания стека, если такая оптимизация не происходит, притом это будет наглядно показано в ассемблере. Учиться отлаживать код надо будет тоже «с пеленок», притом отлаживать и ассемблер, и всякие там Си. Будет и про асм-вставки в Си, clobber list. В качестве ассемблера будет рассматриваться GAS, а никакой не NASM т.к. GCC умеет выплевывать ассемблер именно в GAS синтаксисе. Насчет выбора Intel или AT&T синтаксиса - тут я склонюсь пожалуй к тому, что надо ЗНАТЬ И УМЕТЬ ПОНИМАТЬ ОБА. Кроме того, GAS давно уже умеет в оба синтаксиса, так что проблем с этим не будет. Единственная проблема с GAS в том, что это однопроходной ассемблер, так что можно освоить и какой-нибудь NASM, YASM.

Первые хеллоуворды будут написаны вообще в особом стиле, без использования printf() и вообще без библиотеки Си; Будут использованы куски на ассемблере, которые делают системный вызов write и read, и с ними можно(нужно) будет линковаться, чтоб что-то вывести на экран. Будет рассказано и про printf естественно, но только когда будет совершенно четко ясно, что такое вообще va_list. Будет куча отсылок к драфту стандарта Си (недрафт почему-то платный). Будет так же рассказано про устройство ОС. В конце скорее всего будет дано задание сделать свою игрушечную ОС так что предполагается что человек к тому моменту должен уже отлично понимать всякие там связные списки, графы, очереди, спинлоки-аллокаторы свои уметь делать на асме при желании. Алгоритмы сортировки, обхода графов, хеш-таблицы, все это будет объяснено на языке Си, и плюсов вообще касаться я не буду.

Насчет графики: работу с протоколом иксов тоже можно будет рассказать, обработку нажатий клавиши. Правда там надо дофига писать про кучу всего, например что есть сокеты, есть AF_LOCAL... Тогда это можно еще и сетевому программированию учить на каких-нибудь беркли-сокетах.

Кроме того, после моей книги предполагается, что человек должен уметь заниматься такими ненужными (в GNU/Linux) на первый взгляд вещами, как крякинг, реверсинг, исправление ошибок в бинарниках, не обладая исходным текстом. Восстановление логики работы программы по дизасму. Ну и программирование в машинных кодах (без ассемблера, одним HEX редактором).

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

cast ASM be_nt_all mister_VA

UPD: Программирование и отладка на C/ASM - Первые программы. Знакомство с C и ассемблером. Компиляция, линковка, код возврата. Вывод текста.

★★★★★

Последнее исправление: CYB3R (всего исправлений: 6)
Ответ на: комментарий от deadskif

write более байтолюбство - сплошной пересыл куска байтов из памяти в гиперпростанство файлов.

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

Ну пусть puts. Если компилять gcc -O2, puts и будет.

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

puts(«Hello world\n»), исходники puts, исходники write. Попутно объяснить что вообще такое сисколы и ОС хотя бы в общих чертах. Например.

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

А чем вызов libc-шной функции write лучше вызова libc-шной функции printf?

Ну формально, write это всего лишь обёртка для syscall вызова.

Можно сделать так:

#include <linux/unistd.h>
typedef int ssize_t;
typedef int size_t;
static inline ssize_t write(int fd, const void *buf, size_t count) {
	return syscall(__NR_write, fd, buf, count);
}
int main(void) {
	const char msg[] = "Hello World!";
	return write(2, msg, sizeof(msg)-1);
}

Результат (если собрать с флагом -static -Os):

0000000000400ce6 <main>:
  400ce6:       48 83 ec 28             sub    $0x28,%rsp
  400cea:       be 84 35 49 00          mov    $0x493584,%esi
  400cef:       b9 0d 00 00 00          mov    $0xd,%ecx
  400cf4:       48 8d 7c 24 0b          lea    0xb(%rsp),%rdi
  400cf9:       48 8d 54 24 0b          lea    0xb(%rsp),%rdx
  400cfe:       f3 a4                   rep movsb %ds:(%rsi),%es:(%rdi)
  400d00:       64 48 8b 04 25 28 00    mov    %fs:0x28,%rax
  400d07:       00 00 
  400d09:       48 89 44 24 18          mov    %rax,0x18(%rsp)
  400d0e:       31 c0                   xor    %eax,%eax
  400d10:       be 02 00 00 00          mov    $0x2,%esi
  400d15:       bf 01 00 00 00          mov    $0x1,%edi
  400d1a:       b1 0c                   mov    $0xc,%cl
  400d1c:       e8 6f 3c 03 00          callq  434990 <syscall>
  400d21:       48 8b 54 24 18          mov    0x18(%rsp),%rdx
  400d26:       64 48 33 14 25 28 00    xor    %fs:0x28,%rdx
  400d2d:       00 00 
  400d2f:       74 05                   je     400d36 <main+0x50>
  400d31:       e8 7a 63 03 00          callq  4370b0 <__stack_chk_fail>
  400d36:       48 83 c4 28             add    $0x28,%rsp
  400d3a:       c3                      retq   
  400d3b:       0f 1f 44 00 00          nopl   0x0(%rax,%rax,1)

0000000000434990 <syscall>:
  434990:       48 89 f8                mov    %rdi,%rax
  434993:       48 89 f7                mov    %rsi,%rdi
  434996:       48 89 d6                mov    %rdx,%rsi
  434999:       48 89 ca                mov    %rcx,%rdx
  43499c:       4d 89 c2                mov    %r8,%r10
  43499f:       4d 89 c8                mov    %r9,%r8
  4349a2:       4c 8b 4c 24 08          mov    0x8(%rsp),%r9
  4349a7:       0f 05                   syscall 
  4349a9:       48 3d 01 f0 ff ff       cmp    $0xfffffffffffff001,%rax
  4349af:       0f 83 9b 3b 00 00       jae    438550 <__syscall_error>
  4349b5:       c3                      retq   
  4349b6:       66 2e 0f 1f 84 00 00    nopw   %cs:0x0(%rax,%rax,1)
  4349bd:       00 00 00 

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

puts(«Hello world\n»), исходники puts, исходники write.

puts уже манипулирует FILE*. Причем со своими буферами, которые находятся в юзерспейсе...

С другой стороны может и верно, стоит сделать на puts и printf, потом рассказать про всю прослойку, а потом уже переходить к lowlevel...

ASM ★★
()

Кстати, ещё в плюс использования stdio, это всё же большая кроссплатформенность.

К примеру соберётесь под atmel avr программу писать, printf там есть, а вот write уже нет.

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

Ну формально, write это всего лишь обёртка для syscall вызова.

Ну вообще да, это понятно. Но это все в libc лежит, и write(2), и syscall(2). Так что разницы не так много. А как просто так, без асма, из С сисколы дергать, я с ходу не нашел.

puts уже манипулирует FILE*. Причем со своими буферами, которые находятся в юзерспейсе...

Это да. Но с другой стороны, можно привести упрощенный вариант puts(3) как простой обертки над write(2). Главное написать, что это на самом деле все сложнее и расписать зачем это все.

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

ПММЛ - машины тьюринга вообще не нужны ни для чего в нашем ремесле.

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

Наверное, ассемблер несколько сложнее, чем С, ну и что.

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

ПММЛ - машины тьюринга вообще не нужны ни для чего в нашем ремесле.

Попробую объяснить. Я хочу (и буду) описывать то, как можно написать свой интерпретатор. Первый интерпретатор будет какой-нибудь брейнфакоподобный, потом может быть будет сделано нечто более практичное. Мне надо рассказать, что на этом самом интерпретаторе можно впринципе сделать все то же(в плане алгоритмов) что и на Си, ассемблере, чем угодно. Как это рассказать, не рассказывая про Тьюринг-полноту и МТ?

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

повторюсь

http://homepage.ntlworld.com/edmund.grimley-evans/

в части http://homepage.ntlworld.com/edmund.grimley-evans/bcompiler.html (сырцы полный комплект http://homepage.ntlworld.com/edmund.grimley-evans/bcompiler.tar.gz) ну и загляни в http://homepage.ntlworld.com/edmund.grimley-evans/cc500/

как точка роста очень познавательный экзерсис.

вот если будет такого рода интерпретатор реализован т.е «ci500» будет интересно по ...

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

Ну, машина Тьюринга — только один из абстрактных исполнителей алгоритмов, есть и другие, в математическом смысле эквивалентные… Нужна ли в учебнике МТ и брейнфак? Наверное да, но в качестве первого интерпретатора, не знаю… Как по мне — раз если ужж писать самоучитель, это должна быть опциональная глава, на правах врезки. А в качестве первого интерпретатор дать, какой-нибудь стековый калькулятор, может быть dc, в рамках ориентации на unix/linux.

be_nt_all ★★
()

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

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

Ох, не хочу втягиваться в эту тему. Но отвечу: можно посвятить этому один абзац. Дать понятие, не вникая в детали. Кому надо, пусть почитает Википедию. Само понятие вычислимости для компьютеров имеет мало пользы. Потому что в реальной жизни нужно не только вычислить функцию, но и, скажем, драйвер устройства или программу для работы с Postgres. А для этого не все языки подходят, хотя все они вроде бы ТП. Когда вы будете сравнивать разные реализации ЯП, вы же об этом не умолчите.

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

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

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

Брейнфак вообще неясно зачем нужен (незнаком с ним и как-то прожил). В остальном согласен.

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

Вот с этим особенно согласен.

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

Брейнфак вообще неясно зачем нужен

Для общего развития, чисто факультативно

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

к Си лучше подходить с двух сторон: сверху и снизу, поэтому лучше изучать минимум третьим.

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

То есть, что такое машина Тьюринга ты не знаешь?

anonymous
()

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

Хотя мне кажется что я делаю все правильно. Надо б перевести https://www3.nd.edu/~dthain/courses/cse40243/fall2015/intel-intro.html и включить отдельной статьей, а потом разобрать простейший хелловорд через системные вызовы write из ассемблера, без всяких там glibc-ов

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

Миникс не умеет в 64 бит, а я уже взял курс на 64-бит. Кроме того, с ним придется возиться в виртуалках всяких(мало кто станет это ставить на реальное железо, пусть даже в дуалбут), что не очень хорошо.

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

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

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

Ну переписывать миникс под 64бита я точно не буду. Если мне нужна будет какая-нибудь примитивная ОС в учебных целях, я возьму http://www.returninfinity.com/baremetal.html https://github.com/ReturnInfinity/BareMetal-kernel скорее всего

SZT ★★★★★
() автор топика
Ответ на: комментарий от SZT
user@localhost:~$ mkdir learn
user@localhost:~$ cd learn/
user@localhost:~/learn$ mkdir asm
user@localhost:~/learn$ mkdir c
user@localhost:~/learn$ cd c
user@localhost:~/learn/c$ mkdir 01_hello
user@localhost:~/learn/c$ cd 01_hello/
user@localhost:~/learn/c/01_hello$ mkdir puts_hello
user@localhost:~/learn/c/01_hello$ cd puts_hello

Что это? Афтор? Зачем этот ад? Проще уж через файловый менеджер тогда.

mkdir -p learn/{asm,c}
mkdir -p learn/c/01_hello/puts_hello && cd $_

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

Зачем ты говоришь о «папках», которых итак не будет, о VCS, лицензии? Это для тебя тут всё просто, поэтому ты легко отвлекаешься от темы. Но если ты пишешь про хеллоуворлд, то не надо лишней информации. Лучше вынести её в отдельную часть.

Если мы хотим вызывать функцию, вершина стека должна быть кратна 16 байт (требования 86_64 ABI). Регистр rsp как раз за это отвечает

Это что? Для кого этот бесполезный комментарий? А статья твоя, между прочим, называется «Знакомство с Си и ассемблером».

На кого ориентирована книга? На лоровца? Ты, конечно, молодец. Тема действительно хорошая и нужная. Но тебе надо чётко определиться с целевой аудиторией. И будет лучше, если ей будет один конкретный человек.

Ещё я тебе посоветую помельче дробить темы и не смешивать их. А то тут у тебя и про сисколы и про библиотеки и про препроцессор, который не пойми откуда берёт этот странный файл с расширением .h. Я думаю, лучше вынести в отдельную часть информацию о том, как происходит сборка из сырцов. В отдельную — про статическую и динамическую линковку. В отдельную — про синтаксис языка, асма И т.п.

В отдельную — про память, сегментирование, стек и структуру программы в памяти.

Как программист ты должен бы в совершенстве уметь структурировать информацию.

Ещё было бы очень полезно сделать что-то типа читшитов по параметрам компилятора, приоритетам операторов, ассемблерным инструкциям и т.п. Или, на крайний случай, хорошие ссылки на подобную информацию.

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

И побольше интересных примеров.

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

Что это? Афтор? Зачем этот ад? Проще уж через файловый менеджер тогда.

Чтоб с консолью привыкали работать. Файловые менеджеры тут не нужны

mkdir -p learn/{asm,c}
mkdir -p learn/c/01_hello/puts_hello && cd $_

Да, можно так

Это что? Для кого этот бесполезный комментарий?

Это чтоб было понятно, зачем там делается этот subq $8, %rsp

Ещё я тебе посоветую помельче дробить темы и не смешивать их. А то тут у тебя и про сисколы и про библиотеки и про препроцессор, который не пойми откуда берёт этот странный файл с расширением .h. Я думаю, лучше вынести в отдельную часть информацию о том, как происходит сборка из сырцов. В отдельную — про статическую и динамическую линковку. В отдельную — про синтаксис языка, асма И т.п.

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

Как программист ты должен бы в совершенстве уметь структурировать информацию.

Пока что мне проще сначала все свалить в одну кучу, а потом уже все упорядочивать, структурировать и наводить красоту.

Ещё было бы очень полезно сделать что-то типа читшитов по параметрам компилятора, приоритетам операторов, ассемблерным инструкциям и т.п. Или, на крайний случай, хорошие ссылки на подобную информацию.
Обязательно нужно привести ссылки на мануалы и спецификации всех тех вещей, о которых ты пишешь.
И побольше интересных примеров.

Да, будет

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

Пока что мне проще сначала все свалить в одну кучу, а потом уже все упорядочивать, структурировать и наводить красоту

У каждого своя, в принципе, тактика. Но с целевой аудиторией надо определиться. Если это совсем нуб, то не надо ему тогда про регистры и стек с самого начала задвигать. От такой плотности информации можно мозг надорвать. Проще надо. Сильно проще.

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

Я так думаю.

anonymous
()

Автор не хотите ли присоединиться к проекту?

Уважаемый SZT, есть проект Morpho-OS, не хотите ли поучаствовать, есть возможность разместить книгу вашу на morpho-os.github.io, после того как уточним все моменты. Готов помочь с написанием, хотя мои знания в теме скудны.

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

ProtoH
()

On the ideological front, many people (myself included) strongly believe that Version 7 was not only an improvement on all of its predecessors, but also on all of its successors, certainly in terms of simplicity, coherence and elegance.

ps. and see http://www.vpri.org/pdf/m2007007a_revolution.pdf and http://www.vpri.org/html/work/NSFproposal.pdf

qulinxao ★★☆
()

Зачем вообще Си? Давай сразу ассемблер и ничего больше. Есть кстати книга «The Art of Assembly Language». Смотрел?

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

Зачем вообще Си? Давай сразу ассемблер и ничего больше.

Учить неудобную, устаревшую, полную legacy систему команд Intel86 (с последующими)? Отказываться от возможности переноса программ на мобильные устройства? No way. Или вы сразу ARM предлагаете изучать?

be_nt_all ★★
()

Уважаемый SZT, есть проект Morpho-OS, не хотите ли поучаствовать, есть возможность разместить книгу вашу на morpho-os.github.io, после того как уточним все моменты.

Конкретно про Morpho-OS — это похоже какой-то ваш дистрибутив на базе Arch. Я пишу свою книгу не применительно к какому-то конкретному GNU/Linux дистрибутиву, а вообще в целом. Не совсем понимаю, причем тут Morpho-OS. Но конечно я совершенно не против того, чтобы написанный мной текст переиспользовали и адаптировали применительно к какому-то конкретному дистрибутиву, но я перед собой такую задачу не ставил. И я совершенно не понимаю, зачем мне привязываться к какому-то вполне конкретному дистрибутиву.

Что такого есть особенного в Morpho-OS чтобы о нем упоминать в контексте рассмотрения языков Си и ассемблера в моей начатой книге?

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

Есть кстати книга «The Art of Assembly Language». Смотрел?

Слышал. Там рассматривается не обычный ассемблер, а какой-то High Level Assembly который к тому же не умеет в x86-64. Так что не подходит

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

SZT, возможно все моменты стоит обсудить отдельно, пишите на email danilvorotnikov@rambler.ru.

Ответ на ваш вопрос: не нужно упоминать, если вы не знаете зачем. Morpho-OS это система, задача которой дать систему удобную для программиста. В состав базовых языков входит C и Ассемблер. Есть зачаток спецификации - https://morpho-os.github.io/spec/index.html. Здесь вкратце описывается как программы взаимодействуют с ОС. Хотелось бы разложить более подробно это взаимодействие, чтобы люди понимали как процессор выполняет единички и нолики и как программа в них преобразуется, причём не абстрактно, а на практике, с применением конкретных инструментов.

Проблема большинства книг в том, что они написаны в отрыве от реальности и реальных инструментов. Нужно показать как выполнять конкретные вещи, конкретными инструментами, указать их версии на момент использования. Какие это вещи? Это можем мы сами определить, можно задаться вопросом: Что мы хотим донести до человека?

Можно взять за основу понятие *программы* и *процесса*. Процесс это работающая программа. Во первых что такое программа? Программа может рассматриваться как:
1) реализация алгоритма (логическая составляющая)
2) последовательность инструкций (физическая составляющая).
3) файл на диске, который может быть загружен ядром ОС Linux (физическая составляющая)

Можно рассмотреть на примере как выполняется какая-нибудь конкретная программа в виде файла на диске, скажем, это бинарник редактора vim - /usr/bin/vim. Мы даём команду в терминале /usr/bin/vim, что происходит дальше? Вот эти моменты и хорошо бы описать.

Насколько я понимаю процесс выполнения программы при запуске из $SHELL таков: $SHELL, например, bash (ещё можно рассмотреть zsh) в цикле читает и выполняет команды. В исходниках это main() -> reader_loop() -> read_command() -> execute_command() -> execute_command_internal() -> execute_simple_command() и всё заканчивается в execute_disk_command() непрямыми вызовами fork() и execve().

Вот ещё хороший пример: https://gist.github.com/amitsaha/8169242 - разбор команды ls.

Что происходит дальше после вызова каждой из функций: fork() и execve()? Это функции libc? Хорошо бы описать логику их работы, как они взаимодействуют с ядром. Какие средства доступны процессу, в данном случае vim и как ядро контроллирует и ограничивает процесс, его память на программном и аппаратном уровнях. Хорошо бы описать какими структурами данных описывается процесс в ядре Linux (современном на момент написания).

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

Полезно описать как стыковать вместе Ассемблер и C, inline Ассемблер и отдельно подключаемый файл на GAS.

Кроме этого, хорошо бы рассказать о безопасном коде на C - что такое переполнение буфера, как это может использоваться и как это можно предотвратить. Какие механизмы ядра есть для контроля процессов, например cgroups.

Интересно было всё это показывать на конкретных примерах маленьких работающих программ на С и Ассемблере, которые были бы написаны на современном С, который актуален в 2016.

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

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

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

Покажи примеры таких книг.

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

ты будешь смеяться но:

Ньютон Начала натуральной Философии.

Автобиография Кардано (тот чувак что уравнения 4 степени)

Астрономический Вестник Г.Галилея.

а вообще см. список в конце книги М.Адлер. Как читать книги.

ззы. История чтения в западном мире от античности до наших дней - вообще бомба -сборник.

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

Ну вообще был интересен ответ registrant27492, а то у него много крикливых слов, а по делу, какой-то конкретики, маловато.

А что касаемо программирования?

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

Ну вообще был интересен ответ registrant27492, а то у него много крикливых слов, а по делу, какой-то конкретики, маловато.

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

anonymous
()

Нехило, на такую работу 5 лет уйдёт.

SZT, а может ты хочешь посоревноваться с Столяровым? Так это глупо, у вас разные цели!

anonymous
()

скорее для варианта сборника хинтов в освоении - чем для варианта книжка всё в одном по которой неофит будет скиловаться

вот ссылка на

Plauger- The Standard C Library (1991) - а конкретно глава 12 <stdio.h> в части разьяснения printf write - да и вообще откоменченная не последним челом своя реализация - вот и сырцы почитают.

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

SZT, возможно все моменты стоит обсудить отдельно, пишите на email danilvorotnikov@rambler.ru.

Все это можно обсудить и тут.

Можно рассмотреть на примере как выполняется какая-нибудь конкретная программа в виде файла на диске, скажем, это бинарник редактора vim - /usr/bin/vim. Мы даём команду в терминале /usr/bin/vim, что происходит дальше? Вот эти моменты и хорошо бы описать.

Лучше написать какую-нибудь совсем простенькую программу, и описывать ее работу. vim это слишком сложная программа для начала

Что происходит дальше после вызова каждой из функций: fork() и execve()?

Если fork() делается только чтобы запустить новый процесс из-под него, лучше делать vfork().
man 2 vfork:
vfork() is a special case of clone(2). It is used to create new processes without copying the page tables of the parent process. It may be useful in performance-sensitive applications where a child is created which then immediately issues an execve(2).

Это функции libc?

Ядро разбирает elf заголовок http://lxr.free-electrons.com/source/fs/binfmt_elf.c

Вот точка входа, указанная в elf заголовке:

readelf -h /bin/ls | grep Entry
  Entry point address:               0x404890
Tочка входа выставляется обычно в процедуре _start из которой потом вызывается _init

https://www.opennet.ru/base/dev/objdump_elf.txt.html вот есть статья в опеннете, но там про 32-бит и довольно устаревшая информация.

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

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

Полезно описать как стыковать вместе Ассемблер и C, inline Ассемблер и отдельно подключаемый файл на GAS.

Кроме этого, хорошо бы рассказать о безопасном коде на C - что такое переполнение буфера, как это может использоваться и как это можно предотвратить. Какие механизмы ядра есть для контроля процессов, например cgroups.

Да, это все надо будет описать, но начинать надо явно не с vim.

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

Ну без конкретики он не царь, а просто чмарь, балабол в общем.

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


Ядро разбирает elf заголовок http://lxr.free-electrons.com/source/fs/binfmt_elf.c

Вот точка входа, указанная в elf заголовке:

readelf -h /bin/ls | grep Entry
Entry point address: 0x404890

Tочка входа выставляется обычно в процедуре _start из которой потом вызывается _init

https://www.opennet.ru/base/dev/objdump_elf.txt.html вот есть статья в опеннете, но там про 32-бит и довольно устаревшая информация.


Полезная инфа.

vfork() is a special case of clone(2). It is used to create new processes without copying the page tables of the parent process. It may be useful in performance-sensitive applications where a child is created which then immediately issues an execve(2).

Что такое page tables?

Ещё хорошо бы было описать, как отрабатывает команда процессора syscall, что делает ядро, что делает процессор и т.д.

Вот, кстати, пару полезных ссылок:
* способы адресации и список регистров - там есть картинка с регистрами и ссылки на .pdf мануалы Intel.
* список команд процессора

Один момент хотел бы предложить. Чтобы понять соответствие между кодом C и Ассемблером, полезно рассмотреть команду mov и оператор присваивания. Это может стать отправной точкой для дальнейшего изучения. Вот ссылка по теме: http://stackoverflow.com/questions/24746123/assembly-mov-instruction

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

Для облегчения понимания ассемблера можно написать, что регистр это как-бы предопределенная переменная, в которую можно писать/читать биты, хотя для некоторых регистров есть ограничения. В зависимости от того сколько битов можно читать/писать регистры называются по-разному:
* 8 бит - ?H, ?L, где ? это A, B, C или D. Пример: AL, AH, CL, CH, DL, DH
* 16 бит - ?X, ...
и т. д. до 512 бит
* 512 бит - ...
Регистры в зависимости от назначения условно делятся на группы. Например: писать/читать свободно всё что угодно можно в GPR (General Purpose Registers), т.е. в них можно хранить какие-то свои данные. IP/EIP/RIP - содержит адрес следующей инструкции, которая будет выполнена. Биты регистра флагов выставляются процессором автоматом в зависимости от того как отработала предыдущая команда, за разными битами закреплён разный смысл. Некоторые регистры используются для адресации, см. способы адресации выше. Некоторые, чтобы делать циклы и т.д, см. тут

Чтобы вызвать функцию ОС, нужно записать аргументы в регистры и вызвать команду syscall.

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

Свою функцию можно определить с помощью метки, которая будет аналогом имени функции и команды ret. Метка в ассемблере == адресу.

Могу где-то ошибаться, так как не помню некоторые моменты уже.

Кроме того, что выше написал, будет полезно сопоставить передачу по ссылке и по значению в Cи и ассемблерный код.

ProtoH
()

По тексту:

Функция puts находится в файле libc.so, который обычно располагается по адресу /usr/lib/libc.so

Как получить список функций в .so или др. файле?

При запуске нашей программы помимо исполняемого файла hello в память загружается и файл libc.so.

Как получить список подгружаемых .so-файлов?

Объектный файл содержит в себе особым образом подготовленный код (часто называемый двоичным или бинарным), который может быть объединён с другими объектными файлами при помощи редактора связей (компоновщика, линкера) для получения готового исполнимого модуля, либо библиотеки.

Каков формат .o-файла?

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