数组的偏移量是如何表示数组的起始地址的 [英] How did offset of an array come to mean the starting address of an array
问题描述
mov edi, offset newarray
据我所知,这将把
newarray
的地址放入寄存器edi
我不明白的是
offset
这个词的英文意思是什么?
适合这里。
推荐答案
x86内存地址的格式为segment:offset
,其中偏移量部分位于普通(通用)寄存器中,如edi(或64位代码中的rdi)。
在我们使用平面内存模型的现代系统中,segment
基数始终为0,offset
是整个地址,等于线性地址。
mov eax, [rdi + rax*4 + 1234]
的x86-64寻址:
RDI是addressing mode中的基址寄存器。
- RAX是索引(因为它具有比例因子,或
[rdi+rax]
中的第二个寄存器) - 1234是位移,编码为双字(Disp32)符号-扩展到64位
- RAX是索引(因为它具有比例因子,或
RDI + RAX*4 + 1234
是通过寻址模式计算有效地址。(因此,lea eax, fs:[rdi + rax*4 + 1234]
为您提供了这一点,即使FS段基数不为零。)这是seg:off地址的偏移量部分。RDI作为基址寄存器表示DS段。
seg:off
-线性地址为DS_base + offset
。(它等于偏移量,因为在64位模式下,CS、DS、ES和SS基数固定为0,而在32位模式下,主流操作系统将它们设置为0。)线性地址是虚拟地址,因为64位模式要求启用分页。
通过在页表中查找页码部分(位于底部12以上的位)来进行Virt-&phys转换,页表由TLB缓存。(Why in x86-64 the virtual address are 4 bits shorter than physical (48 bits vs. 52 long)?)。生成的物理地址用于访问内存(通过缓存),如果PHY地址是设备地址,则用于通过PCIe访问MMIO。
OFFSET my_array
。(当然,在64位模式下,您可能需要lea rdi, [my_array]
这样的RIP相对LEA,但在32位模式下,您需要的是mov edi, OFFSET my_array
。)
操作系统负责确保CS、DS、ES和SS的段基地址为
0
,因此[ebx]
和[ebp]
在EBX=EBP时访问相同的线性地址。(使用EBX或EBP作为寻址模式的基址寄存器,隐含DS与SS段。)
和call ebx
将从您可以使用mov dword ptr [ebx], 0C3909090
(3x nop+ret)读取或写入的相同内存地址获取代码。
旧式16位实模式代码通常需要确保DS段基数设置为匹配数据段的开始。或大型程序中的数据段。**(在实模式下,mov ds, ax
写入段寄存器将设置基数=value<<4
,而不是将该值用作选择器索引the GDT或LDT。)
例如,DOS.exe
程序通常以
PROC main
mov ax, @data ; segment for the data section
mov ds, ax
mov es, ax
mov bx, OFFSET other_var
mov ax, [bx] ; relies on DS being set properly
mov [some_var], ax ; also relies on DS; uses the offset of some_var in the addressing mode.
...
您可以在设置DS之前mov bx, OFFSET some_var
,然后取消引用它。段和偏移量部分是独立的。
同样,旧式BIOS MBR引导加载程序需要将DS设置为与它们假定的org
值匹配,否则它们会访问内存中的错误位置。
这篇关于数组的偏移量是如何表示数组的起始地址的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!