如何指定应使用哪个段寄存器 (x86)
How is it being specified which segment register should be used (x86)
这是一个函数:
void func(char *ptr)
{
*ptr = 42;
}
这是 gcc -S function.c 的输出(剪切):
func:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movq %rdi, -8(%rbp)
movq -8(%rbp), %rax
movb , (%rax)
nop
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
我可以将该函数用作:
func(malloc(1));
或如:
char local_var;
func(&local_var);
问题是处理器如何确定该指令中应该使用哪个段寄存器将有效地址转换为虚拟地址(可能是DS也可能是SS)
movb , (%rax)
我有一个 x86_64 过程。
默认段为DS;这就是处理器在您的示例中使用的内容。
在 64 位模式下,使用什么段并不重要,因为段基数始终为 0,权限将被忽略。 (还有一两个细微差别,这里就不赘述了。)
在 32 位模式下,大多数操作系统将所有段的基数设置为 0,并将它们的权限设置为相同,所以同样无所谓。
在重要的代码中(尤其是需要使用超过 64 KB 内存的 16 位代码),代码必须使用远指针,其中包括段选择器作为指针值的一部分。软件必须将选择器加载到段寄存器中才能执行内存访问。
这是一个函数:
void func(char *ptr)
{
*ptr = 42;
}
这是 gcc -S function.c 的输出(剪切):
func:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movq %rdi, -8(%rbp)
movq -8(%rbp), %rax
movb , (%rax)
nop
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
我可以将该函数用作:
func(malloc(1));
或如:
char local_var;
func(&local_var);
问题是处理器如何确定该指令中应该使用哪个段寄存器将有效地址转换为虚拟地址(可能是DS也可能是SS)
movb , (%rax)
我有一个 x86_64 过程。
默认段为DS;这就是处理器在您的示例中使用的内容。
在 64 位模式下,使用什么段并不重要,因为段基数始终为 0,权限将被忽略。 (还有一两个细微差别,这里就不赘述了。)
在 32 位模式下,大多数操作系统将所有段的基数设置为 0,并将它们的权限设置为相同,所以同样无所谓。
在重要的代码中(尤其是需要使用超过 64 KB 内存的 16 位代码),代码必须使用远指针,其中包括段选择器作为指针值的一部分。软件必须将选择器加载到段寄存器中才能执行内存访问。