Языки и методы программирования неэффективны?(требуется знание ассемблера и C) - PullRequest
10 голосов
/ 16 июня 2010

я долго думаю и изучаю вывод компилятора языка Си в виде ассемблера, а также архитектуру процессора.Я знаю, что это может быть глупо для вас, но мне кажется, что что-то очень неэффективно.Пожалуйста, не сердитесь, если я ошибаюсь, и есть причина, по которой я не вижу всех этих принципов.Я буду очень рад, если вы скажете мне, почему он разработан таким образом.Я действительно искренне верю, что ошибаюсь, я знаю, гениальные умы людей, которые собирают компьютеры, знали причину для этого.Что именно, спросите вы?Скажу сразу, я использую C в качестве примера:

1: выделение памяти в локальной области стека:

Итак, типичное распределение локальной памяти использует стек.Просто скопируйте esp в ebp и затем выделите всю память через ebp.Хорошо, я бы понял это, если вам явно необходимо выделить ОЗУ по умолчанию для значений стека, но если я правильно понимаю, современные ОС используют подкачку в качестве уровня трансляции между приложением и физической ОЗУ, когда адрес, который вы хотите преобразовать, прежде чем достичь фактической ОЗУбайт.Так почему бы просто не сказать, что 0x00000000 - это int a, 0x00000004 - это int b и так?И получить к ним доступ только по mov 0x00000000, # 10?Потому что вы на самом деле не обращаетесь к блокам памяти 0x00000000 и 0x00000004, а к тем, в которых ваша ОС установила таблицы подкачки.На самом деле, поскольку при распределении памяти по ebp и esp используется косвенная адресация, «мой» путь был бы еще быстрее.

2: Двойственность распределения переменных:

Когда вы запускаете приложение, Loader загружает свой код вБАРАН.Когда вы создаете переменную или строку, компилятор генерирует код, который помещает эти значения в верхний стек при создании в main.Таким образом, есть фактическая инструкция для этого и это фактическое число в памяти.Итак, в оперативной памяти 2 записи одного и того же значения.Один в виде инструкции, второй в виде действительных байтов в ОЗУ.Но почему?Почему бы просто не объявить переменную count, в каком блоке памяти это будет, чем при использовании, просто вставить эту ячейку памяти?

Ответы [ 5 ]

17 голосов
/ 16 июня 2010

Как бы вы реализовали рекурсивные функции?То, что вы описываете, эквивалентно использованию глобальных переменных везде.

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

6 голосов
/ 16 июня 2010
  1. Поскольку C (и большинство других языков) поддерживает рекурсию, поэтому функция может вызывать сама себя, и каждый вызов функции требует отдельных копий любых локальных переменных. Кроме того, на большинстве современных процессоров ваш путь будет на самом деле медленнее - косвенная адресация настолько распространена, что процессоры оптимизированы для нее.

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

3 голосов
/ 16 июня 2010

Ответы на ваши вопросы в основном заключены в разную семантику разных классов хранения

  • Google "сегмент данных"
  • Подумайте о разнице в поведении между глобальным и локальнымПеременные.
  • Подумайте о том, как постоянные и непостоянные переменные имеют разные требования, когда функции вызываются неоднократно (или , как говорит Мехрдад, рекурсивно)
  • Подумайте о разнице междустатические и нестатические автоматические переменные снова в контексте множественных или рекурсивных вызовов.
2 голосов
/ 16 июня 2010

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

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

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

1 голос
/ 17 июня 2010
  1. Если каждая функция поместит свою первую переменную со смещением 0 и т. Д., То вам придется менять отображение памяти при каждом входе в функцию (вы не можете распределить все переменные по уникальным адресам, если выхочу рекурсию).Это выполнимо, но с текущим оборудованием это очень медленно.Кроме того, преобразование адресов, выполняемое виртуальной памятью, также не является бесплатным, на самом деле это довольно сложно реализовать эффективно.
    Адресация за пределами ebp (или любого другого регистра) стоит иметь мультиплексор (для выбора регистра) и сумматордобавить смещение в регистр).Время, затрачиваемое на это, часто может перекрываться другими операциями.

  2. Если вы хотите изменить статическое значение, вам необходимо скопировать его в стек.Если вы этого не сделаете (говоря, что это 'const'), то хороший компилятор C не скопирует его в стек.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...