我有一个汇编/c 问题。我刚刚读到了有关段前缀的内容,例如 ds:varX 等。前缀对于逻辑地址的计算很重要。我也读到,默认值是“ds”,一旦您使用 ebp 寄存器来计算地址,就会使用“ss”。对于代码“cs”是默认值。这一切都是有道理的。
现在我在c中有以下内容:
int x; // some static var in ds
void test(int *p){
...
*p =5;
}
... main(){
test(&x);
//now x is 5
}
如果您现在考虑测试函数的实现...您会在堆栈上获得指向 x 的指针。如果要取消引用指针,首先从堆栈中获取指针值(x 的地址)并将其保存在例如 eax 中。然后您可以取消引用 eax 来更改 x 的值。但是,c 编译器如何知道给定的指针(地址)是否引用堆栈上的内存(例如,如果我从另一个函数调用 test 并将局部变量的地址作为测试参数推送)或数据段?完整的逻辑地址是如何计算的?该函数无法知道给定地址偏移量与哪个段相关..?!
一般情况下,在分段平台上,您不能只将指针值读入“eax
“正如您所建议的。在分段平台上,指针通常会同时保存段值和偏移值,这意味着读取这样的指针意味着至少要初始化two寄存器 - 段和偏移量 - 不仅仅是一个eax
.
但在特定情况下,它取决于所谓的内存模型。分段平台上的编译器支持多种内存模型。
对于初学者来说,出于显而易见的原因,这并不重要which只要段寄存器保存正确的值,您就可以使用段寄存器。例如,如果DS
and ES
寄存器内部保存相同的值,然后DS:<offset>
将指向内存中相同的位置ES:<offset>
.
例如,在所谓的“微小”内存模型中,all段寄存器保持相同的值,即所有内容 - 代码、数据、堆栈 - 都适合一个段(这就是它被称为“微小”的原因)。在这个内存模型中,每个指针只是该段中的一个偏移量,当然,使用哪个段寄存器来处理该偏移量并不重要。
在“更大”的内存模型中,您可以为代码 (CS)、堆栈 (SS) 和数据 (DS) 提供单独的段。但在这样的内存模型上,指针对象通常会保存both其中地址的偏移量和段部分。在你的示例指针中p
实际上是一个由两部分组成的对象,同时保存段值和偏移值。为了取消引用此类指针,编译器将生成从以下位置读取段值和偏移值的代码:p
并同时使用它们。例如,段值将被读入ES
寄存器,而偏移值将被读入si
登记。然后代码将访问ES:[di]
为了阅读*p
value.
还有“中间”内存模型,其中代码存储在一个段(CS)中,而数据和堆栈都存储在另一段中,因此DS
and SS
将保持相同的值。显然,在该平台上,没有必要区分DS
and SS
.
在最大的内存模型中,您可以有多个数据段。在这种情况下,很明显,分段模式下正确的数据寻址实际上并不是选择正确的段寄存器的问题(正如您似乎相信的那样),而是采取相当多的方法的问题any段寄存器并在执行访问之前使用正确的值对其进行初始化。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)