Notice
Recent Posts
Recent Comments
«   2025/02   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28
Tags
more
Archives
Today
Total
관리 메뉴

seven05

[CSAPP] 3.7~3.9,11 어셈블리어가 함수와 배열을 표현하는 방법 본문

SW JUNGLE 9기/CSAPP

[CSAPP] 3.7~3.9,11 어셈블리어가 함수와 배열을 표현하는 방법

박상비누 2024. 9. 4. 20:56

프로시저: 함수를 어셈블리어에서 나타내는 말로 이해했다.

스택은 단지 메모리의 한 부분일 뿐이지만 이 부분을 스택 자료구조처럼 다뤄서 스택이라고 부른다.

 

스택은 프로시저와 관련된 상태를 나타내기 위해 쓰이는데 왜그럴까? 생각해보면 함수가 호출되는 과정은 한국어로는 후입선출 영어로는 LIFO(Last-In-First-Out) 이기때문에 스택의 형태가 함수호출에 적합하다.

왼쪽 그림에 보이는것처럼 스택은 높은 메모리 주소부터 아래로 증가한다. %rsp 레지스터는 스택의 가장 낮은 주소를 항상 저장하고있으며 스택에 원소가 추가될수로 %rsp가 감소한다.

 근데 이부분에서 궁금한것이 생겼다. 무슨 궁금증이냐면 스택이 왜 높은 주소부터 할당될까? 였다. 그래서 찾아보았더니 프로세스 주소공간에서 동적으로 할당되는 힙과 스택을 교차시켜 사용해야 중복을 방지하는데 스택을 반대로 할당함으로써 이를 만족하도록 하는것으로 보였다.(정확하지는 않지만 일단은 이정도로 이해하고 넘어가기로했다.)

 

 

프로시저는 호출이 일어날때마다 인자와 지역변수등의 정보를 스택의 저장한다.이를 스택 프레임이라고한다.

즉 함수 호출은 메모리를 사용한다. 알고리즘 문제를 풀때 recursion error를 겪는 이유가 재귀함수호출로 메모리를 초과했기때문이다.

 

 

 

 

호출을 한 함수의 프레임은 회색이고 새로 호출된 함수의 프레임은 보라색이다. 회색 구간에 함수 인자와 리턴할 주소, 보라색 구간에 레지스터와 지역 변수가 들어가 있는걸 볼 수 있다.

yoo는 %rdx에 15213이란 값을 저장하고, who 호출이 끝나고 %rdx에 담겨있는 값을 다시 사용한다.
이때 문제가 생긴다 who에서 %rdx를 수정했을 수 있기 때문에 yoo에서 값이 유지될지 확신할수없다.
yoo는 호출자, who는 피호출자 라고 하며, 레지스터를 두가지로 분류한다.
호출자 저장 레지스터(caller saved)는 호출자는 호출을 하기 전에 레지스터의 값을 다른 곳에 저장해놓는다. 
피호출자 저장 레지스터(callee saved)는 피호출자가 레지스터의 원래 값을 다른곳에 저장해두고 프로시저가 끝나기 전에 레지스터의 원래 값을 복원한다.
피호출자 저장 레지스터는 %rbx, %r12, %r13, %r14, %rbp, %rsp가 해당하고 나머지는 전부 호출자 저장 레지스터이다.

주어진 long에 1이 몇개 있는지 세는 함수

재귀함수가 어셈블리어로 어떻게 동작되는지 보자. testq %rdi %rdi 로 rdi가 0인지 확인후 맞다면 L6으로 점프한다.

rep; ret는 그냥 ret이다. rep는 바이트수를 맞추기위한 버퍼이다.

%rdx를 스택에 push해서 저장하고 %rdi로 덮어씌운다. long이기때문에 %ebx(%rbx의 하위 32비트)에 &연산을 하고 인자가 될 %rdi에 >> 1을 한다. 그 이후에는 재귀호출한 값을 더한다.이때 %rbx를 그냥 더할 수 있는건 피호출자가 알아서 %rbx의 원래 값을 복원한다. (pop %rbx가 하는일이다.)

 

데이터: 메모리에 배열과 구조체가 어떻게 저장되는가?

data type에 따른 배열 저장
2차원 배열이 저장되는 방법

2차원 배열이더라도 저장자체는 1차원 배열처럼 이루어진다. 이러한 특성때문에 속도차이가 발생하는경우가있다.

같은 기능이지만 저장 방식의 차이로 인해 속도차이가 나는 경우
struct가 저장되는 방식

 

주소가 4의 배수나 8의 배수를 만족하게끔 패딩비트를 추가해서 저장한다. 1바이트짜리 변수를 넣는다 하더라도 4의 배수로 주소가 이동하기때문에 공간이 낭비된다. (RB트리에서 color 변수가 이런 경우인데 실제로 linux RB tree의 경우 부모 주소를 저장하는 변수에 1의 자리 비트가 사용되지않는 것을 이용해서 변수 선언을 하나 아낀다. 참고: Red-Black Tree in Linux Kernel - Part 2 (soopsaram.com))

 

실습 attack lab

 

참고:CSAPP , 컴퓨터시스템 3강 : 어셈블리어 - 프로시저와 데이터 - 코딩 채널 (arca.live)