首页 > 解决方案 > 与存储内存的顺序有什么关系

问题描述

我一直在尝试并且未能理解内存管理中的 [计算] 偏移量。

我想这样做的原因是因为我需要将一个数组传递给 WASM 来减去它,这是不可能的,因为 WASM 只有数字类型。有人告诉我要实现这一点,我必须计算偏移量并通过 JavaScript 传入类型化数组。

我知道偏移量就是它们听起来的样子 - 从一个地址的位置到另一个地址的距离,但我不完全知道如何计算它。我找到的资源很好地解释了它是什么,但我一辈子都无法找出内存地址之间的关系来计算偏移量。

我不明白如何计算偏移量,因为我不完全知道存储的内存顺序(例如:内存是否以爬升顺序存储,如 0x001、0x002、0x003)。

因此,要回答关于计算偏移量的问题,我必须首先回答主要问题——与存储内存的顺序有什么关系

这一切都让我感到困惑,因为我来自一个高级语言环境,您通常不使用偏移量和内存地址。

我曾经[试图]在这个问题上帮助我的资源:

标签: assemblymemorywebassembly

解决方案


是的,在最简单的层面上,内存就像一个巨大的数组,其元素是字节。
(假设一个普通的现代计算机架构,一个字节可寻址而不是字,平面内存模型等)

更广泛的访问可以一次加载多个字节,作为整数(或作为不在 TypedArray 中的 JavaScript 数字之类的 FP 双精度数)。

数组只是一个地址范围。(或起始地址和长度,或起始地址和结束地址)。通过在 start + offset 的地址访问“内存”来使用数组的偏移量(在实际的 CPU 组件中),其中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 作为一个单独的 arg,这样你就可以循环它。

知道自己长度的数组对象或切片是高级构造,您可以使用包含 2 个指针的数据结构来实现。

我不知道这有多少适用于Web Assembly,抱歉;在那里,您实际上可能会得到一个 TypedArray,它仍然可以进行边界检查以阻止您在数组边界之外写入或读取。在实际 CPU(或 C 语言)的 asm 中,如果您不手动检查index已知长度,或者根据循环逻辑或您从中获取索引的已知内容证明它将在界限内,则没有什么能阻止这种情况。


推荐阅读