Каково отношение к порядку хранения памяти

#assembly #memory #webassembly

#сборка #память #webassembly

Вопрос:

Я пытался и не мог понять [вычисление] смещений в управлении памятью.

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

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

Я не понимаю, как вычислить смещение, потому что я точно не знаю порядок хранения памяти (например: хранится ли память в порядке возрастания, например 0x001, 0x002, 0x003).

Итак, чтобы ответить на вопрос о вычислении смещения, я должен сначала ответить на главный вопрос — каково отношение к порядку хранения памяти.

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

Ресурсы, которые я использовал, чтобы [попытаться] помочь мне по этому вопросу:

Ответ №1:

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

Более широкий доступ может загружать несколько байтов одновременно, как целое число (или как FP double, как числа JavaScript, которых нет в TypedArray).

Массив — это просто диапазон адресов. (Или начальный адрес и длина, или начальный и конечный адреса). Смещения в массив используются (в реальной сборке процессора) путем доступа к «памяти» по адресу start offset , где start это адрес первого элемента массива. например, в сборке x86-64 mov eax, [rdi rsi*4] / ret реализует функцию C.

 int32_t idx_arr(int32_t *array_start, size_t index) {
    return array_start[index];        // mov eax, [rdi   rsi*4]
}
 

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

Забавный факт, return *(array_start index); точно идентичен, потому что C определяет оператор [] в терминах математики указателей. И обычно вы просто вызываете свой указатель arg array ; Раньше я array_start подчеркивал, что в сборке вы обычно просто получаете указатель на начало, а иногда и длину или end_ptr как отдельный аргумент, чтобы вы могли перебирать его.

Объект массива или фрагмент, который знает свою собственную длину, является высокоуровневой конструкцией, которую вы могли бы реализовать со структурой данных, содержащей 2 указателя.

Я не знаю, насколько это применимо к веб-сборке, извините; там вы можете фактически получить TypedArray, который все еще может выполнять проверку границ, чтобы помешать вам записывать или читать за пределами границ массива. В asm для реальных процессоров (или в C) ничто не мешает этому, если вы вручную не проверите index на известную длину или не докажете, что она будет находиться в границах, основанных на логике цикла или известном содержимом того, откуда вы получили индекс.

Комментарии:

1. Ха, мне придется прочитать это немного подробнее. Итак, смещение в некотором роде вычисляется в увеличении или уменьшении размера, но насколько я говорю. Это 1 для каждого адреса памяти, 2 и т. Д.? Вычислить смещение легко, но я не могу этого сделать, не зная, как хранится память.

2. @Реальность: да, первый байт памяти имеет адрес 0, следующий имеет адрес 1 и так далее. (В виртуальном адресном пространстве вашего процесса обычно у вас фактически не отображается адрес 0.) Но в любом случае да, соседние байты разделены на 1 адрес. (Это то, что подразумевает массив байтов). Соседние 4-байтовые int32 находятся на расстоянии 4 адресов друг от друга, поэтому вы масштабируете индекс C на 4 = sizeof(int32_t) при реализации в x86 asm. WASM может выполнить масштабирование за вас, я не знаю, но если это так, то вы бы просто выполняли индексацию массива, как в JavaScript.

3. Ах, это имеет смысл. Это также зависит от размера байтов, что имеет смысл (поскольку в нем хранятся байты). Хорошо, мне все равно придется немного поэкспериментировать, но, по крайней мере, я знаю немного больше о том, что я делаю. Спасибо!