지난 글에서는 다차원 배열에 대한 내용을 정리하였다. row-major, column-major 에 따라 주소값을 구하는 방식이 달라지는 것에 유의하여야 함을 기억하자. 또, 배열 원소 하나의 사이즈에 따라 주소값 계산식에 W 를 다르게 넣어야 함도 유의하여야 했다. 이번 글에서는 스택 메모리 공간에 구조체를 저장할 때 어떻게 저장되는지 정리하고자 한다. 구조체가 메모리에 들어갈 때 다음과 같은 구조체가 있다고 해보자. struct s { int a, b; char c; short d, e; int f, g; } 이때 이 구조체 변수 하나를 스택에 선언하면, 실제 메모리에는 어떻게 저장될까? 구조체도 배열과 마찬가지로 선언된 순서대로 점점 주소가 높아진다. (즉, 마지막에 선언된 변수가 %fp에 가깝다)..
지난 글에서는 일차원 배열에 대한 내용을 정리하였다. 일차원배열을 스택에 선언하는 경우, 배열의 주소는 낮은곳부터 높은 곳순으로 증가하지만, 배열 공간이 선언되는 위치는 지역변수가 선언되는 것과 마찬가지로 높은 주소부터 쌓이는 식으로 선언되었다. 이번 글에서는 다차원 배열에 대해 정리하고자 한다. 다차원 배열의 표현 다차원배열은 결국 선형구조인 메모리에 저장되어야 한다. 이때 선형 구조인 메모리에 어떻게 저장하느냐에 따라 크게 2가지로 나눌 수 있다. 1. row major 2. column major row major 는 우리가 흔히 사용하는 방식으로, 먼저 row 를 기준으로 구역을 나눈 뒤, column 인덱스가 증가할 때 메모리 주소가 순차적으로 증가하고, 모든 column이 다 차면 그때 row..
어셈블리 과제 + 정리하다가 만난 오류이다. 처음 만났을 때는 구글링 실력이 모자라서 그런가, 아무리 검색해도 해결방법이 나오지 않았다. 그러다가 오늘 코드를 한줄 한줄 주석했다가 풀어보면서 이 오류를 발생시키는 코드를 찾았고, 이 오류가 발생하는 원인을 발견했다. data 섹션에 데이터를 선언하고, 이렇게 라벨링을 하였을 때 이렇게 라벨링 된 값을 그대로 가져다가 사용하면 위 에러가 발생한다. 이렇게 반드시 set 명령어를 사용해서 레지스터에 주소값을 옮겨준 후, 연산을 해야 한다.
지난 글에서는 스택 프레임의 개념에 대해 정리하였다. 스택프레임은 스택이라는 메모리 공간을 차지하는 기본 단위이다. 서브루틴을 호출할 때마다 레지스터와 스택프레임이 할당된다. 이때 할당되는 스택프레임의 크기는 save 명령어를 통해 지정할 수 있는데, 최소 사이즈는 64바이트였다. (l-register, i-register 저장 용도) 만약 스택 프레임 내에서 또다른 함수를 호출한다면, 구조체 반환 포인터 크기 4byte와, 매개변수 전달 용도의 24byte 사이즈 공간이 추가로 더 필요해 최소 92byte 사이즈가 필요했다. 여기에 만약 지역변수를 추가로 사용한다면 사용할 지역변수의 총 사이즈만큼 추가로 할당이 필요했다. 마지막으로 총 사용하는 사이즈 크기를 8의 배수로 맞춰 생성해야 한다. 스택 프레..
지난 글에서는 SPARC의 (근데 찾아보니 아마도 기본적인 컴퓨터 공통의) 메모리 맵을 정리하면서 BSS 섹션의 내용을 추가로 정리하였다. bss 섹션은 정적 메모리 영역 중 하나로, 이곳에 할당한 변수는 모두 0으로 초기화되는 특징이 있었다. 이번 글에서는 다시 '스택' 영역으로 돌아와서, 새로운 스택 영역의 메모리를 할당하는 단위인, '스택 프레임' 에 대해 정리하고자 한다. Stack Frame (스택 프레임) 스택 프레임은 나중에 정리할 '서브루틴' 과 관련되어 있다. 서브루틴(함수)는 호출될 때마다, 레지스터 공간과 함께 스택 공간을 새로 할당한다. 이때 각 함수마다 할당하는 스택 공간의 크기를 임의로 지정할 수 있는데, 이 스택 공간을 '스택 프레임' 이라고 한다. 즉, 스택 프레임은 서브루틴..
메모리 개요 메모리는 프로그램의 명령어와, 그 명령어가 사용할 데이터가 들어있는 공간이다. (폰 노이만 구조에서는 프로그램의 명령어도 데이터이다.) 저장 단위는 byte 단위이며, 레지스터와 달리 4byte로 고정되지 않고 1, 2, 4, 8 byte 등으로 유동적인 사이즈로 저장할 수 있다. 하지만 레지스터가 한번에 4byte 씩 파악하기 때문에, 명령어의 사이즈는 4byte 로 고정되어있다. 메모리 접근 메모리에 접근하여 데이터를 읽고 쓰는 명령어는 기본적으로 아래와 같은 형태를 띈다. Load, 메모리의 데이터를 불러와(loading) 레지스터에서 읽는 것 ld [메모리주소], 레지스터주소 메모리 -> 레지스터 순서로 읽으면 되니 이해가 간단하다. 메모리주소는 R + A 형태로 표현되고, [ ] 는..
지난 글에서는 분기 최적화에 대해 정리하였다. 분기 최적화를 하는 방법에는 from before, from after, annulled branch 3가지가 있었다. from before 은 분기 명령어 이전에 실행되는 명령어를 가져오는 것으로, 보통 mov 명령어를 이용한 레지스터 값 세팅을 가져올 수 있다. from after 은 분기 명령어 이후에 실행되는 명령어를 가져오는 것으로, 보통 분기 이후 실행되는 명령어 중, 분기 여부에 상관없이 반드시 실행되는 명령어를 당겨올 수 있었다. annulled branch 는 분기를 할 때는 delay slot 명령어를 실행하고, 분기를 하지 않을 때는 delay slot 명령어를 실행하지 않는 분기 명령어로서, 반드시 분기 후 첫 명령어를 delay slo..
지난 포스팅에서는 SPARC 에서 사용하는 레지스터의 종류 4가지와, 레지스터 윈도우에 대하여 정리하였다. 이번에는 어셈블리 언어 프로그래밍의 기본 문법과 어셈블리 언어 명령어의 분류를 정리한다. 어셈블리 언어 기본 문법 - 각 줄의 코드는 명령어 또는 데이터 정의이다. - 매 줄 끝마다 세미콜론은 사용하지 않는다. - 콜론(:) 으로 끝나는 문자열을 '레이블' 이라고 한다. 이는 프로그램의 지표가 된다. - /* */ 를 를 이용해 다중 라인 주석을 적거나 ! 을 이용해 한 줄 주석을 적을 수 있다. - 어셈블리 언어의 명령어는 크게 3가지로 나뉜다. 1. Pseudo-operation (의사 명령어) 2. Synthetic instruction (합성 명령어) 3. Machine instruction..
지난 포스팅에서는 프로세서가 각 명령어들을 빠르게 처리하기 위해 파이프라이닝을 사용할 경우 발생할 수 있는 해저드의 종류와 해결 방법을 정리하였다. 이번 포스팅에서는 SPARC 라는 ISA 의 아키텍처와 레지스터 종류에 대해 정리하여 본다. 우리 학교는 어셈블리 실습으로 SPARC를 사용한다. 이 SPARC 라는 ISA의 주요 특징은 다음과 같다. 1. RISC 타입이다. 2. 명령어와 데이터의 크기가 모두 32bits 이다. 따라서 레지스터 하나의 사이즈도 32bit 이다. .3. 한번에 사용 가능한 레지스터의 개수가 32개이다. 하드웨어적으로는 더 많은 레지스터가 있지만, 한번에 32개씩만 쓸 수 있다. (Register Window System) SPARC 의 레지스터는 4가지 타입이 있다. 그리고..