Смешанный порядок операнда назначения / источника в синтаксисе сборки RIS C -V - PullRequest
5 голосов
/ 18 января 2020

Большинство инструкций в RIS C -V ассемблере упорядочивают операнд-адресат перед исходным, например:

li  t0, 22        # destination, source
li  t1, 1         # destination, source
add t2, t0, t1    # destination, source

Но инструкции по хранению имеют этот порядок в обратном порядке:

sb    t0, (sp)    # source, destination
lw    t1, (a0)    # destination, source
vlb.v v4, (a1)    # destination, source
vsb.v v5, (a2)    # source, destination

Как получилось?

Какова мотивация для этого (возможно, асимметричного) c синтаксического дизайна ассемблера?

Ответы [ 2 ]

4 голосов
/ 29 января 2020

Я не вижу реального несоответствия в сборке RIS C -V, когда дело доходит до приемник и исходные операнды : операнд-адресат - когда он является частью инструкции кодировка - всегда соответствует первому операнду на языке ассемблера.

Если мы посмотрим на следующие примеры команд из четырех из шести различных форматов команд:

  • R-тип : add t0, t1, t2
  • I-тип : addi t0, t1, 1 1
  • J -тип : jal ra, off
  • U-тип : lui t0, 0x12345

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

Теперь давайте сосредоточимся на инструкциях сохранения (формат S-типа). В качестве примера рассмотрим следующую инструкцию сохранения:

sw t0, 8(sp)

Я думаю, что совершенно ясно, что t0 выше - исходный операнд , так как инструкция сохранения сохраняет его содержимое в памяти.

Мы можем поддаться искушению думать, что 8(sp) является операндом-адресатом . Однако, внимательно посмотрев на формат инструкции S-типа:

S-type format

Мы можем сказать, что часть 8(sp) в приведенной выше инструкции по сборке не является ' на самом деле это единственный операнд, но фактически два, т. е. непосредственный 8 (т. е. imm ) и регистр источника sp (т. е. rs1 ). Если бы вместо этого инструкцию можно было выразить следующим образом (аналогично addi 2 ):

sw t0, sp, 8

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

Регистр sp не изменяется, только чтение; поэтому его нельзя считать регистром назначения . Это также исходный регистр , так же как t0 - это регистр, содержимое которого хранит инструкция сохранения в памяти. Память - это целевой операнд , поскольку именно он получает содержимое t0.

Формат команды S-типа не кодирует целевой операнд. То, что кодирует инструкция, это адресация информации в операнде-адресате . Для sw t0, 8(sp) операндом-адресатом является слово в памяти в месте, указанном действующим адресом , который инструкция сохранения вычисляет из sp и 8. Регистр sp содержит часть этой адресной информации об этом слове в памяти (т. Е. Операнде-адресате).

Сводка

Инструкции по сборке в RIS C -V, которые кодируют пункт назначения операнд имеет этот операнд в качестве первого. Однако инструкция сохранения не кодирует целевой операнд. Его целевой операнд - это место в памяти, а адрес этого места в памяти вычисляется из содержимого операндов источника инструкции.


1 Возможно, мы могли бы утверждают, что приведенная выше инструкция jal ra, off имеет дополнительный целевой операнд, а именно pc, поскольку pc обновляется следующим образом: pcpc + SignExtension (off) . Однако выполнение любой другой инструкции также приводит к изменению pc, например, к увеличению pc на четыре (может отличаться для ветвей и jalr). В любом случае, pc не закодирован ни в одной инструкции, и он не доступен напрямую программисту как регистр. Поэтому он не представляет интереса для обсуждения. По этой же причине в этом обсуждении я также пропустил формат типа B.

2 Или наоборот: думайте так, как если бы вы могли express addi t0, t0, -1 как addi t0, -1(t0). Тогда вы бы сказали, что addi принимает два операнда (например, t0 и -1(t0))?

2 голосов
/ 18 января 2020

Язык ассемблера определяется ассемблером, программой. Это зависит от автора (ов), чтобы выбрать синтаксис. Ассемблер может выбрать синтаксис

bob pickle,(jar)

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

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

Чтобы иметь шанс на успех - в интересах разработчиков процессоров создать или нанять кого-то, чтобы сначала создать ассемблер, а затем набор инструментов для своего нового процессора, который будет включать кого-то, кто садится и изучает машинный код и создает из этого язык. Шанс на успех для стороннего ассемблера для цели включает использование синтаксиса для инструкций, который похож на синтаксис оригинала, но зачем создавать новый, если вы не собираетесь смешивать его. Синтаксис инструкций является лишь частью всего языка, определенного ассемблером, и вы найдете большие вариации для mips, arm, et c, и с течением времени увеличится для ris c -v, хотя желание создавать новые инструменты имеет резко упал за последние пару десятилетий.

Единственное правило, которому должен следовать успешный ассемблер, это правила, определенные в logi c, синтаксис может быть любым, что они выберут по любой причине, которую они выберут. Поэтому вам нужно спросить каждого автора / команду, хотите ли вы знать, но не уверены, что даже bugzilla вас туда доставит.

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

y = mx + b

, а не

mx + b = y

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

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

Не только для intel, но и для всех основных / второстепенных наборов инструкций вы обнаружите несовместимость синтаксиса между инструментами, x86, arm, mips, msp430, avr, 8051, 6502, z80, et c и, в конечном итоге, ris c -v, если это еще не сделано. Люди, которые добавляют цели в ассемблер gnu, должны гордиться созданием несовместимых языков ассемблера, как они делают это так часто.

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

add r0,r1,r2  ; r0 = r1 + r2 

add r0,r0,r2  ; r0 + r1 -> r2

, а затем имена регистров имеют произвольную форму и иногда различаются. топор,% топор. r0, $ 0

Недавнее (ужасное) увлечение, которое я предполагаю, пришло от mips и его использования в школе v0, a0, t0, et c ... и заразило другие несвязанные наборы инструкций. В наши дни часто происходит искажение привычек различных наборов команд.

они выбирают, как указать косвенность @ r1, (r1), [r1] ...

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

некоторые выбирают 4 (r1), где другой будет использовать в качестве [r1, # 4]

языки первой сборки или интенсивно использовать для человек играет роль в том, как ему нравится обращаться с другими, некоторые люди просто должны создать свой собственный инструмент, чтобы избежать необходимости изучать другой язык или иметь дело с тем, что им не нравится в другом языке, таким образом, это AT & T, возможно, выбор ассемблера gnu. Определенно, как MIPS обрабатывал соглашение о вызовах и как это понятие, функция? Заражало другие инструменты и, возможно, классные комнаты.

Посмотрите на эволюцию языков ассемблера x86 в частности (AT & T и Intel не имеют отношения к тому, что я говорить о) со временем.

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

Краткий ответ, потому что это делают другие языки ассемблера. Поскольку вы можете видеть четкую связь между ris c -v и MIPS в их дизайне, без сомнения, авторы документации также придерживались стиля MIPS, который они использовали, чтобы привести к RIS C -V. Исключения из правила случаются, хотя было бы более пуристическим решением всегда оставлять пункт назначения. Что более важно, так это последовательность, как вы указали. Не имейте один аромат магазина один путь и другой аромат другой. Посмотрите на MRS / MSR в типичном синтаксисе ARM, пункт назначения / источник находится посередине, там же.

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

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

...