문제 1
– 다음 C 문장에 해당하는 MIPS 어셈블리 코드를 작성하시오.
변수 g, i, j는 레지스터 $s1, $s3, $s4에 할당되었고
배열 A와 B의 시작 주소는 레지스터 $s6, $s7에 들어 있다고 가정하며
A, B의 각 원소는 4 바이트 워드이다.
• B[g] = A[i] + A[j];
[풀이]
sll $t0, $s3, 2 // $t0 = i * 4
add $t0, $t0, $s6 // $t0 = &A[i]
lw $t0, 0($t0) // $t0 = A[i]
sll $t1, $s4, 2 // $t1 = j * 4
add $t1, $t1, $s6 // $t1 = &A[j]
lw $t1, 0($t1) // $t1 = A[j]
sll $t2, $s1, 2 // $t2 = g * 4
add $t2, $t2, $s7 // $t2 = &B[g]
add $t3, $t0, $t1 // t3 = A[i] + A[j]
sw $t3, 0($t2) // B[g] = A[i] + A[j]
문제 2
– 다음과 같은 MIPS 명령어들이 주어졌을 때 이에 해당하는 C 문장은 무엇인가?
변수 f는 레지스터 $s0에 할당되었고,
배열 A와 B의 시작 주소는 레지스터 $s6, $s7에 들어 있다고 가정한다.
addi $t0, $s6, 4
add $t1, $s6, $0
sw $t1, 0($t0)
lw $t0, 0($t0)
add $s0, $t1, $t0
[풀이]
addi $t0, $s6, 4 -> $t0 = $s6 + 4, t0는 A[1]
add $t1, $s6, $0 -> $t1 = $s6 + $0, t1은 A[0]
sw $t1, 0($t0) -> $s6 + $0을 $t0에 넣음, A[0]을 A[1]에 넣음
lw $t0, 0($t0) -> $s6 + $0(=A[0])을 $t0에 넣음
add $s0, $t1, $t0 -> $s0 = $t1+ $t0, f는 A[0]+ A[1]의 값
따라서
A[1] = A[0];
f = A[0] + A[1];
문제 3
– 레지스터 $s0와 $s1이 값 0x80000000과 0xD0000000을 갖고 있다고 가정한다.
– 3.1 다음 명령어를 수행한 후의 $t0 값은 무엇인가?
• add $t0, $s0, $s1
[풀이]
Add $t0, $s0, $s1은 $t0 = $s0 + $s1를 의미함.
0x80000000 + 0xD0000000 = 0x150000000 이므로 $t0의 값은= 0x150000000 이다.
레지스터의 사이즈는 32비트 까지이다. 따라서 $t0의 값은 0x50000000이다.
– 3.2 $t0 값이 원하는 값인가 아니면 오버플로가 일어났는가?
• 값들을 부호있는 정수로 생각하고 답하시오.
[풀이]
0x80000000를 binary 로 표현하면 1000 0000 0000 0000 0000 0000 0000 0000(32bits)
0xD0000000를 binary 로 표현하면 1101 0000 0000 0000 0000 0000 0000 0000(32bits)
이 둘을 합한 $t0의 값은 10101 0000 0000 0000 0000 0000 0000 0000(33bits) 이다.
따라서 1bit가 늘어났으므로 오버플로우가 발생하였다.
– 3.3 다음 명령어를 수행한 후의 $t0 값은 무엇인가?
• sub $t0, $s0, $s1
[풀이]
2진수끼리의 뺄셈은 2의 보수를 더하는 방식으로 구하면 된다.
Sub $t0, $s0, $s1 은 $t0 = $s0 - $s1을 의미한다.
$s1 은 binary로 표현하면 1101 0000 0000 0000 0000 0000 0000 0000(32bits) 이고,
이 값의 2의 보수를 구하면 0011 0000 0000 0000 0000 0000 0000 0000 이다.
따라서 $t0 = $s0 - $s1 은
1000 0000 0000 0000 0000 0000 0000 0000(32bits)
+ 0011 0000 0000 0000 0000 0000 0000 0000(32bits)
= 1011 0000 0000 0000 0000 0000 0000 0000(32bits)
이다. 결과 값은 0xB0000000 이다. 오버플로우는 일어나지 않았다.
– 3.4 $t0 값이 원하는 값인가 아니면 오버플로가 일어났는가?
• 값들을 부호있는 정수로 생각하고 답하시오.
[풀이]
$t0 값은 원하던 값이다. 오버플로우가 일어나지 않았다.
– 3.5 다음 명령어를 차례로 수행한 후의 $t0 값은 무엇인가?
• add $t0, $s0, $s1
add $t0, $t0, $s0
[풀이]
$t0 = $s0 + $s1 = 0x80000000 + 0xD0000000 = 0x15000000 을 binary로 표현하면
1000 0000 0000 0000 0000 0000 0000 0000(32bits)
+ 1101 0000 0000 0000 0000 0000 0000 0000(32bits)
= 10101 0000 0000 0000 0000 0000 0000 0000(33bits) 이어서 1bit가 늘어났다.
이 값에 $s0을 더해준다.
$t0 = $t0 + $s0 = 0x15000000 + 0x80000000를 binary로 표현하면
10101 0000 0000 0000 0000 0000 0000 0000(33bits)
+ 1000 0000 0000 0000 0000 0000 0000 0000(32bits)
= 11101 0000 0000 0000 0000 0000 0000 0000(33bits)
이므로 32비트가 아닌 33비트이다. 레지스터는 32비트까지 가능하므로
$t0의 값은 1101 0000 0000 0000 0000 0000 0000 0000 이다. 이는 0xD0000000 이라고 표현할 수도 있다.
– 3.6 $t0 값이 원하는 값인가 아니면 오버플로가 일어났는가?
• 값들을 부호있는 정수로 생각하고 답하시오.
[풀이]
$t0의 값은 11101 0000 0000 0000 0000 0000 0000 0000(33bits) 이다.
레지스터의 사이즈는 32비트 이므로 오버플로우가 일어났다.
문제 4
– 레지스터 내용을 다음과 같이 가정하자.
$t0 = 0xAAAAAAAA, $t1 = 0x12345678
– 4.1 다음 두 명령어를 차례로 수행한 후의 $t2 값은 무엇인가?
• sll $t2, $t0, 4
or $t2, $t2, $t1
[풀이]
$t2은 $t0 << 4한 값이다.
$t0은 0xAAAAAAAA 이고 이걸 binary로 표현하면 10101010101010101010101010101010 이며 shift left를 4만큼 하면 10101010101010101010101010100000 이다. 이 값은 AAAAAAA0 으로도 표현 가능하다.
그리고 $t2와 $t1를 가지고 or 연산을 해보려고 한다.
$t2는 현재 10101010101010101010101010100000 이고 $t1은 0x12345678 이다. $t1을 binary로 표현하면 10010001101000101011001111000이다.
$t2와 $t1 둘을 or 연산을 수행하고 나면 값은 10111010101111101111111011111000가 나오고 16진수로 표현한다면 $t2은 0xBABEFEF8 이 된다.
– 4.2 다음 명령어를 차례로 수행한 후의 $t2 값은 무엇인가?
• sll $t2, $t0, 4
andi $t2, $t2, -1
[풀이]
$t2는 $t0에서 shift left를 4만큼 한다. 그러면 0xAAAAAAAA에서 0xAAAAAAA0이 된다. 따라서 $t2 = AAAAAAA0 이 된다.
andi $t2, $t2, -1은 $t2와 -1 사이의 AND 연산(&)을 한 값이 $t2라는 의미이다.
AAAAAAA0 은 10101010101010101010101010100000 인데 이 값과 -1을 AND 연산을 하면 10101010101010101010101010100000 이다. 따라서 $t2는 AAAAAAA0 이다.
– 4.3 다음 명령어를 차례로 수행한 후의 $t2 값은 무엇인가?
• srl $t2, $t0, 3
andi $t2, $t2, 0xFFEF
[풀이]
$t2은 $t0을 3만큼 shift right 한 값이다. 계산하면 0xAAAAAAAA은 10101010101010101010101010101010 이고 여기서 3만큼 shift right하면 10101010101010101010101010101(16진수로 0x15555555)가 되는데 이 값이 $t2이다.
이번에는 $t2와 0xFFEF(2진수로 표현하면 1111111111101111)를 AND 연산을 해보면
0x00005545 가 나온다. 따라서 $t2의 값은 0x00005545이다.
문제 5
어떤 C 순환문을 어셈블리어로 작성한 프로그램이 아래와 같이 주어졌다.
이 프로그램을 다시 C 순환문으로 변환하라.
이때, 원 C 순환문에서 사용한 인덱스 i는 $t1에,
정수 result는 $s2에
정수 배열 MemArray의 시작(베이스) 주소는 $s0에 있다고 가정한다.
add $t1, $0, $0
LOOP: lw $s1, 0($s0)
add $s2, $s2, $s1
addi $s0, $s0, 4
addi $t1, $t1, 1
slti $t2, $t1, 100
bne $t2, $0, LOOP
[풀이]
add $t1, $0, $0 // i = 0
LOOP: lw $s1, 0($s0) //배열의 시작 주소를 $s1에
add $s2, $s2, $s1 // result += $s1
addi $s0, $s0, 4 // $s0 += 4
addi $t1, $t1, 1 // i += 1
slti $t2, $t1, 100 // $t1이 constant 100보다 작으면 $t2를 1로 셋팅. 아니면 0으로셋팅
bne $t2, $0, LOOP // $t2의 값이 1이면 LOOP로 돌아가서 반복.
따라서 정리하면 아래와 같다.
i = 0;
do {
result += MemArray[i];
i++;
} while(i<100);