지난 글까지 산술 명령어를 정리하였다.
산술 명령어 (덧셈 뺄셈, 곱셈, 나눗셈, 나머지) 연산 중, 덧셈과 뺄셈은 기계 명령어로 구현되고,
특히 뺄셈은 2의 보수를 이용하여 덧셈 연산되는 것이 특징이었다.
연산 데이터에는 signed integer 와 unsigned integer 가 있었는데, 덧셈 / 뺄셈시 각 데이터 종류별로 연산 결과에서 나오는 CC의 의미가 달라지게 되었다.
unsigned 데이터 연산에서는 Carry 가 중요한 의미를 지녔으며, 덧셈시 오버플로우, 뺄셈시 캐리가 존재한다면 A < B 아니라면 A >= B 의미를 지니는 것으로 해석하게 되었다.
signed 데이터 연산에서는 oVerflow 와 Negative 코드를 통해 연산 결과의 부호를 알아낼 수 있고,
이를 통해 두 수의 대소 비교를 할 수 있었다.
V 가 0 일 때, N = 0 이면 의도된 연산 결과는 양수
V 가 0 일 때, N = 1 이면 의도된 연산 결과는 음수
V 가 1 일 때, N = 0 이면 의도된 연산 결과는 음수 (오버플로우로 양수처럼 보이지만)
V 가 1 일 때, N = 1 이면 의도된 연산 결과는 양수 (오버플로우로 음수처럼 보이지만)
이번 글에서 논리 연산 명령어를 정리하고자 한다.
논리 연산 명령어 - 기계 명령어
우선 기계 명령어부터 정리해보자.
SPARC 에서 사용되는 논리 명령어 중 기계 명령어는 아래와 같다.
and, andcc
andn, andncc
xor, xorcc
or, orcc
xnor, xnorcc
orn, orncc
익숙한 것도 있지만 낯선 명령어도 있다.
하나씩 정리하면 다음과 같다.
AND / ANDCC
두 비트가 모두 1이면 1, 아니면 0 을 반환한다. CC 는 CC 코드를 생성하는 연산자이므로, 이후 설명은 생락한다.
1 and 1 = 1
1 and 0 = 0
0 and 1 = 0
0 and 0 = 0
ANDN / ANDNCC
a and (not b) 연산을 수행한다.
1 and (1)` = 0
1 and (0)` = 1
0 and (1)` = 0
0 and (0)` = 0
XOR / XORCC
두 비트가 서로 다르면 1, 아니면 0 을 반환한다.
1 xor 1 = 0
1 xor 0 = 1
0 xor 1 = 1
0 xor 0 = 0
XNOR / XNORCC
a xor (not b) 연산을 수행한다.
(왜 얘는 xorn 이 아닌걸까..)
1 xor (1)` = 1
1 xor (0)` = 0
0 xor (1)` = 0
0 xor (0)` = 1
OR / ORCC
두 비트중 하나라도 1이 있으면 1, 아니면 0 을 반환한다.
1 or 1 = 1
1 or 0 = 1
0 or 1 = 1
0 or 0 = 0
ORN / ORNCC
a or (not b) 연산을 수행한다.
1 or (1)` = 1
1 or (0)` = 1
0 or (1)` = 0
0 or (0)` = 1
논리 연산자에서 CC 는 Z, N 만을 사용한다.
C와 V는 무조건 0으로 설정한다.
논리 연산 명령어 - 합성 명령어
논리 연산자의 합성명령어는 아래와 같은 명령어들이 있다.
not a
not a, b
mov a, b
clr a
tst a
NOT A / NOT A, B
not a = xnor a, %g0, a
not a, b = xnor a, %g0, b
(연산 결과를 그대로 a 에 넣는지, 새로운 b 에 넣는지 차이이다.)
a의 비트를 abcd 라고 하자.
%g0 은 항상 0 이므로 이를 0과 xnor 한다는 말은
(abcd) xor (1111) 와 같다.
xor 은 '다르면 1, 같으면 0 을 반환하므로,
abcd 중 모든 1에 대해서는 0을 반환하고,
abcd 중 모든 0에 대해서는 1을 반환한다.
즉, not 연산이 발생한다.
MOV A , B
mov a, b = or %g0, a, b
a 와 0 을 or 연산하면, a 가 그대로 똑같이 반환된다.
그 값을 b 에 넣어주는 것이므로, a 의 값을 b 로 복사해서 넣는 효과가 생긴다.
(근데 or a, %g0, b 로 하면 안되는 것일까? 왜 not 에서와는 달리 %g0 을 먼저 넣었을까?)
CLR A
clr a = or %g0, %g0, a
0과 0을 or 하면 0 이 나온다.
그 값을 a 에 넣어주는 것이므로, a 의 값을 0으로 초기화 (clear) 시키는 것과 같다.
TST A
tst a = orcc a, %g0, %g0
a 와 0 을 or 연산하면, a 가 그대로 똑같이 반환된다.
그 값을 %g0 에 넣어주는데, %g0 은 항상 0으로 고정된 값이므로, 연산 결과를 버리게 된다.
이때 orcc 를 사용하였으니 CC코드가 발생하므로, 연산 결과는 버리고 a와 0을 or 한 CC만을 봄으로서
a의 값을 확인 (test) 해보겠다는 것이다.
이때 논리연산의 CC 는 N, Z 만 나오므로, 이 수가 음수인지, 0인지 판별하는 용도가 된다.
이는 다음에 작성할 분기 여부를 판별할 비교에서 사용하게 된다.
지금까지 SPARC 의 논리 연산 명령어에 대해 정리해보았다.
다음 글에서는 SPARC의 bit 연산 명령어를 정리해볼 예정이다.
bit 연산까지 끝나면 SPARC의 모든 연산 명령어 정리가 끝난다.
그 이후에는 분기와 분기 최적화에 대한 내용을 정리할 것이다.
'CS > 어셈블리' 카테고리의 다른 글
[SPARC] 17. 분기 명령어 (0) | 2023.10.15 |
---|---|
[SPARC] 16. 비트 연산 명령어 (0) | 2023.10.15 |
[SPARC] 14. 곱셈과 나눗셈 그리고 서브루틴 (2) | 2023.10.11 |
[SPARC] 13. Hardware & 큰 수 연산 (0) | 2023.10.11 |
[SPARC] 12. Unsigned/Signed Integer & Carry / Overflow (0) | 2023.10.06 |