这是一个简单的函数
#include <stdio.h>
int foo() {
int a = 3;
int b = 4;
int c = 5;
return a * b * c;
}
int main() {
int a = foo();
}
Run Code Online (Sandbox Code Playgroud)
foo() 的程序集看起来像
foo:
push rbp
mov rbp, rsp
mov DWORD PTR [rbp-4], 3
mov DWORD PTR [rbp-8], 4
mov DWORD PTR [rbp-12], 5
mov eax, DWORD PTR [rbp-4]
imul eax, DWORD PTR [rbp-8]
imul eax, DWORD PTR [rbp-12]
pop rbp
ret
Run Code Online (Sandbox Code Playgroud)
从 中可以看出rbp - N,内部堆栈框架正在被修改。那么,为什么没有 …
我的系统:在 x86_64 上运行的 Ubuntu 22.04.3。海湾合作委员会版本 11.4.0
我读到 System V ABI 强制要求使用红色区域。来自海湾合作委员会手册:
红色区域是 x86-64 ABI 强制规定的,它是超出堆栈指针位置的 128 字节区域,不会被信号或中断处理程序修改,因此可用于临时数据而无需调整堆栈指针。该标志
-mno-red-zone禁用该红色区域。
我的问题:
如果我在 gcc 中使用该标志,红色区域是否仍然存在-mno-red-zone?
如果红色区域被“禁用”,这是否意味着我不再遵守系统 V ABI?
这会产生什么后果(不符合 System V ABI)?
我正在尝试将为 x86 架构构建的设备驱动程序交叉编译到 ARM 平台。它的编译没有任何错误,但我认为所有功能都不可用。所以我检查了 makefile 并找到了这个特定的部分。
ifeq ($(ARCH),x86_64)
EXTRA_CFLAGS += -mcmodel=kernel -mno-red-zone
Run Code Online (Sandbox Code Playgroud)
这似乎是唯一依赖于架构的部分。在google上一段时间后,我发现 -mcmodel=kernel 用于内核代码模型,而 -mno-red-zone 是为了避免在内存中使用红色区域,并且它们都适用于 x86_64。但我不清楚,将 cmodel 设置为内核会产生什么影响?
(任何对arm问题的深入了解也将不胜感激。)
以下代码
int main() {
int arr[120];
return arr[0];
}
Run Code Online (Sandbox Code Playgroud)
编译成这样:
sub rsp, 360
mov eax, DWORD PTR [rsp-480]
add rsp, 360
ret
Run Code Online (Sandbox Code Playgroud)
知道整数是 4 个字节,数组的大小为 120,数组应该占用 480 个字节,但从 ESP 中只减去了 360 个字节......这是为什么?
In the x86-64 System V ABI it is specified that the space behind the $rsp - 128 is the so-called red zone which is not touched by any signal handlers. On my machine
$ ulimit -s
8192
Run Code Online (Sandbox Code Playgroud)
I expected there is only 2 pages in the stack. So I wrote the following program to test till which size red zone can expand:
PAGE_SIZE equ 0x1000
SYS_exit equ 0x3C
section .text
global _start
_start:
lea rcx, [rsp - 0x1f * PAGE_SIZE] …Run Code Online (Sandbox Code Playgroud)