【问题标题】:MASM32 Memory LocationsMASM32 内存位置
【发布时间】:2009-02-15 00:44:44
【问题描述】:

我正在尝试使用 masm32 程序集从主内存中读取数据,为了做到这一点,我创建了(如之前在此处对我的另一个问题的回答中所建议的那样)一个数组,该数组将包含非常分离的内存位置(为了避免从缓存中读取)。 我已经设法创建了数组并让它被读取,但是,我有一个问题。我已经做过并测试过的这个数组正在使用我给它的数据(即数字)并且一切正常。但是我需要内存位置,但我在任何地方都找不到地图或对这些位置的引用。我的意思是我需要类似的东西:

my_arr db 5, 2, 8, 9, 1, 7, 3, 0, 4, 6

但我不应该使用数字,而是应该使用相应的内存位置保留字。但我找不到它们 =( 甚至不知道还要寻找什么。


编辑

让我检查一下是否正确,然后您告诉我可以(而不是使用数组,而是使用变量之间的所有空格来强制从主内存读取?

【问题讨论】:

  • 是的,我在想一个循环,比如“top_of_loop: al[my_var_1]; mov al[my_var_2]; ... etc ...; dec cx; jnz top_of_loop;”
  • 不清楚你的问题是什么:你知道你想实现什么算法,但不知道如何在汇编中实现它?如果是这样,请用 C 或伪代码发布您的算法以说明它。

标签: assembly x86 masm32


【解决方案1】:

正如你所说,这是一个(连续的)字节数组:

my_arr db 5, 2, 8, 9, 1, 7, 3, 0, 4, 6

这是一个占用 10 MB 的变量(相对于 CPU 缓存来说很大):

wasted_space BYTE 10485760 DUP(?)

这里有几个变量,它们之间有很多浪费的空间:

my_var_1 db 5
spacer_1 BYTE 10485760 DUP(?)
my_var_2 db 2
spacer_2 BYTE 10485760 DUP(?)
my_var_3 db 8
spacer_3 BYTE 10485760 DUP(?)
my_var_4 db 9
spacer_4 BYTE 10485760 DUP(?)
my_var_5 db 1
spacer_5 BYTE 10485760 DUP(?)
my_var_6 db 7
spacer_6 BYTE 10485760 DUP(?)
my_var_7 db 3
spacer_7 BYTE 10485760 DUP(?)
my_var_8 db 0
spacer_8 BYTE 10485760 DUP(?)
my_var_9 db 4
spacer_8 BYTE 10485760 DUP(?)
my_var_10 db 6

这(在您的数据段中创建变量)是获取一些数据内存地址的一种方法(变量不包含地址......相反,变量位于地址处)。

另一种获取内存地址的方法是调用 O/S API,它从堆中分配内存并返回所分配内存的地址,例如 HeapAlloc 或 VirtualAlloc API。


我不知道您为什么在 ASM 中这样做(学习汇编除外)。如果要学习缓存,我认为您也可以使用 C 来做到这一点(而且更容易)。

无论如何,我对缓存很好奇:多少空间足以导致缓存未命中?需要多少个不同的变量才能开始导致未命中(假设缓存是拆分的,因此可以包含多个(但只有少数)宽间距的内存缓存)?

显然,多年来,它(缓存)已成为一个复杂的主题。 http://lwn.net/Articles/252125/ 是一篇链接自维基百科的文章。本文包括一些图表,例如图 3.11:多个尺寸的顺序读取

【讨论】:

  • 我不熟悉 MASM 是如何构建它的目标文件的,但是那些间隔可以让你的 obj 文件变得很大。您可以使用 'org' 语句执行相同的操作,将每个变量放在不同的地址。
  • 谢谢(我已经忘记了 MASM 的大部分内容)。 DUP(?) 的意思是不要将它初始化为任何特别的东西,所以我不知道它是否会占用可执行文件中的空间。
【解决方案2】:

Assembly 中的间接内存访问

要将数组中的字节视为内存地址,您需要将它们加载到可以用作基地址的寄存器中,然后访问该寄存器指向的内存:

MOV AX, [MY_ARR+3]  ; Element 3 in array, that is 9
MOV BX, [AX]        ; Read from that address

关于缓存

请注意,您的缓存可能比该数组所覆盖的内存地址范围大得多,因此所有内容都可以放入缓存中。

另外,请考虑您的缓存可能是关联的,这意味着如果相距很远的地址碰巧不在同一(完整)缓存行上,则它们可以一起放入缓存中。

要真正用完缓存并保证您必须直接访问内存,您应该(在循环中)访问一组比缓存更大的连续内存位置。 IE。创建一个与缓存一样大的数组。还要考虑到可能有多层缓存(L1、L2,可能还有 L3 甚至更多),所以你需要多大取决于你想要溢出的缓存。


我曾经用 C 语言编写了一个程序来计时内存和缓存访问,并通过一些统计计算和补偿时间测量开销(在如此短的时间范围内是不可忽略的),得到了非常准确的结果(通过运行更长时间的测试并等待标准偏差下降,可以根据需要使其尽可能准确)。

然而,我的程序并不是最有效的方法,而且也没有过多地暗示缓存的关联性(我必须根据配色方案的知识单独测量)。然而,两者都以相对独立于架构的方式相当有效地完成,并在SIGMETRICS 2005 work of Larry McVoy and Carl Staelin 中使用了一些深思熟虑的技巧。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-24
    • 2012-10-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多