용어 Memory : stores a programs instructions and data size of an instrcution : 4 byte size of data : Byte(1 byte), Half word(2 byte), Word(4 byte), Double (8 byte) => memory read/write size Register : memory place in a processor (CPU), store intermediate results during calculation, or values often used size of register : 4 byte Text Section : save the program instructions, save read-only data (glo..
지난 글에서는 단점일도 FPU 명령어 사용 예제를 살펴보았다. 이번 글에서는 배정밀도 FPU 명령어 사용 예제를 살펴보고자 한다. Double-Precision Floating Point Computation 배정밀도 연산자는 기존 연산자 끝에 s 대신 d 가 붙는 것만 다르다. faddd fsubd fmuld fsmuld (single * single = double, 피연산자는 single 이다.) fdivd fsqrtd double 연산자의 피연산자 레지스터는 반드시 짝수번째 레지스터가 들어가야 한다. %fi 와 %f(i+1) 의 2개 레지스터로 하나의 소수를 표현하기 때문이다. 연산 결과도 double 로 나오므로 짝수번째 레지스터를 사용한다. 데이터 형변환 명령어도 종류가 늘어났다. fitod ..
지난 글까지 실수에서의 산술연산 방법과 FPU의 개념 및 FPU에서 사용 가능한 연산들에 대해 정리하였다. 이번 글에서는 정리한 명령어를 직접 사용해보면서 명령어에 익숙해져보려고 한다. 단정밀도 예제 1 다음 코드를 어셈블리로 컴파일해보자. void main() { static float a = 1.5, b=10.5, c=0.0, d=3.5; if (c == d) c = a+b; else c = a-b; } 간단히 float 형 (단정밀도) 정적 변수 4개를 선언해 값을 할당하고, 비교해서 연산 결과 값을 저장하는 코드이다. 먼저 static 정적 공간에 데이터를 생성해야 하므로, ".data" 섹션을 사용하면 된다. .data 섹션에 단정밀도 공간을 할당하는 방법은 아래와 같이 하면 된다. 선언하는 사..
지난 글에서는 Floating Point 의 개념과 10진 소수를 이진 소수로 상호 변환하는 과정을 정리하였다. 이번 글에서는 Floating Point 간 사칙 연산을 정리하고자 한다. SPARC는 FPU 라고 하는 실수 계산용 arithmetic units (산술 연산 유닛) 이 존재하여, 덧셈/뺄셈/곱셈/나눗셈 기능을 지원한다. 그래서 정수와는 다르게, 곱셈과 나눗셈을 '명령어' 수준으로도 지원한다. 먼저 FPU를 살펴보기 전에, 실수의 산술 연산 과정을 정리해보자. 실수 덧뺄셈 실수의 덧뺄셈은 아래 과정으로 진행된다. 1. significand를 맞춘다. 2. significand 끼리 더해준다. 3. 결과를 Normalize 한다. 4. 기존 자릿수에 맞게 유효숫자를 맞춘 뒤, 필요하다면 다시 ..
10진수 소수 2진수 소수 상호 변환 이번 글에서부터는 컴퓨터가 '실수'를 어떻게 표현하는지 정리하고자 한다. 이진수를 다루는 컴퓨터가 실수를 어떻게 표현하는지를 알기 위해 먼저 10진수의 소수가 어떤 식으로 표현되고 있는지를 생각해보자. 10.155 라는 소수는 1 x 10^1 0 x 10^0 1 x 10^-1 5 x 10^-2 5 x 10^-3 이렇게 표현된다는 건 자연스럽게 알고 있다. 이는 이진수에서도 마찬가지로 작용한다. 10.111 이라는 이진수 소수는 1 x 2^1 0 x 2^0 1 x 2^-1 1 x 2^-2 1 x 2^-3 이렇게 표현된다. 그리고 이 값을 10진수로 잘 계산해주면 우리가 사용하는 10진수 소수값이 나온다. 그리고 이 과정을 통해 자연스럽게 2진수를 10진수로 변환하는 방..
이번에는 지금까지 정리한 내용에 더불어 C 라이브러리를 활용하여 버블소트를 SPARC로 구현할 것이다. C 코드 #include #incdlue #incdlue struct sort_info { unsigned int num_items; unsigned int max_value; }; unsigned int askNumber(char* message) { unsigned int val; register int result; do { printf("%s", message); result = scanf("%u", &val); } while (result != 1); return val; } struct sort_info askInfo() { struct sort_info si; si.num_items = a..
지난 글에서는 서브루틴에서 구조체를 다루는 방법을 정리하였다. %sp+64 위치에 구조체 시작 주소를 넘겨서 직접 해당 구조체를 다루는 것이 포인트였다. 서브루틴 내에서는 %fp+64로 접근하는 것이 차이점이었다. 이번 글에서는 리프 서브루틴에 대해 정리하고자 한다. Leaf Subroutine 트리에서 자식 노드가 없는, 즉, degree = 0 인 노드를 leaf 노드라고 한다. 함수의 call graph 를 그렸을 때, leaf 노드에 해당하는 함수는 가장 마지막에 호출되어 더 이상 함수를 추가로 호출하지 않는 함수를 의미한다. 리프노드는 그냥 평범한 서브루틴과 비슷하게 구현하면 된다. 그런데 만약 리프노드에서 수행하는 작업이 너무 간단해서 새 스택 프레임을 할당할 필요가 없어 save, resto..
지난 글에서는 6개를 넘는 매개변수를 서브루틴에 넘기는 방법과 그 예제를 살펴보았다. 이번 글에서는 서브루틴의 값 반환 중 '구조체'를 반환하는 경우를 중점적으로 정리해보고자 한다. 서브루틴의 값 반환 서브루틴에서 값을 반환할 때, word 하나 사이즈의 데이터를 반환하는 것은 %i0 레지스터를 통해 값을 넘기면 되었다. 그리고 서브루틴을 호출한 함수 입장에서는 %o0 위치에서 반환 값을 읽어올 수 있었다. 그렇다면 아래 C 코드와 같이 구조체를 반환하는 경우는 어떻게 받아올 수 있을까? struct point { int x; int y; }; struct point zero() { struct point local; local.x = 0; local.y = 0; return local; } struct..
지난 글에서는 register set 과 register window overflow / underflow 에 대해 정리하였다. SPARC는 CWP, WIM 2가지 값을 이용해 오버플로우나 언더플로우가 발생하는지 확인하고, 처리하였다. 이번 글에서는 서브루틴에 매개변수를 전달하는 방법을 정리하였다. 서브루틴의 매개변수 전달 서브루틴의 매개변수를 전달할 때, 전에는 그냥 %o0 ~ %o5 를 사용한다고 정리하였다. 그런데 만약 매개변수의 개수가 6개를 넘어가면 어떻게 해야할까? SPARC에서는 매개변수의 순번에 따라 데이터를 넘기는 방식이 다르다. 6번째 매개변수까지 6번째 매개변수까지는 전에 정리했던대로 o-register 를 이용하여 매개변수를 전달한다. %o0~%o5 를 사용할 수 있다. %o6 은 ..
지난 글에서는 함수를 호출하는 call 명령어와, 이와 비슷하게 코드의 실행을 조정하는 jmpl 명령어, 그리고 이전 주소로 복귀하는 ret 명령어와 retl 명령어에 대해 정리하였다. 이번 글에서는 call 명령어를 호출한 이후, 함수의 시작을 알리는 역할로 불리는 save 명령어에 대해 정리하고자 한다. 'Save' Instruction save 명령어는 서브루틴을 위한 공간을 할당하는 명령어로서, 함수의 시작을 나타낸다. save 명령어는 2가지 기능을 한다. 첫번째 기능은 스택 메모리에 사용자가 지정한 사이즈 (스택 프레임의 사이즈) 만큼 공간을 할당한다. 공간을 할당하는 것은 %fp, %sp 의 이동과 같다. %fp 은 스택 프레임의 시작점, %sp 는 스택 프레임의 끝 점을 의미한다. 스택 공..