스택 할당, 패딩 및 정렬
컴파일러가 머신 코드를 생성하는 방법, 특히 GCC가 스택을 처리하는 방법에 대해 더 깊이 이해하려고 노력했습니다.그렇게 함으로써 저는 간단한 C 프로그램을 작성하고, 그것들을 조립하여 결과를 이해하려고 노력하고 있습니다.다음은 간단한 프로그램과 이 프로그램이 생성하는 출력입니다.
asmtest.c
:
void main() {
char buffer[5];
}
asmtest.s
:
pushl %ebp
movl %esp, %ebp
subl $24, %esp
leave
ret
왜 24바이트가 스택에 할당되어 있는지 의문입니다.프로세서의 메모리 주소 지정 방법 때문에 스택을 4씩 할당해야 한다는 것은 알고 있습니다만, 이 경우 스택 포인터를 24바이트가 아닌 8바이트만 이동해야 합니다.예를 들어 버퍼가 17바이트일 경우 스택포인터가 40바이트 이동되고 버퍼는 전혀 이동하지 않습니다.1 ~ 16바이트의 버퍼는 이동됩니다.ESP
24 바이트
8바이트가 필요한 상수라고 가정하면(필요한 것은 무엇입니까?), 16바이트의 청크로 할당됩니다.컴파일러가 왜 이런 식으로 정렬되는 거죠?x86_64 프로세서를 사용하고 있지만 64비트 워드라도 8바이트 정렬만 필요합니다.왜 차이가 나는 거죠?
참고로 10.5를 실행하고 있고 최적화가 활성화되지 않은 Mac에서 컴파일합니다.
이 기능은 GCC에 의해 제어됩니다.-mpreferred-stack-boundary=n
여기서 컴파일러는 스택 상의 아이템을 정렬 상태로 유지하려고 합니다.2^n
만약 당신이 변했다면n
로.2
스택에 할당되는 바이트는 8바이트뿐입니다.디폴트값n
이4
즉, 16바이트 경계에 맞추려고 합니다.
"기본값"이 8바이트이고 다음으로 24=8+16바이트인 이유는 스택에 이미 다음 시간 동안 8바이트가 포함되어 있기 때문입니다.leave
그리고.ret
따라서 컴파일된 코드가 스택을 2^4=16으로 정렬하려면 먼저 스택을 8바이트만큼 조정해야 합니다.
LWN에는 메모리 정렬에 대한 기사가 있어 흥미로울 수 있습니다.
이 사이트를 찾았습니다.페이지 하단에 스택이 더 큰 이유에 대한 설명이 있습니다.개념을 64비트 시스템으로 확장하면 표시되는 내용을 설명할 수 있습니다.
SSEx 명령 패밀리를 사용하려면 패킹된 128비트 벡터를 16바이트로 정렬해야 합니다. 그렇지 않으면 벡터를 로드/저장하려고 하는 세그먼트 오류가 발생합니다.즉, 스택에서 SSE와 함께 사용하기 위해 16바이트 벡터를 안전하게 전달하려면 스택을 16으로 일관되게 정렬해야 합니다. 기본적으로는 GCC가 이를 고려합니다.
Mac OS X/Darwin x86 ABI에서는 16바이트의 스택 정렬이 필요합니다.Linux, Win32, FreeBSD 등 다른 x86 플랫폼에서는 그렇지 않습니다.
첫 번째 명령이 스택의 %ebp 시작 값(64비트를 전제로 함)을 푸시하기 때문에 8바이트가 존재합니다.
언급URL : https://stackoverflow.com/questions/1061818/stack-allocation-padding-and-alignment
'programing' 카테고리의 다른 글
메서드에서 메서드를 하나만 호출합니다. (0) | 2022.07.30 |
---|---|
파일 내용을 C 문자열로 읽는 방법은 무엇입니까? (0) | 2022.07.30 |
불투명 데이터 유형의 정적 할당 (0) | 2022.07.30 |
Vuejs - 템플릿의 헤더 섹션을 부모로 이동 (0) | 2022.07.30 |
스트링 리터럴에 헥스 이스케이프를 적절히 추가하는 방법은? (0) | 2022.07.30 |