gcc x86/x86_64 ABI:ss必须等于ds/es/fs/gs吗?

gcc x86/x86_64 ABI:ss必须等于ds/es/fs/gs吗?,gcc,x86,x86-64,abi,Gcc,X86,X86 64,Abi,似乎我听说x86和x86_64 ABI中的所有数据段都是相同的。但是ss寄存器也是?我正在编写内核,我想检测堆栈溢出。为此,要求ss段选择器不等于其他段寄存器…其ss不同于其他段寄存器,尤其是隐式不同于其他段寄存器 用过的(CS,DS)不是个好主意 大多数(几乎所有)x86 ABI都规定了平面地址模型,即在地址内 在一个进程的内存空间中,64位地址指的是相同的内存位置,无论是哪个位置 指令使用该地址访问该内存位置 这意味着RSP的内容可以移动到通用寄存器(比如R9)中,并且 通过PUSH、POP

似乎我听说x86和x86_64 ABI中的所有数据段都是相同的。但是
ss
寄存器也是?我正在编写内核,我想检测堆栈溢出。为此,要求
ss
段选择器不等于其他段寄存器…

其ss不同于其他段寄存器,尤其是隐式不同于其他段寄存器 用过的(CS,DS)不是个好主意

大多数(几乎所有)x86 ABI都规定了平面地址模型,即在地址内 在一个进程的内存空间中,64位地址指的是相同的内存位置,无论是哪个位置 指令使用该地址访问该内存位置

这意味着RSP的内容可以移动到通用寄存器(比如R9)中,并且 通过PUSH、POP(隐式使用SS)和MOV(隐式使用DS),可以使用相同的地址访问相同的内存位置

反之亦然

具有不同的段寄存器基将需要为指针类型使用更多内存(存储段和偏移量),并可能产生混叠(具有多个表示相同内存位置的不同位序列)

考虑这一点:

void foo(int *ptr) {
    *ptr = 0;
}

void bar() {
    int x;
    foo(&x);
}

int y;

void baz() {
    foo(&y);
    bar();
}
如果SS与DS不同,则为(非详尽列表)

  • 指针类型也应包含段寄存器,或

  • 编译器在获取 局部变量


这两种方法都会带来一些(时间或空间)开销。

您可能希望了解堆栈金丝雀/堆栈保护器(例如google for x86_64 stack protector)。