어셈블리언어

CS/어셈블리

[SPARC] 37. 실수 계산 & FPU & FPU Instructions

지난 글에서는 Floating Point 의 개념과 10진 소수를 이진 소수로 상호 변환하는 과정을 정리하였다. 이번 글에서는 Floating Point 간 사칙 연산을 정리하고자 한다. SPARC는 FPU 라고 하는 실수 계산용 arithmetic units (산술 연산 유닛) 이 존재하여, 덧셈/뺄셈/곱셈/나눗셈 기능을 지원한다. 그래서 정수와는 다르게, 곱셈과 나눗셈을 '명령어' 수준으로도 지원한다. 먼저 FPU를 살펴보기 전에, 실수의 산술 연산 과정을 정리해보자. 실수 덧뺄셈 실수의 덧뺄셈은 아래 과정으로 진행된다. 1. significand를 맞춘다. 2. significand 끼리 더해준다. 3. 결과를 Normalize 한다. 4. 기존 자릿수에 맞게 유효숫자를 맞춘 뒤, 필요하다면 다시 ..

CS/어셈블리

[SPARC] 34. Leaf Subroutine & Pointer Type Argument

지난 글에서는 서브루틴에서 구조체를 다루는 방법을 정리하였다. %sp+64 위치에 구조체 시작 주소를 넘겨서 직접 해당 구조체를 다루는 것이 포인트였다. 서브루틴 내에서는 %fp+64로 접근하는 것이 차이점이었다. 이번 글에서는 리프 서브루틴에 대해 정리하고자 한다. Leaf Subroutine 트리에서 자식 노드가 없는, 즉, degree = 0 인 노드를 leaf 노드라고 한다. 함수의 call graph 를 그렸을 때, leaf 노드에 해당하는 함수는 가장 마지막에 호출되어 더 이상 함수를 추가로 호출하지 않는 함수를 의미한다. 리프노드는 그냥 평범한 서브루틴과 비슷하게 구현하면 된다. 그런데 만약 리프노드에서 수행하는 작업이 너무 간단해서 새 스택 프레임을 할당할 필요가 없어 save, resto..

CS/어셈블리

[SPARC] 32. 서브루틴 매개변수 전달

지난 글에서는 register set 과 register window overflow / underflow 에 대해 정리하였다. SPARC는 CWP, WIM 2가지 값을 이용해 오버플로우나 언더플로우가 발생하는지 확인하고, 처리하였다. 이번 글에서는 서브루틴에 매개변수를 전달하는 방법을 정리하였다. 서브루틴의 매개변수 전달 서브루틴의 매개변수를 전달할 때, 전에는 그냥 %o0 ~ %o5 를 사용한다고 정리하였다. 그런데 만약 매개변수의 개수가 6개를 넘어가면 어떻게 해야할까? SPARC에서는 매개변수의 순번에 따라 데이터를 넘기는 방식이 다르다. 6번째 매개변수까지 6번째 매개변수까지는 전에 정리했던대로 o-register 를 이용하여 매개변수를 전달한다. %o0~%o5 를 사용할 수 있다. %o6 은 ..

CS/어셈블리

[SPARC] 25. Stack Frame

지난 글에서는 SPARC의 (근데 찾아보니 아마도 기본적인 컴퓨터 공통의) 메모리 맵을 정리하면서 BSS 섹션의 내용을 추가로 정리하였다. bss 섹션은 정적 메모리 영역 중 하나로, 이곳에 할당한 변수는 모두 0으로 초기화되는 특징이 있었다. 이번 글에서는 다시 '스택' 영역으로 돌아와서, 새로운 스택 영역의 메모리를 할당하는 단위인, '스택 프레임' 에 대해 정리하고자 한다. Stack Frame (스택 프레임) 스택 프레임은 나중에 정리할 '서브루틴' 과 관련되어 있다. 서브루틴(함수)는 호출될 때마다, 레지스터 공간과 함께 스택 공간을 새로 할당한다. 이때 각 함수마다 할당하는 스택 공간의 크기를 임의로 지정할 수 있는데, 이 스택 공간을 '스택 프레임' 이라고 한다. 즉, 스택 프레임은 서브루틴..

CS/어셈블리

[SPARC] 23. label로 data 영역의 메모리주소 가져오기 (set, sethi)

data영역 메모리에 데이터를 저장하고 나서 메모리에 저장된 데이터를 가져오기 위해 그 메모리 위치를 label로 표시할 수 있다. 이때, 문자열로된 label로부터 실제 메모리 주소값을 가져오는 명령어가 set 이다. .data i_m: .word 4 j_m: .word 9 k_m: .word 3 위 코드에서는 data 영역에 4바이트 크기의 메모리 공간 3개에 각각 4, 9, 3을 저장하고, 각 메모리 주소를 i_m, j_m, k_m 으로 표시하였다. 이때 i_m, j_m, k_m 이 가리키는 메모리 주소는 아래와 같이 가져올 수 있다. set i_m, %o0 위 코드는 i_m의 주소값을 가져와서 %o0 레지스터에 저장하는 코드이다. 한편, 지난 지연주기 최적화 글에서 set은 nop에 바로 넣을 수..

CS/어셈블리

[SPARC] 22. 정적 메모리와 경계정렬

지난 글에서는 메모리와 레지스터 사이 데이터를 주고받는 방법을 정리해보았다. 간단히 정리하면, ld [메모리주소], 레지스터 형태로 메모리에서 값을 불러온다. 메모리주소는 불러올 데이터 크기의 배수여야한다. 만약 ldd 로 8byte 를 불러온다면 레지스터는 짝수번째 레지스터여야한다. 메모리주소는 레지스터와 레지스터(상수) 합으로 표현되며, -레지스터만 없으면 된다. st 레지스터, [메모리주소] 형태로 레지스터 값을 메모리에 저장한다. 마찬가지로 메모리 주소는 저장할 데이터 크기의 배수여야 하고 만약 std 로 8byte 를 저장한다면 레지스터는 짝수번째 레지스터여야 한다. 메모리주소는 레지스터와 레지스터(상수) 합으로 표현되며, -레지스터만 없으면 된다. 이번 글에서는 메모리의 영역 중 static ..

CS/어셈블리

[SPARC] 21. 메모리

메모리 개요 메모리는 프로그램의 명령어와, 그 명령어가 사용할 데이터가 들어있는 공간이다. (폰 노이만 구조에서는 프로그램의 명령어도 데이터이다.) 저장 단위는 byte 단위이며, 레지스터와 달리 4byte로 고정되지 않고 1, 2, 4, 8 byte 등으로 유동적인 사이즈로 저장할 수 있다. 하지만 레지스터가 한번에 4byte 씩 파악하기 때문에, 명령어의 사이즈는 4byte 로 고정되어있다. 메모리 접근 메모리에 접근하여 데이터를 읽고 쓰는 명령어는 기본적으로 아래와 같은 형태를 띈다. Load, 메모리의 데이터를 불러와(loading) 레지스터에서 읽는 것 ld [메모리주소], 레지스터주소 메모리 -> 레지스터 순서로 읽으면 되니 이해가 간단하다. 메모리주소는 R + A 형태로 표현되고, [ ] 는..

CS/어셈블리

[SPARC] 20. switch - case 구현하기

지난 글에서는 분기 최적화에 대해 정리하였다. 분기 최적화를 하는 방법에는 from before, from after, annulled branch 3가지가 있었다. from before 은 분기 명령어 이전에 실행되는 명령어를 가져오는 것으로, 보통 mov 명령어를 이용한 레지스터 값 세팅을 가져올 수 있다. from after 은 분기 명령어 이후에 실행되는 명령어를 가져오는 것으로, 보통 분기 이후 실행되는 명령어 중, 분기 여부에 상관없이 반드시 실행되는 명령어를 당겨올 수 있었다. annulled branch 는 분기를 할 때는 delay slot 명령어를 실행하고, 분기를 하지 않을 때는 delay slot 명령어를 실행하지 않는 분기 명령어로서, 반드시 분기 후 첫 명령어를 delay slo..

CS/어셈블리

[SPARC] 19. Delay Slot Optimization

지난 글에서는 Branch Delay Slot 이 발생하는 이유를 파이프라이닝 과정을 따라가보며 살펴보았다. 요약해보면, Branching 여부는 E 단계에서 결정되기 때문에, E 단계에서 분기를 하더라도, E 단계 시점의 F 단계에 있던 명령어가 파이프라인에 남아 계속 실행되는 문제 때문에 이를 비워둠으로써 Delay Slot 이 발생하였다. 이번 글에서는 이렇게 Delay Slot 을 비워두지 않고, 다른 명령어로 채워 활용하는 방법. Delay Slot Optimization 에 대해 정리해보고자 한다. 최적화 개요 그렇다면 어떻게 분기 명령어를 쓴 직후, nop 를 넣지 않고 최적화를 할 수 있을까? nop 대신 분기에 (전체 코드 실행에) 영향을 주지 않는 다른 명령어를 넣으면 된다. 즉, de..

CS/어셈블리

[SPARC] 18. Branch Delay Slot 의 발생 이유

지난 글에서는 분기 명령어의 종류와 사용 방법, 그리고 예제들을 살펴보았다. 간단하게 정리하면 분기 명령어 중 조건 분기와 무조건 분기는 CC 코드를 이용해 분기 명령어에 적힌 조건을 파악하기 때문에, 명령어를 실행시키기 전에 반드시 조건식의 CC 코드를 발생시켜 두어야 했다. 그리고 분기 명령어의 실행 직후에는 Branch Delay Slot 이 반드시 발생하였다. 이번 글에서는 Branch Delay Slot 이 발생하는 이유를 실제 명령어의 실행 파이프라인을 따라가보며 정리해보고자 한다. 다음과 같은 명령어를 순차적으로 실행시킨다고 하자. ble next_r - A add R1, R2, R3 - B mov 130, R4 - C ... next_r: - D add R3, R4, R1 set str, ..

에버듀
'어셈블리언어' 태그의 글 목록