|
|
||
Процесс компиляции18.06.2012, 10:32. Показов 19247. Ответов 19
Метки нет (Все метки)
Вопрос из лички перетащу на форум, т.к. другим, возможно, тоже будет интересно
2. В любом случае я может неправильно понимаю, что означает "исполнительный" 3. Если под "линком" подразумевается линковка при помощи линкера (в русских книгах обычно это называют "связывание" и "редактор связей"), то препроцессор к этому отношения не имеет. Весь код функций находится в библиотеках. В языках Си и Си++ любая библиотека предоставляется в виде файла с бинарным кодом и набором инклюдов. Автор библиотеки должен гарантировать, что инклюды соответствуют бинарному файлу. Т.е. когда ты вызываешь printf, то в файле stdio.h есть только описание прототипа и больше ничего. Сам код функции printf находится в библиотеке в уже скомпилированном виде, а эта библиотека поставляется в комплекте вместе с компилятором. Компилятор по умолчанию линкуется с библиотекой, пользователю дополнительных действий делать не надо. 4. Что такое "ссылки" не понял В среднем при плохой терминологии и кривой постановке вопроса я примерно понимаю, чего человек хочет узнать. Если получится придумать, каким образом аккуратно и понятно изложить мысли, то попробую отписаться попозже
1
|
||
| 18.06.2012, 10:32 | |
|
Ответы с готовыми решениями:
19
Открыть процесс процесс на полный доступ, и запретить для других Процесс A в цикле просит пользователя ввести 5 чисел и затем передает их процессу B. Процесс B отображает на Процесс А инициализирует массив случайными значениями и записывает их в файл, а затем запускает процесс Б |
|
9 / 9 / 0
Регистрация: 15.07.2010
Сообщений: 255
|
||
| 18.06.2012, 12:21 | ||
|
0
|
||
|
|
|
| 19.06.2012, 13:24 [ТС] | |
Сообщение было отмечено как решение
Решение
Процесс компиляции состоит из нескольких стадий. Ко всему, что я буду объяснять, следует подходить условно и воспринимать как самое общее приблизительное пояснение. Просто в реальной жизни есть очень много тонкостей, которые начинающему понять будет сложно и такие объяснения будут лишь загромождением. Просто попытаюсь вкратце пояснить на пальцах суть происходящего.
Рассмотрим на простеньком примере C #include <stdio.h> int main (void) { printf ("Hello world\n"); return 0; } *** UPDATE *** Пока писал, понял, что пример выбрал неудачно и методику изложения следует немного поменять. Но для этого нужно в очередной раз найти время и уже в законченном виде с нормальными пояснениями выложить в блог, где можно спокойно редактировать и исправлять 1 этап. Препроцессирование На данном этапе работа идёт только с текстовыми файлами. Здесь препроцессор объединит наш исходник и все include-файлы в один большой текстовый файл. Для нашего случая это будет что-то типа: C /* Здесь идут потроха, подцепившиеся из stdio.h и прочих .h файлов, * которые могут подключаться внутри stdio.h. Касаемо функций или переменных * тут будут только описания, но никаких определений */ ... extern int printf (const char*, ...); ... /* Текст из stdio.h закончился, далее идёт текст нашей программы */ int main (void) { printf ("Hello world\n"); return 0; } Результат работы препроцессора можно посмотреть так: Bash $ gcc t.c -E -o t.i 2 этап. Трансляция Полученный после препроцессирования единый текстовый файл скармливается транслятору. В процессе работы транслятора уже нет никакой работы со внешними файлами, путями поиска и т.п. На вход транслятору подаётся один файл с исходником, на выходе транслятора получается один файл, содержащий ассемблерный текст. А сам транслятор занимается преобразованием исходника на языке программирования в ассемблерный текст, содержащий код целевой машины на языке ассемблера. В нашем случае на выходе транслятора мы получим ассемблерный текст. Я привожу тот текст, который получен в результате работы компилятора gcc. Некоторые интересные места я отметил стрелочками и пронумеровал. О них пойдёт речь ниже. Assembler .file "t.c" .section .rodata.str1.1,"aMS",@progbits,1 .LC0: <----- 1 .string "Hello world\n" .text .p2align 4,,15 .globl main <----- 2 .type main, @function main: <----- 3 pushl %ebp movl %esp, %ebp andl $-16, %esp subl $16, %esp movl $.LC0, 4(%esp) <----- 4 call printf <----- 5 xorl %eax, %eax leave ret .size main, .-main .ident "GCC: (Ubuntu 4.4.3-4ubuntu5) 4.4.3" .section .note.GNU-stack,"",@progbits В нашем случае мы видим, что в коде имеются две метки. Метка ".LC0" (стрелка 1), описывающая набор символов от строкового литерала и метка "main" (стрелка 3), описывающая начало функции main. У каждой метки есть так называемая область видимости: локальная или глобальная. Локальные метки видны только внутри данного модуля, глобальные метки видны из других модулей. Метка ".LC0" является локальной, т.к. строковой литерал - это внутренние данные нашего модуля. Метка main является глобальной, т.к. эта функция должна быть видна извне (в исходнике у main'а нет модификатора static), а потому этот факт подсвечивается специальной директивой (стрелка 2). Помимо вхождения меток мы видим ещё и обращения к меткам: обращение к строковому литералу ".LC0" (стрелка 4) и обращение к внешней метке "printf" (стрелка 5). Результат работы препроцессора можно посмотреть так: Bash $ gcc t.c -S -o t.s 3 этап. Ассемблирование Полученный ассемблерный текст далее передаётся программе-ассемблеру, которая преобразует его в объектный файл. Объектный файл представляет собой бинарные коды целевой машины плюс дополнительная информация о метках и их использовании. Информация, содержащаяся в объектном файле принципиально ничем не отличается от информации, содержащейся в ассемблерном тексте. Только весь код вместо мнемоник, понятных человеку, содержит двоичный код, понятный машине. А вместо меток, расставленных по ассемблерному тексту, объектный файл содержит специальную таблицу символов (symbol table), описывающую все метки из нашего ассемблерного текста и таблицу перемещений (relocations table), описывающую точки, где метки использовались. Эти таблицы спроектированы таким образом, чтобы с ними было удобно работать линкеру и дизассемблеру. Конкретно в нашем случае эти таблицы будут выглядеть примерно таким образом. В объектном файле определена локальная метка ".LC0", глобальная метка "main" и внешняя метка "printf", к которой в данном файле есть обращения (но определения метки нет). В объектном файле есть использование метки ".LC0" и использования метки "printf" Важным моментом является то, что в объектном файле адреса ещё не настроены. Например, у нас в функции main есть обращение к метке ".LC0". но в том месте кода, где происходит это обращение, адрес метки ".LC0" ещё не проставлен, т.к. он будет известен только на этапе линковки Объектный файл можно получить так: Bash $ gcc t.c -c -o t.o Таблица символов (меток) - symbol table: Bash $ readelf --symbols t.o Symbol table '.symtab' contains 10 entries: Num: Value Size Type Bind Vis Ndx Name ... 8: 00000000 41 FUNC GLOBAL DEFAULT 1 main 9: 00000000 0 NOTYPE GLOBAL DEFAULT UND printf Таблица перемещений (использований) - relocation table: Bash $ readelf --relocs t.o Relocation section '.rel.text' at offset 0x360 contains 2 entries: Offset Info Type Sym.Value Sym. Name 00000015 00000501 R_386_32 00000000 .rodata.str1.1 <----- 00000021 00000902 R_386_PC32 00000000 printf 4 этап. Линковка Полученный объектный файл (а их может быть несколько) отдаётся линкеру. Линкер склеивает между собой все поданные ему файлы и формирует один большой исполняемый файл. Помимо объектных файлов компилятор подаёт в линкер ещё и библиотеки. Какие-то библиотеки компилятор подаёт невидимым для пользователя образом (т.е. пользователь непосредственно в этом процессе не участвует). Какие-то библиотеки пользователь сам просит компилятор передать линкеру. В первую группу, как правило, относятся библиотеки, отвечающие за run-time поддержку языка программирования и библиотеки, входящие в состав стандарта языка программирования или входящие в состав стандартной библиотечной поддержки на данной операционной системе. Библиотека, содержащая реализацию функции printf относится именно к этой группе. Ко второй группе относятся все пользовательские библиотеки (графические библиотеки, библиотеки для работы с криптографией и прочее) В контексте данной статьи к библиотекам нужно относиться следующим образом. Где-то кто-то написал реализации всех стандартных функций, в том числе и printf. Далее все эти реализации откомпилированы до объектного файла. Дальше каким-то образом склеили эти объектные файлы в единый файл (или в небольшое количество раздельных файлов) и назвали эти файлы словом "библиотека". Т.е. библиотека - это набор уже откомпилированных кодов. Далее эту библиотеку и include-файлы к ним включили в состав компилятора или в состав операционной системы Помимо склеивания файлов линкер ещё и занимается настройкой адресов. Поскольку весь набор кодов, требуемых для формирования программы-бинарника, уже имеется на руках у линкера, то линкер после склеивания уже однозначно может сказать, по какому адресу будет располагаться та или иная функция или переменная. Для каждого файла, поступившего на ликновку, линкер заглянет в таблицу перемещений (использований), из которой поймёт, в какое место кода какой адрес нужно прописать. Конкретно в нашем случае в объектном файле у нас две перемещения: для бывшей метки ".LC0" (которая превратилась в обращение к секции с данными) и для метки printf. В итоге в функцию main в те места, которые засвечены в таблице перемещений, будут воткнуты итоговые адреса в исполняемом файле, соответствующие местоположению метки ".LC0" и функции "printf" ======================================== ======================== В общем, пояснение было несколько сумбурным, а потому лучше будет, если ты задашь конкретные вопросы по непонятным местам, чтобы было ясно, каким образом в дальнейшем аккуратно это дело переписать
45
|
|
|
9 / 9 / 0
Регистрация: 15.07.2010
Сообщений: 255
|
|||
| 19.06.2012, 23:01 | |||
|
Vis - область видимости, установлено в default, т.е. весь файл. Как интерпретируются остальные значения в таблице (блок, класс, пространство имён)? Type printf будет установлен линкером? Type, тип процессора, под который скомпилирована функция? Sym. Value для printf будет установлено позже линкером для printf?
0
|
|||
|
|
|||||
| 19.06.2012, 23:59 [ТС] | |||||
Сообщение было отмечено как решение
Решениеvalue - это некое подобие адреса. В исполняемом файле это действительно адрес, а вот в объектном - это смещение внутри секции (в данном случае внутри секции кода). Мой пример неудачен тем, что там только одна функция. Сделай несколько функций и увидишь, что они имеют разные value (разные смещения внутри одной секции). Поле Ndx - это номер секции, в которой расположена метка. Список секций можно посмотреть через Bash $ readelf --sections t.o На данном этапе в неё углубляться не стОит Поле Type определяет тип метки (функция, переменная, всякая прочая служебная фигня). Как правило для линкера это поле не нужно. Это некий элемент удобства. Ещё по этим полям работают дизассемблер, отладчик, возможно ещё какие-то утилиты Поле size оно описывает размер (функции или переменной). Поле для линкера тоже не нужно. Точно так же используется дизассемблером, отладчиком, всяческими распечатывалками кода Имя метки - ну вроде бы и так понятно. По символьным именам и происходит линковка в том месте, где нужно расставлять адреса функций и переменных Поле Sym - это порядковый номер символьной ссылки (метки) в таблице символом текущего модуля. По этому номеру другие таблицы (типа таблицы перемещений) ссылаются на метку (символ)
5
|
|||||
|
9 / 9 / 0
Регистрация: 15.07.2010
Сообщений: 255
|
|||||||||||
| 20.06.2012, 19:03 | |||||||||||
0
|
|||||||||||
|
Волшебник
656 / 259 / 88
Регистрация: 18.12.2010
Сообщений: 545
|
|
| 21.06.2012, 12:00 | |
|
А как можно сделать, чтобы ассемблерный текст был не AT&T-синтаксис а Intel-синтаксис? Вообще возможно это?
0
|
|
|
|
||
| 21.06.2012, 12:07 [ТС] | ||
|
1
|
||
|
9 / 9 / 0
Регистрация: 15.07.2010
Сообщений: 255
|
|
| 24.06.2012, 20:22 | |
|
Как происходит весь процесс (компиляция + связывание), если используются виртуальные функции?
0
|
|
|
|
|
| 24.06.2012, 22:32 [ТС] | |
|
Сам процесс происходит точно так же (и не зависит от того, что в исходниках написано). О том, как устроена таблица виртуальных функций, написано в любом учебнике по Си++. Либо я вопроса не понял
0
|
|
|
9 / 9 / 0
Регистрация: 15.07.2010
Сообщений: 255
|
|
| 25.06.2012, 21:25 | |
|
Необходимость реализации чистых виртуальных функций (ЧВФ) есть из-за возможности ошибки при обращении к нереализованной ЧВФ через указатель таблицы виртуальных функций?
0
|
|
|
9 / 9 / 0
Регистрация: 15.07.2010
Сообщений: 255
|
|||||||
| 26.06.2012, 10:43 | |||||||
0
|
|||||||
|
5058 / 3118 / 271
Регистрация: 11.11.2009
Сообщений: 7,044
|
||
| 26.06.2012, 12:43 | ||
|
0
|
||
| 28.06.2012, 17:12 | |
Сообщение было отмечено как решение
РешениеНе по теме: На днях сдал сессию, был у нас такой предмет "Теория языков программирования и методы трансляции". Хочу поделиться ссылкой http://ermak.cs.nstu.ru/trans/ Для тех, кому лень читать большие толстые книги, там можно почитать об этапах трансляции. Информация в сжатом виде, но общий смысл понятен.
9
|
|
|
Незнайка
|
|
| 06.12.2017, 20:38 | |
|
Evg, можно маленький вопрос?
А каким образом осуществляется передача ассемблерного листинга транслятору (as)? Сохранением файла листинга и передачи транслятору в качестве аргумента пути к нему?
0
|
|
|
|
||||||
| 06.12.2017, 23:49 [ТС] | ||||||
|
Да, через файл. Если есть компилятор gcc, то подай в процессе компиляции опцию -v. Он покажет, что в каком порядке запускает, там наглядно видно, что передача данных между программами идёт через файлы в tmp-каталоге
1
|
||||||
|
Незнайка
|
|
| 07.12.2017, 06:46 | |
|
Evg, понял, благодарю
0
|
|
| 07.12.2017, 06:46 | |
|
Помогаю со студенческими работами здесь
20
Есть процесс A и дочерний процесс B, который находит хэндл родительского процесса A. И этот хэндл в разных случаях РАЗНЫЙ! Почему? Процесс компиляции Java Опишите пошагово процесс компиляции DLL Процесс компиляции aspx страниц на Web севере Как автоматизировать процесс компиляции и компоновки файла asm? Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |
|
Новые блоги и статьи
|
||||
|
Access
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
|
Новый ноутбук
volvo 07.12.2025
Всем привет.
По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне:
Ryzen 5 7533HS
64 Gb DDR5
1Tb NVMe
16" Full HD Display
Win11 Pro
|
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
|
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
|
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов
На странице:
https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/
нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
|
|
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов.
. . .
|
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
|
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
|
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут.
В век Веб все очень привыкли к дизайну Single-Page-Application .
Быстренько разберем подход "на фреймах".
Мы делаем одну. . .
|
Фото: Daniel Greenwood
kumehtar 13.11.2025
|