Как работает разветвление / циклы сборки и функции - PullRequest
0 голосов
/ 11 сентября 2018

Сегодня у нас был первый урок на Ассамблее.Лектор мало что объяснил, так как идея была в том, что мы должны использовать книги, чтобы прочитать, как работает сборка.Мой опыт программирования - Python и C ++, и переход к сборке делает его кощунственным, даже если подумать о том, чтобы прыгать назад и вперед в коде.

Когда я говорю о ветвлении, меня беспокоит проблема, которая, кажется, нигде не объясняется в моей книге.По сути, OP-код B + (EQ, PL и т. Д.) Выполняет ветвления в соответствии с условиями и флагами.Например, «BEQ location» будет переходить в «location», если .... то есть, если что.Из того, что я смог разобрать, он использует предыдущую инструкцию, чтобы выяснить условие (в этом случае, если что-то равно (Z = 1)).Если это правда, что BEQ будет смотреть на возвращение предыдущей инструкции для оценки EQ, как я могу, например, сделать цикл, где первый R0 (регистр 0) получает значение 0, а затем что-то еще происходит и в конце я хочу сделатьусловная ветвь, которая проверяет, равен ли R0 нулю?

Вопрос 2: Я также заметил, что если вы выполняете какую-то функцию:

WhileLoop:
     MOV R0, R1
     ..bla bla bla
     BEQ WhileLoop

Как я узнаю, что BEQ возвращается к"WhileLoop"?Означает ли это, что для каждой функции, которую я делаю, мне нужно называть это чем-то другим.Может быть, я не правильно понимаю функции.

Пожалуйста, помогите.

1 Ответ

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

Вам необходимо прочитать документацию ARM. Ответы на ваши вопросы есть.

Да, ARM использует флаги. Как и в случае с любым набором команд, который использует флаги, вам необходимо изучить каждую инструкцию, которую вы используете или хотите использовать, или для общего понимания, что если какие-либо флаги они изменят. Например, операция И имеет ли смысл устанавливать флаг переноса? Нет, но имеет ли смысл устанавливать нулевой флаг? Конечно, это может быть полезно, или иногда они устанавливают нулевой флаг, а AND - нет, зависит от архитектуры.

В отличие от вашего типичного решения flag basd, у ARM какое-то время был поворот, вы должны спросить инструкцию, чтобы установить флаги. Если вы заметили

loop:
  sub r0,#1
  bne loop

делает не то, что вы хотите, потому что, как написано (согласно документам об оружии), вычитание НЕ касается каких-либо флагов, в частности, флага Z, который мы тестируем, но ...

loop:
  subs r0,#1
  bne loop

Этот код, вычитание ДОЛЖЕН касаться флага Z.

Это позволяет такие вещи, как

  cmp r2,r3
  moveq r1,#1
  bxeq lr
  mov r1,#0
  bx lr

Или сказать

  if(foo==1)
  {
     bar++;
  }

обычно вам нужно реализовать это как

compare with 1
branch if not equal to skip
increment
skip:

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

но вместо

compare with 1
increment if equal

условное выполнение, условные биты.

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

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

Так что не уверен, что вы спрашиваете о функциях, во-первых, на языке ассемблера вы часто можете использовать метки, такие как WhileLoop. Ассемблер превращает это в правильную инструкцию, хотя Loop не является инструкцией, это в основном адрес, в этом случае ассемблер должен использовать запрошенную вами инструкцию и сделать относительное смещение ПК (фиксированный адрес не используется, он подсчитывает, как много инструкций между меткой и beq и говорит, что если равны ветви назад N инструкций). если вы добавили beq к какой-либо метке, которая определена в другом модуле / объекте, компоновщик должен будет позже исправить инструкцию.

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

У ассемблера gnu есть интересная особенность, которая не дает оснований предполагать поддержку других языков ассемблера (язык ассемблера определяется ассемблером, инструментом, а НЕ целью (набором инструкций ARM)), очень легко продемонстрировать это для многих различных наборы инструкций, легкая в написании сборка руки, которая не собирается во всех активно поддерживаемых ассемблерах. Итак, вот трюк с ассемблером GNU, который может помочь, а может и не помочь с метками

1:
 subs r0,#1
 beq 1f
 b 1b
1:

Обычно вы хотели бы просто выполнить bne, но это демонстрирует эту функцию. метка, представляющая собой число, является специальной, 1f означает метку 1: вперед, поэтому следующая метка 1: вниз по странице. 1b означает 1: назад, поэтому с этой точки прочитайте страницу назад, чтобы найти следующую 1: так что вам не нужно делать

myfunction:
...
myfunction00:
...
myfunction01:
...
myfunction02:
...

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

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

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