Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly 如何注册段前缀mov/lea?_Assembly_X86 64_Segment - Fatal编程技术网

Assembly 如何注册段前缀mov/lea?

Assembly 如何注册段前缀mov/lea?,assembly,x86-64,segment,Assembly,X86 64,Segment,我知道在微型内存模型中,段寄存器持有相同的值。(除了%fs,%gs)。这里有一个相关主题: . 但如果段寄存器持有不同的值呢?例如,我们可以通过指针将地址传递给函数: mov %fs:(%rax),%rsi mov %ds:(%rax),%rsi 考虑到%fs和%ds拥有不同的基址。函数可以同时使用这两种引用。那么函数是否能够区分它们?寄存器实际包含的是什么?或者这种情况不存在?在x64下,ss、cs、ds和es段都具有相同的值,即0。 fs和gs段用于不同的目的 Windows fs指向当

我知道在微型内存模型中,段寄存器持有相同的值。(除了%fs,%gs)。这里有一个相关主题: . 但如果段寄存器持有不同的值呢?例如,我们可以通过指针将地址传递给函数:

mov %fs:(%rax),%rsi
mov %ds:(%rax),%rsi

考虑到
%fs
%ds
拥有不同的基址。函数可以同时使用这两种引用。那么函数是否能够区分它们?寄存器实际包含的是什么?或者这种情况不存在?

在x64下,
ss
cs
ds
es
段都具有相同的值,即0。
fs
gs
段用于不同的目的

Windows
fs
指向当前进程的32位线程信息块。
gs
指向当前进程的64位TIB

Linux
在32位内核中,
fs
是每cpu数据区的基础。在一个 64位内核
gs
指向pda(处理器数据区)。pda是一个 单一结构,而每cpu数据是每cpu 变量被放入

fs
用于在64位操作系统(例如WoW64)上运行32位代码

x86中的寄存器过去有特殊用途,但现在大多数寄存器都是通用的

rsi
可用于任何目的。
只有在字符串指令中,它才具有特殊意义。
在该上下文中,它用于指向源(例如)

那么函数是否能够区分它们呢

通过使用段前缀作为指令的前缀

mov rsi,[rax]     // rsi = memory(rax).
xor eax,eax       //rax =0 (remember 32 bit instructions zero extend)
mov rsi,[gs:rax]  //load the first 8 bytes of the 64-bit TIB into rsi.
关于lea
Lea不访问内存,它只进行计算而不改变标志。
这些计算通常涉及计算指针,但也可以是一般的算术运算。

将段前缀放在lea前面没有意义,也没有效果

什么操作系统?在Windows的情况下,至少有一些或可能所有的每线程值(如rand()的种子值)从fs:。。。进入线程的虚拟地址空间,然后可以使用普通指针。由于进程中的线程共享虚拟地址空间,每个线程变量都将通过不同的指针值进行访问。因此,即使
[gs:rax]
[ds:rcx]
实际上拥有相同的线性地址,函数也必须用两段代码分别处理它们。x86_64中的“微型内存模型”是什么?在16b模式下,它是这样使用的,但在那里,段值是物理地址的一部分(添加到最终20b地址的第4位到第19位)不清楚如何将指针传递给此类代码(在
rax
?),但如果
fs
不同
ds
,则每个
mov
将使用不同的逻辑内存地址(如果内存以这种方式映射,它仍然可能映射到相同的物理地址,但从逻辑角度来看,这些指令正在访问不同的内存,第一个指令
fs:rax
,另一个指令
ds:rax
…无论x86_64中的含义是什么(描述符表中的一些索引?)两条汇编语句都从内存中的某个位置读取64位值并存储在RSI中。这两条语句都不会将函数的地址加载到RSI中,除非该函数的地址以前存储在被读取的位置。第一条指令读取的内存中的位置位于线性地址
FS.base+RAX
,而re
FS。base
是FS段的基址。第二个读取的内存位置位于线性地址
RAX
。在64位模式下,DS段的基址始终为0。@Ped7g我看到了“微型内存模型”在另一个主题中,这意味着段寄存器共享相同的值。我实际上想知道函数如何知道应该使用哪个段寄存器访问数据,因为地址是从单个寄存器传递的。很抱歉,我的代码很混乱…取决于您所处的模式。段寄存器在16b实模式下很重要(DOS)(因为您只有16b的偏移量=64ki的最大内存)。在64b模式(linux中)中,用户地内存模型是“平面内存映射”:一个64b的数字足以寻址所有内存(最多2^64个限制)而且您不需要按段重写指令,默认的
ds
/
ss
都设置为相同的值,因此您只使用64b偏移量。我不喜欢OS开发,所以我不知道它在内核中是什么样子,也许它们使用了更复杂的内存映射。fs/gs可能对帮助并行性有额外的意义。