AREA ARM, CODE, READONLY
- это метки начала раздела для кода в источнике.
С аналогичной AREA myData, DATA, READWRITE
вы можете начать раздел, где можно определить данные, как data1 DCD 1,2,3
, это будет компилировать как три слова со значениями 1, 2, 3 в последовательных байтов, с ярлыком data1
, указывающий на первый байт первого слова. (некоторые из AREA документов из Google).
Если они приземляются в физической памяти после загрузки исполняемого файла, зависит от того, как связан исполняемый файл (компоновщик использует файл сценария, который помогает ему решить, какой AREA поставить туда и как создать таблицу символов для динамического перемещения исполняемым загрузчиком, отредактировав скрипт компоновщика, вы можете настроить, где код и данные приземляются, но обычно вам не нужно это делать).
Также ссылки на сценарий компоновщика и ассемблера могут влиять на размер доступного стека и где он отображается в физической памяти.
Итак, для вашей конкретной платформы: google для сопоставлений памяти в Интернете и проверки скрипта компоновщика (для начала просто используйте параметр компоновщика для создания файла .map, чтобы увидеть, где код и данные нацелены на приземление).
Таким образом, вы можете объявить этот массив в некоторой области данных, а затем работать с ним, вы загружаете символ data1
в регистр («адрес загрузки данных1») и используете это для извлечения содержимого памяти с этого адреса.
Или вы можете сначала поместить все числа в стек (который, вероятно, является чем-то разумным для загрузчика ОС вашего исполняемого файла), и работать в коде с указателем стека для доступа к номерам в нем.
Вы можете даже DCD
некоторые значения в области CODE
, поэтому эти слова будут заканчиваться между инструкциями в памяти, отображаемыми как только для чтения исполняемым загрузчиком. Вы можете прочитать эти данные, но писать им, вероятно, вызовет сбой. И, конечно же, вы не должны выполнять их как инструкции случайно (забыв поставить инструкцию ret/jump перед DCD
).
без стека
Ну, это один сложно, вы должны быть осторожны, чтобы не использовать любой вызов/и т.д.. и иметь прерывания отключены, и т.д .. в основном любая вещь, которая требует стека.
Когда люди кодируют загрузчик, обычно они устанавливают некоторый временный стек ASAP в первых нескольких инструкциях, поэтому они могут использовать базовые функции стека до правильной настройки всей среды или загрузки ОС. Пространство для этого временного стека часто резервируется где-то в/после кода или неиспользуемое пространство памяти в соответствии с определенным состоянием машины после сброса.
Если вы находитесь на металле без ОС, обычно вся память записывается после сброса, поэтому вы можете смешать код и данные по своему усмотрению (просто прыгайте с данными, не выполняя их случайно), не используя Определения ОБЛАСТИ.
Но вы должны подумать, создаете ли вы приложение в пространстве пользователя какой-либо ОС (так что у вас есть такие вещи, как области стека и данных, и вы можете использовать их для вашего удобства), или вы создаете загрузчик код, который должен установить все для себя (более сложный, поэтому я бы предложил сначала перейти на пользовательскую территорию какой-либо ОС, причем обертка C с инициализированным клипом тоже очень удобна, поэтому вы можете называть такие вещи, как printf
от ASM для удобный выход).
Как я могу работать со значениями заявленных таким образом
Это не имеет значения в машинном коде, в каком направлении были объявлены значения. Все, что имеет значение, - это если у вас есть адрес памяти, и если вы знаете структуру, то как хранятся данные. Затем вы можете работать с ними любым способом, используя любую желаемую команду. Таким образом, тело этого примера asm не изменится, если вы выделите данные в ASM, вы просто передадите указатель в качестве аргумента, как это делает C.
редактировать: некоторые примеры вслепую без тестирования, может потребоваться дальнейшее закрепление синтаксиса для работы OP (или, может быть, есть даже какая-то ошибка, и он не будет работать вообще, дайте мне знать в комментариях, если он сделал):
AREA myData, DATA, READWRITE
SortArray
DCD 5, 4, 1, 3, 2, 12, 55, 64, 77, 10
SortArrayEnd
AREA ARM, CODE, READONLY
CODE32
PRESERVE8
EXPORT __sortasmarray
__sortasmarray
; if "add r0, pc, #SortArray" fails (code too far in memory from array)
; then this looks like some heavy weight way of loading any address
; ldr r0, =SortArray
; ldr r1, =SortArrayEnd
add r0, pc, #SortArray ; address of array
; calculate array size from address of end
; (as I couldn't find now example of thing like "equ $-SortArray")
add r1, pc, #SortArrayEnd
sub r1, r1, r0
mov r1, r1, lsr #2
; do a direct jump instead of "bl", so __sortc returning
; to lr will actually return to called of this
b __sortc
; ... rest of your __sortc assembly without change
Вы можете вызвать его из кода C, как:
extern void __sortasmarray();
int main()
{
__sortasmarray();
return 0;
}
Я среди других это Introducing ARM assembly language, чтобы освежить свою память ARM ассемблера, но я до сих пор беспокоит это может не работать, как есть.
Как вы можете видеть, я не изменил любой вещь в __sortc
. Поскольку нет никакой разницы в доступе к стековой памяти или памяти «dcd», это одна и та же память компьютера.После того, как у вас есть адрес к определенному слову, вы можете использовать ldr/str с его адресом. __sortc
получает адрес первого слова в массиве для сортировки в обоих случаях, оттуда на нем есть только память для него, без какого-либо контекста, как эта память была определена в источнике, выделена, инициализирована и т. Д. Пока это возможно для записи, это нормально для __sortc.
Таким образом, единственная связанная с «dcd» вещь - это загрузка адреса массива, а быстрый поиск примеров ARM показывает, что это может быть сделано несколькими способами, этот способ add rX, pc, #label
оптимален, но работает только для диапазона + -4k ? Есть также псевдо-инструкция ADR rX, #label
, делающая то же самое, и, возможно, переключение на другое в случае проблемы диапазона? Для любого диапазона это выглядит как форма ldr rX, = label
, хотя я не уверен, что это псевдо-инструкция или как она работает, проверьте некоторые обучающие программы и разберите машинный код, чтобы увидеть, как он был скомпилирован.
Это зависит от вас, чтобы узнать все особенности сборки ARM и как загружать адреса массивов, в настоящий момент мне не нужна ARM ASM, поэтому я не вникнул в эти детали.
И должен быть некоторый способ определения длины массива, вместо вычисления его в коде с конечного адреса, но я не смог найти ни одного примера, и я не буду читать полные документы Ассемблера, чтобы узнать о них все его директивы (в gas
я думаю, ArrayLength equ ((.-SortArray)/4)
будет работать).
Спасибо за ответ! Не могли бы вы привести краткий пример того, как я могу работать с массивом 'READWRITE' и писать из него + из перспективы сортировки, как менять значения. – fyfdzbgz
@fyfdzbgz Я даже не знаю, какой ассемблер вы используете, и на какой платформе, и даже если бы я хотел, у меня только активная платформа ARM в форме Android NDK с ассемблером 'gas', но ваш синтаксис выглядит как какой-то ассемблер от MDK-ARM, как я связал эти документы. И я не собирал ARM-сборку за ~ 10y, и очень немногие из них тогда (я делал GameBoy Advance, но 99% кода было C++, конечно, просто проверяя вывод компилятора для упрощения C++, если компилятор запутался слишком много). Поэтому я попытаюсь добавить несколько примеров в ответ, но я сделаю их слепо без тестирования, извините. – Ped7g
@fyfdzbgz Я добавил что-то, но в целом большая часть материала, который вы просите, уже есть в вашем исходном источнике, поэтому, возможно, вам нужно просто больше копаться в примерах и документах, перечитывать их несколько раз ... помните о каждом новом опыт уже прочитанных документов может иметь больше смысла, возможно, объясняя, о чем вы просите. Также проводите некоторое время в отладчике, выполняющем отдельные инструкции, отслеживая изменение состояния процессора и сравнивая это с инструкцией по инструкции для каждой инструкции, чтобы получить «почувствовать», как это работает. И перечитывать весь список инструкций время от времени, чтобы знать о них. – Ped7g