您的问题实际上充满了地雷,这将不幸地证明为什么装配的准确性如此重要。
所以,我所拥有的是...
你显示语法不正确的匿名结构,突然你有一些指针?它不是那样工作的。你有匿名结构和几个语法错误,仅此而已。
现在在这里,我真的很乐意停止回答,因为如果没有数据的实际定义,您的问题的其余部分就毫无意义。但是,假设您有这样的想法:
struct STRUCT_A {
char str[17];
int x;
float a;
};
STRUCT_A testA[3]{
{"a1", 1111, 1.111},
{"a2", 2222, 2.222},
{"a3", 3333, 3.333}
};
int foo(unsigned index) {
return testA[index].x;
}
所以,我在这里拥有的是 array testA
。数组不仅仅是指针,在编译期间它在 C++ 中还有一点点,虽然它会很高兴地“衰减”成指针,但它并不完全相同。
当我将testA
用作指针时,它不会指向任何进一步的指针,它直接指向数据。
所以你在 OP 中没有一层,而是两层额外的间接。要阅读x
第一个元素,您只需执行mov eax,[testA + 20]
. 未加载指针(示例来自 x86 32b 目标,在其他目标上+20
可能不同)。
你会不会:
STRUCT_A* testA_alias = testA;
// now this ^^ alias is no more array, it's just pointer
// (array silently decays into pointer during compilation, when asked to)
STRUCT_A** testA_indirect = &testA_alias;
然后获取x
第二个元素:
mov eax,[testA_indirect] ; eax = &testA_alias
mov eax,[eax] ; eax = testA (or &testA .. not sure how to write it, "address of data")
mov eax,[eax + 28*1 + 20] ; eax = testA[1].x
我设法创建了两个间接级别(实际上我不得不在这部分编辑答案,因为我从 C++ 错误地读取了程序集,不完整的 Intel 语法让我感到困惑)。
我仍然不确定你从哪里得到所有这些指针,为什么?它不是 Java,而是 C++,您只需将数据直接保存在内存中。如您所见,我必须付出相当多的努力才能获得两个间接级别。
现在您可能想知道为什么x
是 at+20
而不是 at +17
。因为padding,C++会根据结构成员的类型来对齐结构成员,int
喜欢对齐,就是这样。
这也应该解释28
,这是该结构的大小。
在您的问题中,您还有:
step2结果+n+1
那是+1
从哪里来的?也许你对此感到困惑:
char str[]{"abc"}; // str[4]
但那是因为"abc"
is like db 'a', 'b', 'c', 0
= 定义了四个字节。当您仅将 a、b、c 定义为三个字节时,数组将是 3 个字节:
char str2[]{'a', 'b', 'c'}; // str2[3]
当您通过 定义该char
数组时[n]
,不涉及 +1,该数组完全具有n
字符。如果将 C 字符串文字放入其中,它们最多可能有 (n-1) 个字符长,因为第 n 个字节将被零终止符占据。
您可以在此处查看该源代码在编译后的外观。
这可能会以最好的方式回答您的问题。
您可能需要特别注意内存内容定义,我在testA
数组定义的初始行添加了一些注释:
testA:
.string "a1" ; three bytes 'a', '1', 0 defined
.zero 14 ; remaining 14 zeroed to have char[17]
.zero 3 ; padding for "int x"
.long 1111 ; int x
.long 1066284351 ; float a
.string "a2" ; char[17] of second element
...