相关疑难解决方法(0)

Why does Windows64 use a different calling convention from all other OSes on x86-64?

AMD has an ABI specification that describes the calling convention to use on x86-64. All OSes follow it, except for Windows which has it's own x86-64 calling convention. Why?

Does anyone know the technical, historical, or political reasons for this difference, or is it purely a matter of NIHsyndrome?

I understand that different OSes may have different needs for higher level things, but that doesn't explain why for example the register parameter passing order on Windows is rcx - rdx …

windows x86-64 calling-convention

97
推荐指数
4
解决办法
2万
查看次数

斯坦福大学教程和GCC之间的冲突

根据这部电影(约38分钟),如果我有两个具有相同本地变量的函数,它们将使用相同的空间.所以下面的程序应该打印出来5.用gcc结果编译它-1218960859.为什么?

该程序:

#include <stdio.h>

void A()
{
    int a;
    printf("%i",a);
}

void B()
{
    int a;
    a = 5;
}

int main()
{
    B();
    A();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

根据要求,这是反汇编程序的输出:

0804840c <A>:
 804840c:   55                      push   ebp
 804840d:   89 e5                   mov    ebp,esp
 804840f:   83 ec 28                sub    esp,0x28
 8048412:   8b 45 f4                mov    eax,DWORD PTR [ebp-0xc]
 8048415:   89 44 24 04             mov    DWORD PTR [esp+0x4],eax
 8048419:   c7 04 24 e8 84 04 08    mov …
Run Code Online (Sandbox Code Playgroud)

c gcc memory-management

82
推荐指数
5
解决办法
4062
查看次数

x86-64上的红色区域究竟在哪里?

来自维基百科:

在计算中,红色区域是函数堆栈帧中超出返回地址的固定大小区域,该区域不被该函数保留.被调用函数可以使用红色区域来存储局部变量,而无需修改堆栈指针的额外开销.中断/异常/信号处理程序不会修改此内存区域.System V使用的x86-64 ABI要求一个128字节的红色区域,它直接在返回地址之后开始并包含函数的参数.OpenRISC工具链假设一个128字节的红色区域.

System V x86-64 ABI:

超出%rsp指向的位置的128字节区域被认为是保留的,不应被信号或中断处理程序修改.因此,函数可以将此区域用于函数调用不需要的临时数据.特别是,叶子函数可以将这个区域用于它们的整个堆栈帧,而不是调整序言和尾声中的堆栈指针.这个区域被称为红区.

  • 鉴于这两个引号,堆叠的返回地址上方或堆叠的返回地址下方红色区域 是?

  • 由于这个红色区域是相对的RSP,它是否向下push移动并且每个区域向上移动pop

assembly x86-64 abi calling-convention red-zone

20
推荐指数
2
解决办法
2331
查看次数

编译器使用局部变量而不调整RSP

问题编译器:了解从小程序生成的汇编代码,编译器使用两个局部变量而不调整堆栈指针.

不调整RSP以使用局部变量似乎不会中断安全,因此编译器似乎依赖于硬件在发生中断时自动切换到系统堆栈.否则,出现的第一个中断会将指令指针推入堆栈并覆盖本地变量.

该问题的代码是:

#include <stdio.h>

int main()
{
    for(int i=0;i<10;i++){
        int k=0;
    }
}
Run Code Online (Sandbox Code Playgroud)

该编译器生成的汇编代码是:

00000000004004d6 <main>:
  4004d6:       55                      push   rbp
  4004d7:       48 89 e5                mov    rbp,rsp
  4004da:       c7 45 f8 00 00 00 00    mov    DWORD PTR [rbp-0x8],0x0
  4004e1:       eb 0b                   jmp    4004ee <main+0x18>
  4004e3:       c7 45 fc 00 00 00 00    mov    DWORD PTR [rbp-0x4],0x0
  4004ea:       83 45 f8 01             add    DWORD PTR [rbp-0x8],0x1
  4004ee:       83 7d f8 09             cmp    DWORD PTR …
Run Code Online (Sandbox Code Playgroud)

c linux x86 assembly x86-64

9
推荐指数
1
解决办法
330
查看次数

发生中断时x86架构会发生什么?

我正在研究x86和实时系统,我有一个问题,那就是:

x86遵循哪些步骤来处理任何中断?

assembly interrupt x86-16

7
推荐指数
2
解决办法
2137
查看次数

当我们有一个红区时,为什么我们需要堆栈分配?

我有以下疑惑:

正如我们所知,System V x86-64 ABI为我们提供了堆栈帧中固定大小的区域(128字节),即所谓的redzone.因此,结果我们不需要使用,例如,sub rsp, 12.只是做mov [rsp-12], X,这就是全部.

但我无法理解这一点.为什么这有关系?sub rsp, 12没有redzone 是否有必要?毕竟,堆栈大小在开始时是有限的,为什么sub rsp, 12重要?我知道这使得我们可以跟随堆栈的顶部但是让我们忽略它.

我知道一些指令使用了什么rsp价值(比如ret)但在那一刻并不关心它.

问题的症结在于:我们没有红区,我们已经完成了:

function:
    mov [rsp-16], rcx
    mov [rsp-32], rcx
    mov [rsp-128], rcx
    mov [rsp-1024], rcx
    ret
Run Code Online (Sandbox Code Playgroud)

它有区别吗?

function:
    sub rsp, 1024
    mov [rsp-16], rcx
    mov [rsp-32], rcx
    mov [rsp-128], rcx
    mov [rsp-1024], rcx
    add rsp, 1024
    ret
Run Code Online (Sandbox Code Playgroud)

x86 assembly x86-64 abi red-zone

6
推荐指数
1
解决办法
1073
查看次数

为什么在这个函数序言中没有"sub rsp"指令,为什么函数参数存储在负rbp偏移量?

这就是我通过阅读一些内存分段文档所理解的:当调用一个函数时,有一些指令(称为函数序言)将帧指针保存在堆栈上,将堆栈指针的值复制到基本指针中并保存一些局部变量的内存.

这是我尝试使用GDB调试的一个简单代码:

void test_function(int a, int b, int c, int d) {
    int flag;
    char buffer[10];

    flag = 31337;
    buffer[0] = 'A';
}

int main() {
    test_function(1, 2, 3, 4);
}
Run Code Online (Sandbox Code Playgroud)

调试此代码的目的是了解调用函数时堆栈中发生的情况:因此我必须在执行程序的各个步骤(在调用函数之前和执行期间)检查内存.虽然我设法通过检查基指针来查看返回地址和保存的帧指针之类的东西,但我真的无法理解在反汇编代码之后我要写的内容.

拆解:

(gdb) disassemble main
Dump of assembler code for function main:
   0x0000000000400509 <+0>: push   rbp
   0x000000000040050a <+1>: mov    rbp,rsp
   0x000000000040050d <+4>: mov    ecx,0x4
   0x0000000000400512 <+9>: mov    edx,0x3
   0x0000000000400517 <+14>:    mov    esi,0x2
   0x000000000040051c <+19>:    mov    edi,0x1
   0x0000000000400521 <+24>:    call   0x4004ec <test_function>
   0x0000000000400526 <+29>:    pop    rbp
   0x0000000000400527 <+30>:    ret    
End …
Run Code Online (Sandbox Code Playgroud)

c assembly stack x86-64 red-zone

5
推荐指数
1
解决办法
1311
查看次数

GCC访问堆栈顶部的内存

我有C函数做一些SSE计算.当我用GCC编译它时,我得到下一个代码

/* Start of function */
mov    (%rdi),%rax
movslq %ecx,%rcx
...
mov    0x8(%rdi),%rax
pxor   %xmm12,%xmm3
movaps %xmm0,-0x28(%rsp)
movaps %xmm6,%xmm1
...
movaps 0x50(%rax,%rcx,1),%xmm2
movaps 0x60(%rax,%rcx,1),%xmm15
pxor   %xmm2,%xmm0
pxor   %xmm2,%xmm6
movaps -0x28(%rsp),%xmm2
pxor   %xmm15,%xmm5
pxor   %xmm15,%xmm2
movaps 0x70(%rax,%rcx,1),%xmm15
movaps (%rax,%rcx,1),%xmm11
mov    0x10(%rdi),%rax
movaps %xmm15,-0x18(%rsp)
pxor   %xmm11,%xmm4
pxor   %xmm12,%xmm11
pxor   %xmm15,%xmm12
Run Code Online (Sandbox Code Playgroud)

查看movaps说明 - 它是堆栈顶部的访问内存:

movaps %xmm15,-0x18(%rsp)
Run Code Online (Sandbox Code Playgroud)

它不是访问未定义的内存吗?为什么GCC生成了这样不正确的代码?

assembly gcc sse x86-64 sse2

4
推荐指数
1
解决办法
436
查看次数

即使我们在 gcc 中使用 -mno-red-zone 标志,红色区域仍然存在吗?

我的系统:在 x86_64 上运行的 Ubuntu 22.04.3。海湾合作委员会版本 11.4.0

我读到 System V ABI 强制要求使用红色区域。来自海湾合作委员会手册

红色区域是 x86-64 ABI 强制规定的,它是超出堆栈指针位置的 128 字节区域,不会被信号或中断处理程序修改,因此可用于临时数据而无需调整堆栈指针。该标志-mno-red-zone禁用该红色区域。

我的问题:

  1. 如果我在 gcc 中使用该标志,红色区域是否仍然存在-mno-red-zone

  2. 如果红色区域被“禁用”,这是否意味着我不再遵守系统 V ABI?

  3. 这会产生什么后果(不符合 System V ABI)?

c x86-64 abi stack-memory red-zone

3
推荐指数
1
解决办法
188
查看次数

代码如何在同步的单核CPU上异步?

单处理器 (UP) 系统中中,只有一个 CPU 核心,因此一次只能执行一个线程。该执行线程是同步的(它获取队列中的指令列表并逐条运行它们)。当我们编写代码时,它会编译为 CPU 指令集。

我们怎样才能在 UP 机器上的软件中实现异步行为? 难道一切不是都按照操作系统选择的固定顺序运行吗?

即使是乱序执行的CPU 也会给人一种按程序顺序运行指令的错觉。(这与系统中其他内核或设备观察到的内存重新排序是分开的。在 UP 系统中,运行时内存重新排序仅与设备驱动程序相关。)

asynchronous cpu-architecture

2
推荐指数
1
解决办法
1295
查看次数

EFLAGS 状态

在过去的几天里,我一直在为一种试图获得 EFLAGS 状态的奇怪行为而苦苦挣扎。为此,我编写了以下代码:

#include <stdio.h>

int flags_state()
{

  int flags = 0;

  __asm__ __volatile__("pushfq");
  __asm__ __volatile__("pop %%rax": "=a"(flags));

  return flags;
}

int main()
{

  printf("Returning EFLAGS state: 0x%x\n", flags_state());
  return 0;

}
Run Code Online (Sandbox Code Playgroud)

当它运行时,我得到:

./flags
Returning EFLAGS state: 0x246
Run Code Online (Sandbox Code Playgroud)

当我打印两次标志时,它变得更奇怪了

Returning EFLAGS state: 0x246
Returning EFLAGS state: 0x206
Run Code Online (Sandbox Code Playgroud)

当我尝试打印 6 次时它发生了变化

Returning EFLAGS state: 0x246
Returning EFLAGS state: 0x202
Returning EFLAGS state: 0x202
Returning EFLAGS state: 0x202
Returning EFLAGS state: 0x202
Returning EFLAGS state: 0x202
Run Code Online (Sandbox Code Playgroud)

最后是最奇怪的(至少对我来说),当我打印 8 次时

Returning EFLAGS state: …
Run Code Online (Sandbox Code Playgroud)

assembly x86-64 inline-assembly eflags

0
推荐指数
1
解决办法
74
查看次数