Разница между реализацией и синтаксисом - PullRequest
0 голосов
/ 13 сентября 2018

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

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

Я искал, но не могу найти ничего, что объясняет, как работает синтаксис и чем он отличается от реализации.

Я видел синтаксис слова, используемый в http://sun.hasenbraten.de/vasm/, Сколько существует языков ассемблера и еще много статей.

Но я до сих пор не понимаю этого. Скорее всего, я нахожу вещи с синтаксисом AT & T против Intel (может кто-нибудь объяснить?).

Также этот бонус является вопросом: возможно ли ассемблеру поддерживать несколько архитектур? Если да, то как?

1 Ответ

0 голосов
/ 13 сентября 2018

Я думаю, что вы пытаетесь чрезмерно усложнить это.

Так что, хотя многие из них могут с этим справиться, и при необходимости напишите и запрограммируйте таким образом:

0xe0821003
0xe0021003
0xe0421003

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

Таким образом, для этих битов для этого набора инструкций (ISA) поставщик IP или процессора создает способ передачи того, что было задумано, таким образом, чтобы его можно было читать / записывать / обслуживать человеком.

И это будет

add r1,r2,r3
and r1,r2,r3
sub r1,r2,r3

Но это именно для этой конкретной цели, и авторы изобретения предложили рекомендованный язык. Все, что действительно имеет значение, это машинный код. Любой из нас может вместо этого создать язык ассемблера, который принимает этот

bob b,c,d
ted b,c,d
joe b,c,d

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

r1 = r2 + r3
r1 = r2 & r3
r1 = r2 - r3

в качестве языка ассемблера (машинный код цели, о которой я думаю, на самом деле облегчает написание / использование). и мы могли бы легко создать ассемблер, который использует этот синтаксис и создает тот же машинный код, что и выше. Ничто вообще не мешает нам делать это. Или даже добавление подобного синтаксиса к существующему ассемблеру, который поддерживает add r1, r2, r3, может поддерживаться одним и тем же инструментом.

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

Существует грубое недопонимание по этому поводу, люди считают, что x86 - единственный, который имеет разные синтаксисы, и у каждого - один синтаксис на цель. Существует история Intel против AT & T, в которой Intel определила и создала инструменты, которые поддерживают это:

mov ah,05h

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

add r1,r2,r3
r1 = r2 + r3

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

mov 05h,al

И в этом нет ничего плохого, кроме как глупо выглядеть

add r2,r3,r1
r2 + r3 = r1

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

Для этого не существует такого органа управления, как некоторые языки программирования высокого уровня. В лучшем случае у вас есть проблема с цепочкой инструментов, когда у вас есть компоновщик, ассемблер и компилятор, вывод компилятора часто является языком ассемблера, который ассемблер превращает в объекты, которые компоновщик превращает в двоичные файлы, таким образом, термин цепочка инструментов.
Вывод компилятора и ввод ассемблера должны быть согласованы, обычно одна сторона диктует, а другая соответствует. Так что, если по какой-то причине вы хотите использовать другой бэкэнд, вам нужен тот, который соответствует выходным данным компилятора. У вас точно такая же ситуация между ассемблером и компоновщиком, формат файла совершенно произвольный, независимо от того, что авторы решат изобретать, пока он выполняет свою работу, но для передачи одного инструмента другому должен быть согласованный формат. и / или другой инструмент для преобразования из одного формата в другой.

Таким образом, отдельно разработанный компилятор, такой как gnu gcc, хочет соответствовать отдельно разработанному ассемблеру, например, gnu as. Это было бы ближе всего к руководящему органу, который диктует правила о языке. А будучи открытым исходным кодом, человек может по желанию добавить функцию к одному и реализовать использование этой функции в другом.

Вернуться к AT & T против Intel. это неправильно воспринимается как единственный случай различий в языке ассемблера.

иди попробуй собрать этот совершенно законный код руки

add r1,r2,r3 ; and r1,r2,r3
add r1,r2,r3 @ and r1,r2,r3

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

add r1,r2,r3 ; and r1,r2,r3

и хотя бы один инструмент дает

0xe0821003
0xe0021003

и, по крайней мере, другой выводит это как

0xe0821003

(в каком-то формате объектного файла, с этими битами, представленными в этом формате)

Суть в том, что каждый нюанс языка имеет значение, у некоторых метка должна начинаться с первого столбца и иметь двоеточие, у других - нет. У некоторых есть директивы, которые должны начинаться с точки .GLOBAL, а другие - без GLOBAL, и тут код совершенно несовместим, не вдаваясь в реальные инструкции. Тогда у вас есть различия в инструкциях. Существует ОЧЕНЬ плохая новая причуда неиспользования имен регистров, я не могу этого вынести, поэтому я могу не понять их правильно

add a0,v1,v2

что, конечно, делает для полной несовместимости наряду с этим безумием:

mov %eax,0

Десятилетия успешных парсеров, а вы так ленивы?

Теперь мы не знаем, что вы подразумеваете под реализацией. В идеале, хорошо спроектированный язык ассемблера - это тот, который можно использовать как «инструкцию» языка ассемблера и который сопоставляется с конкретной машинной инструкцией. Но, к сожалению, у нас есть некоторые языки ассемблера, которые являются расплывчатыми, и / или наборы команд, которые являются расплывчатыми.

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

add r0,r1,#0
mov r0,r1

и по какой-то причине фактически реализуют разные инструкции для них. Часто вы увидите, что последний является просто псевдокодом для первого, но как на языке ассемблера, так и в наборе команд для x86 мы видим, что есть ряд мест, где вы можете «реализовать» намерение программистов несколькими способами. .

Это то, что вы говорите о реализации?

Более чистые, более узкие наборы команд сохранят пространство набора команд и не будут его иметь, некоторые могут не иметь nop, например, и вместо этого инструмент может просто использовать

and r0,r0

Хотя, если они это сделают, значит, они могли бы также использовать

and r1,r1

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

push {r1}

, который становится

stmia r13!,{r1}

потому что на самом деле в наборе команд нет инструкции push.

Сборка эволюционировала до: раньше для некоторых языков шестнадцатеричные числа были примерно такими, как 12 долларов, для Intel это 12 часов, но потом C стал популярным и доминирующим, а затем инструменты стали поддерживать 0x12, так что вы можете найти другой совместимый компилятор. семья, которая однажды не поддерживала 0x12, и следующую версию, которую они сделали.

ARM сделал что-то интересное прямо из ворот после того, как был Acorn. Они создали 16-битный набор инструкций, который был обратно совместим с 32-битными, в своей документации они показали, что 32-битная инструкция, которая была точно совместима, была той же самой инструкцией, что и более короткая (очевидно, может идти только в одну сторону).

Одним из способов сделать это было то, что большинство инструкций поддерживали только половину регистров r0-r7 вместо всех их r0-r15, что означает, что вам нужно было только три бита в инструкции, а не четыре. И у руки было что-то, что было не редкостью, но также и не очень распространенными инструкциями для трех регистров: добавить r1, r2, r3. Множество старых наборов инструкций, которые вы могли бы добавить r1, r2 с любым синтаксисом, и это означало, что операндом также был пункт назначения r1 = r1 + r2. И они сделали это для некоторых инструкций большим пальцем. И почему это имеет отношение к этому обсуждению, так это для ранних сборщиков большого пальца

add r1,r1,r2 

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

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

add r1,r1,r3
and r1,r1,r3
sub r1,r1,r3

.thumb
add r1,r1,r3
and r1,r1,r3
sub r1,r1,r3

дает

0: e0811003 добавить r1, r1, r3 4: e0011003 и r1, r1, r3 8: e0411003 sub r1, r1, r3 c: 18c9 добавляет r1, r1, r3 е: 4019 и R1, R3 10: 1ac9 sub r1, r1, r3

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

В общем, нет никакого смысла пытаться создать набор инструкций с разными целями, за исключением того, что описано выше, где у вас есть тот, который был получен из другого и когда-то или какое-то время реализован в такое же ядро. Попытка создать один синтаксис, который делает машинный код для x86 или arm, просто меняет цель, но использует тот же источник. Это не имеет смысла, зачем беспокоиться. Дело в том, чтобы сделать машинный код, конкретные инструкции, которые вы хотите иметь полный контроль над генерацией. Таким образом, вам нужна целевая информация, чтобы сделать это. Если вы откроете и удалите конкретные детали цели, то это уже не язык ассемблера, это язык высокого уровня, такой как C или python, JAVA или другой. Именно поэтому у нас есть эти языки высокого уровня, откуда C появился в 60-х годах, чтобы решить именно эту проблему, пытаясь реализовать darpanet, но имея несовместимые процессоры, которые мы сегодня называем модемом и / или маршрутизатором. , Поскольку мир развивался быстрыми темпами, вам пришлось продолжать переписывать одни и те же программы на ассемблере и / или создавать новые языки высокого уровня, а затем перенастраивать их после перекомпиляции компилятора, тогда в идеале вы могли бы повторно использовать некоторый процент от " заявка "на новую цель.

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

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

УСПЕШНЫЙ синтаксис - это тот, который имеет смысл и полезен, он не сложнее, чем сам машинный код.

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

...