ARM: 링크 레지스터 및 프레임 포인터
ARM에서 링크 레지스터와 프레임 포인터가 어떻게 작동하는지 이해하려고 합니다.몇 군데 다녀왔는데 이해를 확인하고 싶었습니다.
다음 코드가 있다고 가정해 보겠습니다.
int foo(void)
{
// ..
bar();
// (A)
// ..
}
int bar(void)
{
// (B)
int b1;
// ..
// (C)
baz();
// (D)
}
int baz(void)
{
// (E)
int a;
int b;
// (F)
}
그리고 foo()라고 부릅니다.링크 레지스터에 (A) 지점의 코드 주소가 포함되고 프레임 포인터에 (B) 지점의 코드 주소가 포함됩니까?그리고 스택 포인터는 모든 로컬이 선언된 후에 bar() 내부의 아무 곳에나 있을 수 있습니다.
일부 레지스터 호출 규약은 ABI(Application Binary Interface)에 의존합니다.FP
APCS 표준에는 필요하며, 최신 AAPCS(2003)에는 필요하지 않습니다.AAPCS(GCC 5.0+)의 경우FP
사용할 필요는 없지만 당연히 그럴 수 있습니다. 디버그 정보에는 AAPCS를 사용한 스택 추적 및 코드 풀기를 위한 스택 및 프레임 포인터 사용이 주석으로 되어 있습니다.만약 함수가static
, 컴파일러는 정말로 어떤 규약도 지킬 필요가 없습니다.
일반적으로 모든 ARM 레지스터는 범용입니다.lr
및 터,한 R14)dpc
(프로그램 카운터 역시 R15)는 특별하며 명령어 세트에 담겨 있습니다.당신 말이 맞습니다.lr
A를 가리킬 겁니다pc
그리고.lr
관련이 있습니다.하나는 "당신이 있는 곳"이고 다른 하나는 "당신이 있었던 곳"입니다.이들은 함수의 코드 측면입니다.
일반적으로 저희는.sp
및 , R13)fp
(프레임 포인터, R11).이 두 가지도 연관이 있습니다.이 마이크로소프트 레이아웃은 사물을 잘 설명해 줍니다.스택은 임시 데이터 또는 로컬을 함수에 저장하는 데 사용됩니다.에 있는 변수foo()
그리고.bar()
, 여기, 스택 또는 사용 가능한 레지스터에 저장됩니다.fp
는 기능에서 기능으로 변수를 추적합니다.해당 기능을 위한 스택의 프레임 또는 그림 창입니다.ABI는 이 프레임의 레이아웃을 정의합니다.일반적으로lr
그리고 다른 레지스터들은 컴파일러에 의해 뒤에 저장될 뿐만 아니라 이전의 값에 의해 여기에 저장됩니다.fp
. 이렇게 하면 스택 프레임의 연결된 목록이 생성되며, 필요한 경우 다음 위치까지 추적할 수 있습니다.main()
. 뿌리가.fp
, 하나의 스택 프레임을 가리키는 것(예를 들어 a.struct
)에 변수가 하나 있는 경우struct
이전의 것으로서fp
. 당신은 결승전까지 목록을 따라가면 됩니다.fp
보통은NULL
.
.sp
는 스택이 있는 곳이고fp
스택이 있던 곳입니다. 마치 그와 같은.pc
그리고.lr
. 각각의 오래된lr
(link register)는 이전 버전에 저장됩니다.fp
(프레임 포인터). 그.sp
그리고.fp
는 함수의 데이터 측면입니다.
당신의 포인트 B는 활성입니다.pc
그리고.sp
. 포인트 A는 사실은.fp
그리고.lr
; 당신이 아직 다른 함수를 호출하고 컴파일러가 설정할 준비를 하지 않는 한.fp
B의 데이터를 가리킵니다.
다음은 이 모든 것이 어떻게 작동하는지 보여줄 수 있는 ARM 어셈블리입니다.이것은 컴파일러가 최적화하는 방법에 따라 다르겠지만 아이디어를 제공해야 합니다.
; Prologue - setup
mov ip, sp ; get a copy of sp.
stmdb sp!, {fp, ip, lr, pc} ; Save the frame on the stack. See Addendum
sub fp, ip, #4 ; Set the new frame pointer.
...
; Maybe other functions called here.
; Older caller return lr
stored in stack frame.
bl baz
...
; Epilogue - return
ldm sp, {fp, sp, lr} ; restore stack, frame pointer and old link.
... ; maybe more stuff here.
bx lr ; return.
This is what
foo()
would look like. If you don't call
bar()
, then the compiler does a
잎 최적화 and doesn't need to save the
틀; only the
bx lr
is needed. Most likely this maybe why you are confused by web examples. It is not always the same.
테이크아웃은 다음과 같습니다.
pc
그리고.lr
관련 코드 레지스터입니다.하나는 "Where you are"이고, 다른 하나는 "Where you were"입니다.sp
그리고.fp
관련 로컬 데이터 레지스터입니다.
하나는 "로컬 데이터가 있는 곳"이고, 다른 하나는 "로컬 데이터가 있는 곳"입니다.- 기능 기계를 만들기 위해 매개 변수 전달과 함께 작업합니다.
- 일반적인 경우를 설명하는 것은 어렵습니다. 왜냐하면 컴파일러들이 가능한 한 빨리 처리하기를 원하기 때문입니다. 그래서 그들은 가능한 모든 속임수를 사용하기 때문입니다.
이러한 개념은 모든 CPU와 컴파일된 언어에 일반적인 개념이지만 세부 사항은 다를 수 있습니다.링크 레지스터, 프레임 포인터의 사용은 함수 프롤로그 및 에필로그의 일부이며, 모든 것을 이해했다면 ARM에서 스택 오버플로가 어떻게 작동하는지 알 수 있습니다.
참고 항목: ARM 호출 규약.
MSDN ARM
개요 APCS
ARM 스택 추적 블로그
링크Apple ABI
기본적인 프레임 배치는,
- 된 fp[-0]
pc
, 우리가 이 액자를 보관했던 곳입니다. - 된 fp[-1]
lr
, 이 함수의 반환 주소입니다. - fp[-2]
sp
, 이 함수가 스택을 먹기 전에. - fp[-3]
fp
, 맨 끝에 쌓아 올린 골조 - 많은 선택 레지스터들...
ABI는 다른 값을 사용할 수도 있지만, 위의 내용은 대부분의 설정에서 일반적으로 사용됩니다.위의 인덱스는 모든 ARM 레지스터가 32비트이므로 32비트 값에 대한 것입니다.바이트 중심인 경우 4를 곱합니다.프레임도 최소 4바이트로 정렬됩니다.
부록:이것은 어셈블러의 오류가 아닙니다. 정상입니다.ARM 생성 프롤로그 질문에 설명이 있습니다.
면책 사항:이 말이 대충 맞는 것 같으니 필요에 따라 수정해 주시기 바랍니다.
이 Q&A의 다른 부분에 나와 있듯이, 컴파일러가 프레임 포인터를 사용하는 ABI(코드 생성)를 생성할 필요가 없을 수도 있습니다.콜 스택의 프레임은 종종 쓸모없는 정보를 저장해야 합니다.
컴파일러 옵션이 '프레임 없음'(의사 옵션 플래그)을 호출하는 경우 컴파일러는 호출 스택 데이터를 더 작게 유지하는 더 작은 코드를 생성할 수 있습니다.호출 함수는 스택에 필요한 호출 정보만 저장하도록 컴파일되고 호출 함수는 스택에서 필요한 호출 정보만 팝하도록 컴파일됩니다.
실행 시간과 스택 공간을 절약할 수 있지만 호출 코드의 역추적을 매우 어렵게 만듭니다. (저는 시도를 포기했습니다.)
스택에 있는 호출 정보의 크기와 모양에 대한 정보는 컴파일러만 알 수 있으며 컴파일 시간이 지나면 해당 정보가 버려집니다.
언급URL : https://stackoverflow.com/questions/15752188/arm-link-register-and-frame-pointer
'programing' 카테고리의 다른 글
자바스크립트 iframe 내용만 출력 (0) | 2023.10.26 |
---|---|
SQL 보기에 기본 키 추가 (0) | 2023.10.21 |
Angular.js 매개 변수를 사용하여 리소스를 삭제 (0) | 2023.10.21 |
mysql 셸 내의 테이블 줄 없이 쿼리 결과 표시(비표 출력) (0) | 2023.10.21 |
함수에서 비동기 대기를 사용하여 비동기 함수에서 값을 반환하는 방법은 무엇입니까? (0) | 2023.10.21 |