Как получить инструкции по сборке? - PullRequest
1 голос
/ 26 января 2020

Чтобы прояснить вопрос о названии, предположим, что я объявил следующий массив в C ++,

int myarr[10];

Это разбирается на следующее в x86

myarr:
    .zero   40

Теперь, AFAIK this * Директива 1007 * используется для обозначения и не является инструкцией. Тогда как именно эта директива переводится в инструкции x86 (или любой другой архитектуры, здесь не главное)? Потому что, насколько мы знаем, процессор может выполнять только инструкции. Итак, я полагаю, что эти директивы каким-то образом переведены в инструкции, я прав?

Я мог бы обобщить вопрос, также задав вопрос: .word .long et c. переводятся в инструкции, но я думаю, что это понятно.

Ответы [ 2 ]

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

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

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

Чтобы собрать директиву .zero 40, компилятор включает в себя только сорок байтов нулей в разделе, которым он является в настоящее время. здание. Когда он пишет окончательный результат, он будет включать эти нули в этом разделе. Директивы данных, подобные этим и .word, и такие просто говорят ассемблеру, какие данные поместить в его вывод.

1 голос
/ 26 января 2020
unsigned int stuff[10];
void fun ( void )
{
    unsigned int r;
    for(r=0;r<10;r++) stuff[r]=r;
}

с использованием ARM ...

00000000 <fun>:
   0:   e3a03000    mov r3, #0
   4:   e59f2010    ldr r2, [pc, #16]   ; 1c <fun+0x1c>
   8:   e5a23004    str r3, [r2, #4]!
   c:   e2833001    add r3, r3, #1
  10:   e353000a    cmp r3, #10
  14:   1afffffb    bne 8 <fun+0x8>
  18:   e12fff1e    bx  lr
  1c:   00000ffc

Disassembly of section .bss:

00001000 <stuff>:
    ...

Массив - это просто данные, это не код, это не инструкции и не будет, директива, о которой вы спрашивали, не будет становитесь кодом, он не может быть данными.

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

Глядя на фактический вывод этого компилятора (комментарии и другие несущественные элементы удалены)

fun:
    mov r3, #0
    ldr r2, .L6
.L2:
    str r3, [r2, #4]!
    add r3, r3, #1
    cmp r3, #10
    bne .L2
    bx  lr
.L7:
    .align  2
.L6:
    .word   stuff-4
...
    .comm   stuff,40,4

.comm в этом случае - это то, как они объявили данные, которые представляют массив на языке высокого уровня. а другие вещи в основном код. .align существует для того, чтобы адрес L6 был выровнен, так что вы не получите ошибку выравнивания при попытке прочитать его.

.word - это директива, здесь вы видите .text vs .data, в то время как это всего лишь одна простая C программа с массивом и кодом прямо рядом друг с другом. потому что код, возможно, может жить в памяти только для чтения, такой как fla sh, а данные должны находиться в памяти чтения / записи, и во время компиляции компилятор не знает, где находятся данные относительно кода, поэтому он генерирует абстракцию, помещая слово только для чтения в коде, который компоновщик заполняет позже, код является обобщенным c и что бы там ни вставлял компоновщик, он использует его. Компоновщик "помещает" .text и .bss в этом случае он не был инициализирован, поэтому он фактически не является .data, а затем устанавливает это соединение в коде.

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

  1c:   00000ffc 

Disassembly of section .bss:

00001000 <stuff>:
    ...

и, исходя из того, как я связал эту (не фактически работающую) программу, это единственный элемент данных в этой программе, и компоновщик разместил его там, где я спросил адрес 0x1000, затем вернулся и заполнил эту директиву .word, чтобы она была stuff-4, которая равна 0xFF C, так что код скомпилированный работает. Директивы

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

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

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

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