지난 글에서는 Unsigned Integer / Signed Integer 연산에 대해 정리하였다.
Unsigned 연산에서는 덧셈 뺄셈시 Carry가 중요했다.
만약 덧셈을 했는데 Carry 가 발생했다면 오버플로우가 발생한 것이고, 뺄셈을 했는데 Carry가 발생했다면 빼는 수가 빼지는 수보다 더 큰 것임을 의미했다. (그래서 이것이 subcc 를 비교에 사용하는 이유이다.)
Signed 연산에서는 덧셈 뺄셈시 Overflow 가 중요했다.
만약 양수와 양수를 더했는데 음수가 나온 것처럼 N 이 활성화 되었다면 오버플로우가 발생한 것이고, 원래 의도된 계산 값이 양수임을 알 수 있다.
만약 음수와 음수를 더했는데, 양수가 나온 것처럼 N 이 활성화되지 않았다면, 오버플로우가 발생한 것이고, 원래 의도된 계산 값의 부호가 음수임을 알 수 있다.
이번 글에서는 하드웨어를 아주 간단히 정리만 하고, 32bit 를 넘어가는 큰 수를 어떻게 SPARC는 연산하는지 정리하여본다.
이는 가산기의 회로도를 간단하게 나타낸 것이다.
n비트의 수를 더하는 회로이다. 두 수와 캐리를 받아서 연산결과와 캐리를 출력하는 회로가 쭉 이어져 있다.
맨 첫자리에서도 캐리를 받는 이유는 2의 보수를 만들고 1을 더할 때 이 자리로 1이 들어오기 때문에 필요하다고 한다.
이는 CC를 발생시키는 회로도의 이미지이다.
FA 는 Full Adder (전가산기) 를 의미한다.
회로도는 어셈블리를 배울 때는 (그리고 교수님 피셜, 앞으로의 인생에서도) 쓸 일이 없을 것이라고 하신다.
근데 그럴만도 한게, 컴공은 하드웨어 위에서 돌아가는 프로그램을 설계하는 분야니 하드웨어는 교양적인 지식으로 넓게 알고, 깊게 공부하는 건 전전이 공부하는 분야가 아닐까
이제 큰 수 연산에 대한 내용을 정리해보자.
만약 32bit 를 넘어가는 수를 연산해야한다면 어떻게 해야할까?
사실 간단하다. 32bit 공간 2개, 3개, 4개...를 이어붙여서 그걸 하나의 수로 취급하고 연산하면 되지 않겠는가
위 이미지처럼 Signed Integer 를 64비트로 표현한다면 32bit 레지스터 하나는 통으로 수를 나타내는 데 사용하고,
그 부분에서 연산하였을 때 발생한 캐리를 다음 32bit 레지스터에 넘겨서 수를 표현하는데 사용하도록 한다.
그렇다면 이제 중요한 것은 '이건 32bit 공간 여러개를 이어붙여서 연산해야 하는 것' 임을 어떻게 CPU에게 알리느냐일 것이다.
이 때 사용하는 것이 x 옵션(?)이 붙은 명령어를 사용하는 것이다. (addx, subx 등)
x 옵션이 붙은 addx 명령어는 이전에 넘어온 캐리를 받아 그 값을 같이 활용하여 add 연산을 진행한다.
따라서 addx 명령어를 사용하기 전에는 반드시 addcc 명령어로 cc를 발생시키는 연산이 선행되어야 한다.
만약 숫자가 더 커진다면, 중간에 cc를 받고 또 cc를 발생시키는 부분이 필요할 것이다.
이럴 때는 x옵션?과 cc 옵션?을 모두 가진 xcc 명령어를 사용하면 된다.
큰 수 뺄셈을 2의 보수를 이용한 덧셈연산으로 직접 바꿔서 연산해보는 코드 예제도 있다.
사실 이 코드는 '함수' 의 코드라서 아직은 실행시킬 수 없다.
이렇게 main 이 아니라 별도 함수를 정의하고, 함수를 실행하는 상황을 가정한 코드이다.
넘어오는 캐리를 받기 위해, 처음에 inccc 로 캐리를 발생시키면서 1을 증가시키고,
이후에는 9번째 줄에서 addxcc 로 캐리를 받아 g 레지스터와 덧셈을 하여 연산 결과를 그대로 유지한채 캐리만 이동시키도록 한 점이 인상깊다.
10번째 줄의 addx 도 마찬가지이다.
(강의록에서 subx 는 carry를 빌려온다 (borrowed) 고 하는데, 이게 구체적으로 무슨 의미인지 이해가 안감
=> 수업중에는 말로만 설명해주시고, 2의 보수로 바꿔서 더하는 방법으로 자세히 설명하심 => 질문하기)
지금까지 간단한 가산기의 하드웨어 구조와 큰 수 연산에 대해 정리하여 보았다.
다음 글에서는 곱셈과 나눗셈, 그리고 subroutine 에 대해 정리하여 보겠다.
'CS > 어셈블리' 카테고리의 다른 글
[SPARC] 15. 논리 연산 명령어 (0) | 2023.10.14 |
---|---|
[SPARC] 14. 곱셈과 나눗셈 그리고 서브루틴 (2) | 2023.10.11 |
[SPARC] 12. Unsigned/Signed Integer & Carry / Overflow (0) | 2023.10.06 |
[SPARC] 11. 산술 연산과 Condition Code (0) | 2023.10.05 |
[SPARC] 10. SPARC에서 사용하는 메모리 종류 (0) | 2023.10.04 |