[Computer Architecture] Logical Operations and Procedure Call

G·2023년 3월 16일
0

Computer Architecture

목록 보기
4/16
post-custom-banner

Logical Operations

논리 연산은 다음과 같다.

shift

맨 마지막 2i2^i(i = 상수)만큼 곱하거나 나누는 연산이다. 이진수로 나타냈을 때, 한 칸씩 앞으로 shift(옮긴다)한다 생각하면 된다.

sll $t2, $s0, 4 # $t2 = $s0 << 4
srl $t2, $s0, 4 # $t2 = $s0 >> 4

AND

and $t0, $t1, $t2
t1과 t2 and 연산 이후 t0에 저장

OR

or $t0, $t1, $t2

NOT Operations

nor $t0, $t1, $zero
0과의 nor 연산을 통해 not을 수행한다.

Conditional Operations

  • beq rs, rt, L1
    if (rs == rt)면, L1으로 점프한다. L1은 주소이다.
  • bne rs, rt, L1
    if (rs != rt)면, L1으로 점프한다.
  • j L1
    조건없이 L1으로 점프한다.
  • slt rd, rs, rt
    if (rs < rt) rd = 1, else rd = 0
  • slti rt, rs, constant
    if (rs < constant) rt = 1, else rt = 0

\leq와 같은 비교연산은 없을까? 저런 비교연산은 CPU clock period를 늘리기 때문에, period가 작은 연산엔 시간 낭비가 일나고 frequency도 줄기 때문이다.

if statement

if (i==j) f = g+h;
else f = g-h;

f,g는 $s0, $s1이다.

bne $s3, $s4, Else
add $s0, $s1, $s2
j Exit
Else: sub $s0, $s1, $s2
Exit: …

while statement

while (save[i] == k) i += 1;

Loop: sll $t1, $s3, 2
add $t1, $t1, $s6
lw $t0, 0($t1)
bne $t0, $s5, Exit
addi $s3, $s3, 1
j Loop
Exit: …

Basic Blocks(참고)

Basic Blocks란 점프가 일어나거나 점프되는 block이 아니다.(이곳에서 명령어 최적화를 한다.)

Signed vs Unsigned

s0=11111111111111111111111111111111s0 = 1111 1111 1111 1111 1111 1111 1111 1111s1 = 0000 0000 0000 0000 0000 0000 0000 0001
slt $t0, $s0, $s1 # signed
–1 < +1  $t0 = 1
sltu $t0, $s0, $s1 # unsigned
+4,294,967,295 > +1  $t0 = 0

Procedure Calling

함수 호출을 위한 과정을 알아보자.

  • 함수 호출 인자들을 레지스터에 저장한다.
  • 함수 코드로 점프한다.
  • 지역변수 등 함수에 필요한 값들을 레지스터에 배치한다.
  • 함수를 수행한다.
  • 반환값을 레지스터에 저장한다.
  • 호출 시점 다음 instruction으로 점프한다.

이전에 $t, $s 레지스터를 확인했다. 남은 레지스터를 알아보자.

  • $a0 – $a3: 함수 인자를 저장 (reg’s 4 – 7)
  • $v0, $v1: 리턴값을 저장 (reg’s 2 and 3)
  • $gp: 전역, 정적 변수를 저장하는 메모리 영역의 주소를 저장 (reg 28)
  • $sp: 스택 메모리의 주소(top 마지막 부분) 저장(reg 29)
  • $fp: 스택 메모리의 주소(시작 부분) 저장 (reg 30)
  • $ra: 리턴할 주소 저장 (reg 31)
  • jal ProcedureLabel
    다음 명령어(반환 위치)를 $ra에 저장 후 함수로 점프
  • jr $ra
    $ra의 값을 program counter 레지스터에 저장: 다음 명령어는 반환 위치가 된다.(리턴)
    case/switch statment 사용가능.

Exmple of leaf(함수 반환 예시)

int leaf_example (int g, h, i, j)
{
int f;
f = (g + h) - (i + j);
return f;
}

• Arguments g, …, j in $a0, …, $a3
• f in $s0 (hence, need to save $s0 on stack)
• Result in $v0

Example of non-leaf(함수 호출 후 반환 e.g. 재귀)

이 경우, 함수를 호출하는 함수의 리턴 주소와 매개변수를 스택에 저장해야함.
함수 수행이 끝난 후 복원

int leaf_example (int g, h, i, j)
{
int f;
f = (g + h) - (i + j);
return f;
}

• Argument n in $a0
• Result in $v0


유심히 봐야할 곳은 리턴할 때 n이 1일 때, 스택에 8만 더하고(리턴 값(4바이트)와 매개변수(4바이트) 를 무시) 1리턴, 만약 n이 1이 아니면 값을 꺼내고 반환값을 계산해주고 리턴한다.

$fp


$fp 레지스터는 하나의 함수가 시작될 때, $sp의 자리로 set된다. 이러한 이유는 특정함수가 시작되고 나서 함수에 관한 데이터들이 스택에 저장되는데, 함수의 시작점이란 것을 알려주는 것이다. 시작 후 매개변수와 리턴 주소 등이 저장되고 이후에 너무 많은 데이터가 있다면 $sp로 찾기 힘들 수 있다. $fp에 대한 상대주소로 쉽게 찾을 수 있을 것이다

profile
열심히 안 사는 사람
post-custom-banner

0개의 댓글