Recommanded Free YOUTUBE Lecture: <% selectedImage[1] %>

Contents

번역 : 강웅빈 감수 : 프갤러들

17장 Jump와 Branch 명령들

http://chortle.ccsu.edu/AssemblyTutorial/Chapter-17/ass17_1.html

컴퓨터의 장점은 반복되는 작동을 할 수 있고, 또한 데이터를 사용하여 작동을 변화시킬 수 있다는 것이다. 현대적인 프로그램 언어는 이러한 컴퓨터의 능력을 제어구조를 사용하여 표현한다. 반복되는 작동은 while 구조로 표현할 수 있고. 작동을 변화 시키는 것은 if-then-else 구조로 표현할 수 있다.

프로세서의 기계명령 자체에 이러한 구조가 존재하는 것은 아니다. 어셈블리어 자체도 이러한 구조를 가지고 있지는 않다. 어셈블리어로 프로그램할때는 기본적인 어셈블리 명령을 가지고 이러한 구조들을 직접 만들어 내야한다. 그런 구조를 만들기 위한 기본적인 명령이 jump명령과 branch 명령이다.

장의 주제:

  • Jump 명령:
- j 명령 (jump)
  • 조건에 따른 Branch 명령:
- beq 명령 (조건이 같을 경우 분기한다) - bne 명령 (조건이 같지않을 경우 분기한다)

질문: 프로그램이 실행될 때, 각각의 기계명령이 있는 메모리장소도 메모리주소로 접근 할 수 있겠습니까. (힌트: 주메모리의 모든 바이트를 주소로 접근할 수 있다).

기계주기(복습)

http://chortle.ccsu.edu/AssemblyTutorial/Chapter-17/ass17_2.html

답: 예. 메인메모리의 모든 바이트는 주소를 가지고 있습니다.

attachment:MachineCycle_kor.GIF

(모든 명령의 크기는 32비트 MIPS를 기준으로 한다) 프로그램이 실행중일때 프로그램의 명령어들은 메인메모리에 위치해 있다. 명령의 주소는 4바이트 길이의 명령중에 첫 바이트(가장 낮은 주소)의 주소이다.

하나의 기계주기에 하나의 기계명령이 수행된다. 그림에서처럼 기계주기의 첫단계에서는 PC(프로그램 카운터)는 메모리로 부터 읽어올 명령의 주소를 담고있다. 명령이 프로세서에 읽히고 나면 실행준비는 끝난다.

기계주기의 중간단계에서 PC는 불러온 명령의 다음 명령을 순차적으로 가리키도록 4바이트씩 증가한다. PC가 증가된 이후 이미 불러온 명령이 실행된다.이런식으로 계속 기계주기는 반복 된다. 기계주기를 따라 자동적으로 명령은 순차적으로 실행된다.

기계주기의 가장 마지막 단계에서 jump명령을 실행함으로써 PC에 새로운 주소를 집어넣는다. Jump명령을 수행한 이 후 기계주기의 첫단계에서는 jump명령으로 변화된 새로운 주소의 명령을 불러온다.프로세서는순차적으로 jump명령 다음에 오는 명령을 실행하는 것이 아니라 jump명령에 의해 메모리의 지정된 곳으로 "뛰어(jump)" 버린다.

하지만 PC가 변경되기위해서는 하나의 기계주기가 소모된다. PC가 바뀌기전에 jump명령 바로 다음의 명령이 읽혀와서 실행된다. 이 명령을 수행하고나서야, 그 다음 수행할 명령이 jump명령이 지정한 주소의 명령이다. 메모리에서 jump명령 다음에 위치한 명령을 분기지연슬롯(branch delay slot)이라고 한다.

이러한 지연이 존재하는 이유는 MIPS가 파이프라인화(pipelined) 되어있기 때문이다. 일반적으로 명령들은 순차적으로 실행된다. 실행 속도를 높이기 위해 프로세서는 미리 여러개의 순차적인 명령들을 읽어들여 처리하기 시작한다. 기계주기에서 이처럼 미리불러온 명령의 실행단계에 이르면 이 명령이 요구하는 대부분의 작업은 이미 끝나있다. 이렇게 미리 불리어져 쳐리되는 명령들은 '명령 파이프(instruction pipe)' 안에 있다 또는 파이프라인화된 명령이라고 표현한다.

다시 말하면 jump가 실행되는 시점에서 jump 다음의 명령의 실행은 거의 끝나 있다는 말이다. jump다음에 있는 명령의 실행을 끝 마친 후에야 PC의 변경이 일어난다.

jump명령 다음의 명령(분기지연슬롯)은 항상 실행 된다. 이것이 실행된 후에 jump로 지정된 주소의 명령이 실행된다. 종종 분기지연슬롯은 무작동명령(no-op instruction)으로 채운다.

SPIM시뮬레이터는 파이프라인 기능을 끌 수 있게 하지만, 실제 MIPS32 하드웨어에선 그럴 수 없다.

질문: 무작동명령(no-op instruction)이 하는 일이 무엇 입니까?

역주 참조: Instruction_pipeline

PC 변경하기

http://chortle.ccsu.edu/AssemblyTutorial/Chapter-17/ass17_3.html

답: 아무 일도 하지 않습니다. 자주 쓰이는 노옵 명령은 sll $0,$0,0 입니다

attachment:MachineCycle_kor.GIF

다음은 순차적으로 메모리에 저장된 명령들을 보여준다. "load" 와 "add"는 일반적 명령을 의미한다. jump명령은 PC를 어디로 바꿀 것인지 보여준다(실제 MIPS명령은 이보다 복잡하지만 나중에 다루겠다.)

마지막 명령인 노옵은 분기지연슬롯을 채우면서 PC를 바꿀 시간을 번다. 이 프로그램은 한번 실행되면 멈추지 않고 끊임없이 4명령을 반복하여 수행한다.

주소 명령(자세한 것은 생략) 명령이 실행되는 시점(기계주기 그림의 마지막단계)에서 PC가 담고있는 주소
............... ........... 00400000
00400000 load 00400004
00400004 add 00400008
00400008 jump 0x00400000 0040000C
0040000C no-op 00400000 -- jump 명령이 지정한 주소
jump명령으로 루프 구조를 만들었다. jump명령의 목적은 PC에 주소 0x00400000을 넣는 것이다. 분기지연슬롯의 명령이 실행된 후에야 PC는 지정된 점프 주소를 담고 있다.

질문: (생긱이 필요한 질문) jump명령이 점프하는곳이 데이터가 아닌 명령어인지 확인해주는 장치가 하드웨어에 존재 합니까?

연습

http://chortle.ccsu.edu/AssemblyTutorial/Chapter-17/ass17_4.html

답: 아니오. cpu는 jump명령다음에 무엇이 있던지간에 그것을 읽어들입니다. 프로그램의 일부가 아닐 수도 있습니다.

attachment:MachineCycle_kor.GIF 이해를 돕기 위한 개략적인 예제 프로그램이다. 명령들은 실제 명령이 아니다. 명령들보다는 jump명령과 jump의 목적지에 주의를 기울이자.

주소 명령 (자세한 것은 생략) 현재 명령 실행후의 PC (기계주기의 맨 아래 단계)
............... ........... 00450000
00450000 load 00450004
00450004 load 00450008
00450008 add 0045000C
0045000C store 00450010
00450010 jump 0x00450000 004500__
00450014 no-op 004500__
jump명령의 목적지는 0x00450000이다.

질문: 빈칸을 채우세요.

Jump 명령

http://chortle.ccsu.edu/AssemblyTutorial/Chapter-17/ass17_5.html

답:
주소 명령 (자세한 것은 생략) 현재 명령 실행후의 PC (기계주기의 맨 아래 단계)
............... ........... 00450000
00450000 load 00450004
00450004 load 00450008
00450008 add 0045000C
0045000C store 00450010
00450010 jump 0x00450000 00450014
00450014 no-op 00450000
대강 윤곽만 잡은 위의 예제 프로그램에서 jump 명령은 PC에 32비트 크기의 주소를 올렸다.

어떻게 32비트 크기의 명령이 32비트 크기의 주소를 지정할 수 있을까? 명령의 비트들중 몇몇은 opcode로 사용되어야만 한다.다음은 jump명령의 어셈블리 버전이다.

j    target     # 1 기계주기의 지연(delay)후에
                # PC 는 target 주소를 담는다. 

다음은 위의 명령을 기계어로 표현한 것입니다.

   6              26
000010 00000000000000000000000000    -- 기계 명령을 필드(field)로 묶어서 보는것

opcode         target                -- 필드(field)가 의미하는 것

주소를 지정하기 위해서 26비트가 사용되었다. 26비트의 target주소가 32비트로 전환되는 것이다.다음은 전환되는 과정이다. 실행시 jump명령이 수행될 때 다음의 작동이 일어난다.

명령은 항상 4의 배수의 주소에서 시작한다.(바꿔말해 워드정렬되어있다) 그러므로 32비트 명령 주소의 하위 2비트는 항상 "00"이다. 26비트의 target을 왼쪽으로 2자리 이동시키명 28비트 크기의 워드 정렬된 주소가된다.(다시말해 하위 2비트가 "00"이된다)

이제 주소의 상위 4비트를 채우는 일만 남았다. 이 4비트는 PC의 상위 4비트로부터 가져온다. PC 상위 4비트를 28비트에 붙여서 32비트 크기의 주소를 결과적으로 만들어 낸다.

attachment:jumpAddressForm.gif

질문: 이와같은 동작이 실행되는 동안 PC는 어떤 명령의 주소를 담고 있습니까?

대부분의 jump와 branch는 지역적이다

http://chortle.ccsu.edu/AssemblyTutorial/Chapter-17/ass17_6.html

답: PC는 jump 명령주소 바로 다음주소를 담고 있다.(Jump 지연 슬롯)

대부분의 jump 명령과 branch명령이 지정하는 주소는 근접지역의 주소들이다. jump가 지정하는 주소와 jump 명령 다음에 오는 주소는 상위의 4비트가 같은 경우가 대부분이다. 그러므로 jump가 지정하는 주소도 PC가 담고 있는 상위 4비트의 영역안에 주소인 경우가 대부분이다.

물론 어셈블리 언어로 프로그램하는 사람은 jump나 branch가 올바른 주소를 지정하는지 주의깊게 살펴 보아야한다. 컴파일러가 소스프로그램을 기계어로 번역할 때도 컴파일러는 주소에 상당한 주의를 기울인다. 이 수업과정에서 여러분이 작성하는 작은 프로그램의 경우에서는 jump 명령이 지정하는 주소의 상위4비트는 PC가 담고있는 상위 4비트와 항상 같은 경우일 것이다.

jump 명령으로는 32비트의 주소공간 중에 어느 임의적인 주소로 마음대로 jump를 할 수 없다. Jump명령은 항상 다음 범위안에 있는 주소중에 하나로 jump해야만 한다.

wxyz 0000 0000 0000 0000 0000 0000 0000
                   .
                   .
                   .
wxyz 1111 1111 1111 1111 1111 1111 1100

위에서 wxyz는 PC의 상위 4비트를 나타낸다. 거의 모든 경우에 jump명령과 jump 명령이 지정하는 주소 모두 이 범위안에 있다.

지금 공부하는 시점에서는 이러한 세부사항들이 너무복잡하고 어려운 것처럼 보일 수 도 있다. 그렇지만 걱정할 필요는 없다. 먼저 일단 이해하고 나면 보여지는 것처럼 그렇게 어려운것은 아니다. 그리고 어셈블러가 대부분의 세부사항을 처리한다.(하지만 공부하는 과정에서 여러분은 어셈블러가 하는일을 직접 해보는 것이다).

질문: 어떤 분은 여기서 Jump명령을 opcode를 사용하지 않고 프로세서가 실행중에 32비트의 주소를 접하게되면 자동적으로 그 주소로 점프 할 수 있도록 만들어 볼 수는 없을까라고 생각해볼 수 있다.

이러한 생각이 가능할까요?

jump 연습

http://chortle.ccsu.edu/AssemblyTutorial/Chapter-17/ass17_7.html

답: 안됩니다. 주소, 기계명령 그리고 많은 데이터들이 32비트 패턴입니다. 앞뒤를 점검하지 않고서는 주소인지 아닌지 알 길이 없습니다. 예를 들어, 읽혀진 패턴이 0x00000000이라고 할 때 메모리의 첫 바이트를 의미하는지, 아니면 sll $0,$0,0 명령인지 알 수 없습니다.

아래의 프로그램은 점프 명령이 어떻게 만들어 지는가를 보여준다. 간단하게 설명하기 위해, jump명령을 제외한 모든 명령은 무동작(no-op)명령이다. jump명령은 PC를 프로그램의 첫 명령으로 옮긴다. 제일 마지막 명령은 jump지연슬롯을 채운다.

Address Machine Instruction Assembly Instruction
00400000 0000 0000 0000 0000 0000 0000 0000 0000 sll $0,$0,0
00400004 0000 0000 0000 0000 0000 0000 0000 0000 sll $0,$0,0
00400008 0000 0000 0000 0000 0000 0000 0000 0000 sll $0,$0,0
0040000C 0000 0000 0000 0000 0000 0000 0000 0000 sll $0,$0,0
00400010 000010 00 0001 0000 0000 0000 0000 0000 j firstInstruction
00400014 0000 0000 0000 0000 0000 0000 0000 0000 sll $0,$0,0
j 기계 명령의 제일 왼쪽 6비트가 op코드 입니다. 나머지 26비트가 올바른지는 프로그래머가 확인 하여야 합니다.

질문:
  1. jump대상의 32비트 주소를 쓰세요:
0x00400000 ______________________________ 2. jump명령의 26비트를 쓰세요: _________________________ 3. 왼쪽으로 2자리 쉬프트 하세요: ___________________________ 4. PC의 상위 4비트가 무엇입니까? ____ 5. (4)를 (3)의 왼쪽에 붙이십시오: __ _________________________ 6. (5)와 (1)이 같습니까? _____

심볼화된 주소(symbolic address)

http://chortle.ccsu.edu/AssemblyTutorial/Chapter-17/ass17_8.html

답: 1. jump대상의 32비트 주소를 쓰세요:: 0x00400000 0000 0000 0100 0000 0000 0000 0000 0000 2. jump명령의 26비트를 쓰세요: 00 0001 0000 0000 0000 0000 0000 3. 왼쪽으로 2자리 쉬프트 하세요: 0000 0100 0000 0000 0000 0000 0000 4. PC의 상위 4비트가 무엇입니까? 0000 5. (4)를 (3)의 왼쪽에 붙이십시오: 0000 0000 0100 0000 0000 0000 0000 0000 6. (5)와 (1)이 같습니까? 같습니다.

PC의 상위 4비트가 무엇인지 어떻게 알 수 있습니까?. jump 명령의 주소가 무엇인지 알고 있기 때문에 PC에 담겨진 비트가 무엇인지 알 수 있습니다. 결국 상위 4비트는 PC로부터 가져온 것 입니다.

이런식으로 26비트만의 필드로도 32비트 크기의 주소를 지정할 수 있다. 하지만 이것을 일일이 기억하고 계산해서 하는일은 번거롭다. 만약 기계어로 직접 프로그램을 한다면 번거롭지만 일일이 주소를 기억하고 계산하면서 프로그램을 해야 하지만, 어셈블리어에서는 어셈블러가 이러한 일을 대신해 준다. 다음 짧은 프로그램을 살펴보자.

## jump.asm
##

      .text
      .globl  main

main: 
      sll    $0,$0,0
      sll    $0,$0,0
      sll    $0,$0,0
      sll    $0,$0,0
      j      main
      addiu $8,$8,1 
      
## 파일의 끝

전 시간에 해보았던 예제와 비슷한 프로그램이다. 심볼 주소 main은 첫번째 명령의 주소이다. 어셈블러는 점프명령문 j main을 main의 주소로 올바르게 jump될 수 있도록 적절한 26 비트 필드를 갖는 기계명령으로 번역한다.

분기지연슬롯(branch delay slot)은 레지스터 $8의 값을 1만큼 증가 시키는 명령으로 채워졌다.

질문: j main 명령이 5번 수행된 후에 8번 레지스터는 무슨 값을 담고 있겠습니까? SPIM은 프로그램이 시작될 때 모든 레지스터를 0으로 초기화 합니다.

프로그램 실행

http://chortle.ccsu.edu/AssemblyTutorial/Chapter-17/ass17_9.html 답: 5. loop가 매번 실행될때마다 분기지연슬롯 명령은 $8의 값을 1만큼 증가시킵니다.

다음 SPIM의 그림은 저번 장에서 작성했던 프로그램을 보여준다. 프로그램을 실행할때는 PC의 값을 0x400000으로 맞추어야 한다. 분기지연이 되는 것을 보기 위해서는 SPIM의 Option를 따로 지정해야 한다.

attachment:branchDelayRun.gif

어셈블러는 우리가 직접 작성했던 것과 같은 jump 기계명령을 생성한다.(17.6과 비교하여 보자). 어셈블러를 사용해서 심볼화된 주소로 프로그램하는것이 훨씬 쉽다는 것을 알 수 있다.

질문: while의 구조를 만들기 위해서는 jump 명령만 사용하면 될까요?

조건 분기(conditional branch)

http://chortle.ccsu.edu/AssemblyTutorial/Chapter-17/ass17_10.html

답:아니오. 무한 루프는(infinite loops)는 만들 수 있습니다. 하지만 while이나 if-then-else 구조를 만들기 위해서는 추가적인 명령이 필요합니다.

조건분기명령(conditional branch instruction)은 특정한 조건이 참일 경우에만 새로운 주소로 분기한다. 대부분 조건은 두레지스터의 값을 비교하는 것이다. 다음은 beq(값이 같을 경우 분기) 명령이다.

beq  u,v,addr   # if 레지스터 $u의 값 == 레지스터 $v의 값
                #     같을 경우 1기계주기 지연 후에 PC  <-- addr 이 된다.
                # else
                #     다를 경우에는 분기하지 않는다. 

두 레지스터에 있는 비트 패턴을 비교한다. 비트 패턴이 같다면 PC는 지정된 주소로 바뀐다. Jump 명령의 경우처럼 beq명령 바로 다음에도 분기지연 슬롯이 있다.

질문: 32비트 크기의 beq 명령에 32비트 크기의 주소를 직접 집어넣을 수 있습니까?

If와 While

http://chortle.ccsu.edu/AssemblyTutorial/Chapter-17/ass17_11.html 답: 아니요. jump 명령의 경우와 유사한 문제입니다.

attachment:beqChart.gif

beq명령은 더작은 필드를 분기하는 주소를 지정하는데 사용한다. 이 필드를 가지고 32비트 크기의 주소를 만들어 내야하기때문에 여러가지 장치가 필요하다. 지금 세부과정을 논하는 것은 생략하기로 한다.

beq명령과 같은 분기 명령들은 루프나 분기구조를 만드는데 사용한다. 위의 플로우차트는 분기 조건을 보여준다. 다음은 어셈블리로 위의 구조를 표현한 것이다.

        ...                # 값을 $8과 $9에 올린다. 
        beq  $8,$9,cont    # 같을 경우 분기한다.
        sll  $0,$0,0       # 분기 지연슬롯
        ...                # 조건에 따라서 
        ...                # 실행되는 
        ...                # 명령들.
cont:   add   $10,$10,$11  #항상 실행된다.
(어떤 명령이든 분기명령의 목적지(target)가 될 수 있다. 이 경우에 add명령이 하나의 예로 쓰였다)

질문: 예제의 레지스터 $8과 $9이 담고 있는 비트 형태를 항상 숫자로 간주 하여야만 할까요?

BNE 명령

http://chortle.ccsu.edu/AssemblyTutorial/Chapter-17/ass17_12.html

답:아니오. beq명령은 각 레지스터의 32 비트 패턴이 같은 것인가를 알아 봅니다. 비트 패턴은 어떤 것이든 표현할 수 있습니다.

다음은 동일하지 않을 경우 분기하는 bne 명령 입니다.
bne  u,v,addr   # if   $u =/=  $v (두 레지스터의 패턴이 같지 않다면)
                #     PC  <-- addr (하나의 기계주기의 지연 이후 PC는 분기하기로 지정된 주소를 담는다) 
                # else(다르지 않을 경우)
                #     아무런 효과도 없다.
질문: 분기 명령을써서 if-then-else구조를 구현할 수 있을까요?

어셈블리로 만드는 if-then-else 구조

http://chortle.ccsu.edu/AssemblyTutorial/Chapter-17/ass17_13.html 답:예

attachment:twoWayChart.gif

어셈블리에서는 조건분기 명령과 jump명령을 함께 사용하여 if-then-else 구조를 만들 수 있다. 다음의 예를 주의 깊게 살펴보자. 이 예제에서는 몇개의 어셈블리 명령을 사용하여 기본적인 if-then-else의 제어구조를 만들었다.
        ...                # 기본 값을 $8과 $9에 올린다. 
                          
        beq  $8,$9,equal   # 같을경우 equal로 분기한다.
        sll  $0,$0,0       # 분기 지연 슬롯
        ...                #  같지 않을 경우 수행된다.
        ...                #  
        ...                #  
        j    cont       # cont로 jump한다.
        sll  $0,$0,0       # 분기 지연 슬롯
equal:  ...                #
        ...                #  같을 경우 수행되는 명령들
        ...                #
cont:   add   $10,$10,$11  # 어떤 경우라도 실행된다.
물론 beq명령 대신에 다른 종류의 조건 분기 명령이 사용될 수 있다. 만약 java나 c의 if-then-else구조처럼 참일 경우 수행되는 명령들을 앞쪽에 배치하고 거짓일 경우 수행되는 명령들을 그 다음에 배열하고 싶다면 다른 종류의 분기문을 사용하면 된다.

질문: 위의 if-then-else의 구조에서는 참일 경우나 거짓일 경우가 if-then-else구조 바깥에 첫번째 문장 즉 cont로 제어의 흐름이 항상 귀결 됩니다.어셈블리에서 꼭 이런식으로 if-then-else 구조를 만들어야 할까요?

절대값 구하기

http://chortle.ccsu.edu/AssemblyTutorial/Chapter-17/ass17_14.html 답: 꼭 그런식으로 만들 필요는 없습니다.

어셈블리어로 스파케티 코드를 만들기가 쉽다. 스파게티 코드를 만들지 않도록 고수준의 언어가 구현하는 구조를 어셈블리에서도 프로그래머가 구현한다. 어셈블리 코드를 짜기전에는 프로그램의 순서도를 그려보거나 C나 JAVA같은 고수준의 언어로 초안을 잡아보자. 어셈블리 코드 소스에는 코드앞에 구현하는 코드가 순서도의 어떤 부분인지 주석으로 설명을 하자.

attachment:absValChart.gif

위의 순서도는 심볼 주소 A가 담고있는 정수의 절대값을 계산하는 프로그램이다. 다음 프로그램은 위순서도의 논리를 따른 프로그램의 시작 부분이다.
## absVal.asm
##
## A의 절대값을 계산한다.

      .text
      .globl  main

main: 
# A 값을 가져오기
        lui   $10,0x1000     # 베이스 레지스터를 초기화 한다.
        lw    $8,___($10)    #  A의 값을 올린다.
        ___   $0,$0,0        #  무작동 no-op

# 음수인가를 확인한다.


# -A를 저장한다.


done:   

      .data
A:    .word   -1

## 파일의 끝
심볼 주소 A는 0x10000000주소에서 시작한다고 가정한다. lui명령은 그 주소를 베이스레지스터 $10값으로 지정하고 있다. 질문:빈칸을 채워보자.

부호비트(sign bit) 이동시키기

http://chortle.ccsu.edu/AssemblyTutorial/Chapter-17/ass17_15.html 답: 다음을 보자.

A가 음수를 담고 있는지 아닌지 확인 하기위해서는 부호비트가 1인지 아닌지 확인하면 된다. 부호비트를 확인하기 위해서 부호비트를 레지스터의 0번 비트 자리로 이동시킨다. 만약 A가 양수를 담고 있다면 레즈스터의 값은 0일 것이다.이 프로그램은 정수값이 2의 보수로 표현되었다고 가정한다.

## absVal.asm
##
##  A의 절대값을 계산한다.


      .text
      .globl  main

main: 
# Get A
        lui   $10,0x1000     # 베이스 레지스터를 초기화 한다.
        lw    $8,0($10)        #  A의 값을 올린다.
        sll   $0,$0,0           #  무작동(no-op)

# Is A negative?
        srl   $9,$8,_____       #  부호 비트를 0번 자리로 이동시킨다. 
        beq   $___,$_____,done  #  부호비트 sign bit == zero 이라면, done으로 분기한다.
        sll   $0,$0,0                      #무작동(no-op)


# Store -A


done:   

      .data
A:    .word   -1

## 파일의 끝

분기 지연 슬롯은 무작동(no-op)명령으로 채워졌다. 질문: 빈칸을 채워보자.

-A 저장하기

http://chortle.ccsu.edu/AssemblyTutorial/Chapter-17/ass17_16.html

답:다음을 보자.

부호비트를 오른쪽으로 31번 이동시킨다.이렇게 함으로써 목적레지스터 $9의 하위비트에 부호비트를 집어넣을 수 있다. $9의 값이 0인지 아닌지 검사하기 위해서는 항상 0의 값을 담고 있는 $0와 $9을 beq명령을 사용해서 비교해본다.

## absVal.asm
##
##  A의 절대값을 계산한다.

      .text
      .globl  main

main: 
# A값을 구한다
        lui   $10,0x1000      # 베이스 레지스터를 초기화 한다.
        lw    $8,0($10)      #  A의 값을 올린다.
        sll   $0,$0,0        #무작동(no-op)

# 음수인지 아닌지 확인한다.
        srl   $9,$8,31       #  부호비트를 레지스터 0번 비트로 이동 시킨다.
        beq   $0,$9,done     #  sign bit == zero, 같을경우 done으로 분기한다.
        sll   $0,$0,0

# -A 저장하기
        sub   $8,$___,$8     #  A를 부정한다.
        sw    $8,___($___)   # 저장한다.

done:   sll   $0,$0,0

      .data
A:    .word   -1

## 파일의 끝
이제 -A를 계산한후 A를 다시 저장하는 과정을 해보자. done 주소는 무작동(no-op) 명령을 담고있다.

질문: 빈칸을 채워보자.

전체 프로그램

http://chortle.ccsu.edu/AssemblyTutorial/Chapter-17/ass17_17.html

답:다음을 보자.

다음은 전체 프로그램이다. 텍스트 파일로 복사하여 SPIM에서 실행해보자. PC는 0x00400000로 초기화 된다는 것을 유념하자. F10을 사용하여 한단계씩 실행할 수 있다.
## absVal.asm
##
## A의 절대값을 계산한다.
##
## Registers:
##   $8  --- A 값 2의 보수로 표현된 정수
##   $9  --- A의 부호값
##   $10 --- 베이스 레지스터. 

        .text
        .globl  main

main: 
# A 값을 구하기
        lui   $10,0x1000     #  베이스 레지스터를 초기화한다.
        lw    $8,0($10)      #  A값을 올린다.
        sll   $0,$0,0

# 음수여부를 확인한다.
        srl   $9,$8,31       #  부호 비트를 0번 자리로 옮긴다
        beq   $0,$9,done     #  sign bit == zero, done
        sll   $0,$0,0

# Store -A
        sub   $8,$0,$8       #  A를 부정한다.
        sw    $8,0($10)      #  저장한다.

done:   sll   $0,$0,0        #  분기대상

        .data
A:      .word   -1

## 파일의 끝
질문: 만약 심볼주소 A가 부호없는 정수를 담고 있더라도 프로그램이 올바르게 작동합니까?

17장 끝

답: 아니오

http://chortle.ccsu.edu/AssemblyTutorial/Chapter-17/ass17_18.html

논의된 주제

  • MIPS의 분기지연슬롯
  • 어떻게 PC의 변경이 분기를 구현하는가
  • jump명령
  • jump명령으로 이동할 수 있는 범위
  • 심볼릭 주소
  • beq명령
  • bne명령
퀴즈 과제를 풀어봅시다.