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

Contents

번역 : 강웅빈 감수 : 프갤ㅤ횽들

구조를 갖추어 프로그램 하기

http://chortle.ccsu.edu/AssemblyTutorial/Chapter-19/ass19_1.html

이 장에서는 컴퓨터 과학에서 가장 흥미로운 두가지 주제중의 하나인, 프로세서에서 어떤 종류의 기계명령이 필요한가와 어떻게 프로그램을 작성할 것인가를 논하여 본다. 하나의 프로세서를 동작하는데는 여태까지 공부한 명령들만으로도 충분하다. 구조를 갖추어 프로그램하는 방법이 신뢰할 수 있는 프로그램을 작성하는데 사용된다.

장의 주제:

  • 계산하는 능력 (Computing power)
  • 최소한의 기계명령 (The minimum set of machine instructions)
  • 동작 처리량 또는 스루풋(Throughput)
  • 복합적인 명령 세트 vs 간소화된 명령 세트 (Complex instructions sets vs. Reduced instruction sets)
  • 구조를 갖추어 프로그램 하기 (Structured programming)
  • 최소한의 제어구조(The minimum set of control structures)
이 장에 대부분이 다음 질문과 연관된 것이다. 하지만 이런 질문을 이상하게도 기초강좌에서는 물어보지 않고 무시한다.

질문: 어떤 경우에 프로세서가 다른 프로세서보다 성능이 좋다고 할 수 있습니까?

계산하는 능력

http://chortle.ccsu.edu/AssemblyTutorial/Chapter-19/ass19_2.html

답: 프로세서가 다른 프로세서는 수행할 수 없는 것을 수행할 수 있을 때 성능이 좋다고 할 수 있다. 하지만 이 말은 모호하게 들릴 수 도있다.

이제까지 여러 장을 통해 여러 종류의 명령을 공부했다.

  • 비트 단위의 논리 명령
  • 정수의 산술 연산 명령
  • 메모리 접근 명령
  • 조건에 따라 프로그램의 흐름을 변화시키는 명령
여러분은 어떤 프로세서가 다른 프로세서 보다 강력해 지기 위해서는 얼마나 많은 명령을 가지고 있어야 하는가라고 궁금해 할 수 있다. 답을 하자면 위에서 공부한 명령만으로도 충분하다고 할 수 있다. 컴퓨터의 힘(power) 또는 능력이라는 용어는 모호한 표현이다. 때때로 사람들은 컴퓨터의 능력을 논할 때 계산 속도를 의미하기도 하고 프로세서가 계산할 수 있는것을 의미하기도 한다. 보통 두가지를 복합해서 모호하게 용어를 사용한다. 여기서 우리는 다음과 같은 정의를 사용한다.

컴퓨터가 계산하는 능력: 두 프로세서가 각프로세서의 기계어로 컴파일 되어질 수 있는 동일한 프로그램을 실행할 수 있고 동일한 결과를 산출한다면 두 프로세서는 동일한 계산 능력을 가지고 있다. 적절한 컴파일 과정을 거쳐 각 프로세서의 기계어로 해석되어진 모든 프로그램에서 위와 같은 정의가 사실이라면 두 프로세서는 동일한 계산 능력을 가지고 있다.

예를 들어 두 프로세서가 동일한 계산능력을 가지고 있다고 가정해보자. 그러한 경우 한 프로세서에 작동되는 특정한 프로그램은 다른 프로세서에서도 실행될 수 있어야만 하고 두 프로세서가 동일한 결과를 산출하여야 한다. 각 프로세서에서 컴파일후 기계어로 산출된 모든 프로그램이 각 프로세서에서 실행될 수 있어야만하고 동일한 결과를 산출하여야 한다.

때때로 프로그램의 실행결과는 컴파일러에 따라 다를 수 있다. 예를 들어 각기 다른 C 컴파일러의 경우 데이터 형태 int에 사용되는 비트의 갯수는 각기 다를 수 있다. 하지만 이것은 컴파일러의 문제이지 프로세서 때문은 아니다. 컴퓨터의 능력(power)을 논할 때는 각각의 프로세서에 동일한 프로그램을 프로세서에 적절한 기계어로 컴파일 할 수 있는가 그리고 이 기계어 프로그램이 각각의 프로세서에서 동일한 결과를 산출할 수 있는가 만이 중요한다.

프로세서의 속도는 정의에서 제외 되었다. 컴퓨터의 능력과 프로세서의 속도를 독자적으로 논의하는 것이 도움이 된다. 메모리와 그래픽보드같은 주변기기또한 정의에서 제외 되었다.

질문: 64비트를 정수(integer)로 사용하는 프로그램이 32비트 크기의 워드(word)를 사용하는 프로세서에서 실행될 수 있습니까?

동일한 능력의 프로세서

http://chortle.ccsu.edu/AssemblyTutorial/Chapter-19/ass19_3.html

답: 실행될 수 있습니다. 프로세서가 어떠한 크기의 word를 사용하든지 어떤 크기의 정수 연산이라도 구현할 수 있습니다. 프로세서의 정수 연산명령(그러한 명령을 프로세서가 가지고 있다면)과 비트를 조작하는 명령으로 구현할 수 있습니다.

예를 들어보자: 16비트 인텔 마이크로프로세서에서 64비트 크기의 정수로 산술 연산하는 프로그램을 실행할 수 있다.각각의 64비트 작동마다 여러가지 16비트 기계명령을 사용하여 구현하 수 있다.

현대적인 예를 들어보자: 펜티엄1과 펜티엄4 프로세서는 동일한 프로그램을 실행할 수 있다. 펜티엄4는 펜티엄1보다 매우 빠른 기계주기를 가지고 있다. 펜티엄4는 펜티엄1보다 훨씬 다양한 종류의 기계명령을 가지고 있다. 만일 여러분이 어떤것을 계산하는 c 프로그램을 작성했다면 펜티엄1이나 펜티엄4 프로세서 모두에서 실행할 수 있다. 적절한 컴파일러가 있다는 가정하에서 계산의 결과는 펜티엄1과 펜티엄4에서 동일하다. 펜티엄1이 펜티엄4보다 훨씬 오랫동안 계산하겠지만, 프로세서의 능력의 정의에 따르면 실행 시간은 프로세서의 능력과는 관계가 없다.

1952년에 SWAC 디지털 컴퓨터는 완전수를 찾도록 프로그램 되었다. 완전수는 자신을 제외한 약수의 총합이 자신과 같은 자연수이다. 예를들어 6은 1,2,3로 나누어질 수 있고 약수의 합이 6(=1+2+3)이므로 완전수이다. 또다른 완전수로 28,496,8128이 있다. 상당한 계산뒤에 SWAC 프로세서는 완전수 33550336을 찾아 내었다.

질문: 펜티엄 프로세서도 SWAC처럼 똑같은 완전수를 발견할 수 있겠습니까?

최소한의 명령 집합

http://chortle.ccsu.edu/AssemblyTutorial/Chapter-19/ass19_4.html

답: 당연히 찾을 수 있습니다. 제 펜티엄 1.7 GHZ 프로세서는 완전수 33550336을 빠르게 찾았습니다.

하지만 컴퓨터 능력의 정의를 따른다면 펜티엄 1.7GHZ 프로세서는 SWAC프로세서보다 더강력하지는 않다.

프로세서는 주변기기와 정보를 주고받고 주변기기를 제어 해야만 한다.프로세서는 시스템 버스에 비트 패턴을 읽기와 쓰기를 하는 것과 주변기기에 할당된 특별한 주소에 읽기와 쓰기를 함으로써 정보를 주고받고 제어를 한다. 메모리에 읽기와 쓰기를 할 수있는 프로세서라면 하드 디스크를 제어할 수 있고 그래픽 보드를 제어할 수 있습니다. 이러한 것을 하는데 특별한 따로 프로세서의 능력이 필요한 것은 아닙니다.최근 프로세서에 추가된 멀티미디어 명령 같은 것이 프로세서에 특별히 추가적인 계산 능력을 부여하는 것은 아니다. 물론 그런 명령들은 편이성을 부여하고 속도를 향상시킨다.

프로세서는 최소한 어떤 기계명령들을 가지고 있어야만 하는가?

중요:비트를 조작하는 기본적인 기계명령,조건분기명령,메모리 접근명령을 지원하는 모든 프로세서는 같은 계산 능력을 가지고 있다. 모든 프로세서가 이러한 명령들을 가지고 있고 많은 추가적인 명령들도 가지고 있다. 이전 장의 정의에 따른다면 모든 프로세서가 동일한 계산 능력을 가지고 있다.

정수나 소수점을 계산하는 산술연산은 비트를 조작하는 명령을 사용하여 할 수 있다.그러므로 산술명령 자체가 기본적으로 필요한 명령은 아니다. 하지만 산술명령은 거의 모든 프로세서에 포함되어있다. 최소한의 명령 집합들 이외에 추가되는 새로운 명령이 프로세서의 계산 능력을 향상시키는 것은 아니다. 이러한 주제에 대하여 공부를 하고자 한다면 계산의 기초(foundation of computation)나 수학적 논리(mathematical logic)에 관련된 수업을 들어보자.

질문: 왜 대부분의 프로세서가 계산 능력을 최대화하기 위해서 최소한의 명령집합 이외에도 여러가지 명령을 가지고 있습니까?

편의성과 작업처리량

http://chortle.ccsu.edu/AssemblyTutorial/Chapter-19/ass19_5.html

답: 편의성과 전체적인 작업량을 높이기 위해 여러가지 명령을 가지고 있습니다.

편의성은 중요하다. 프로그램을 작성할때 적절한 MIPS 명령을 찾지 못해 힘들었을 때가 있었을 것이다. 때때로 프로그램을 작성하면서 둥그런 구멍에 네모난 말뚝을 집어넣으려고 한다는 느낌을 가질 수 도 있다. 비록 계산 능력에는 보탬이 되지 않을지라도 다양한 종류의 말뚝 같은 것을 가지고 있다면 굉장히 편리할 것이다.

편의성은 단지 인간 프로그래머만을 위한 것이 아니다. 컴파일러와 여러 시스템 소프트웨어는 기계코드를 생성한다. 다양한 종류의 명령이 제공 될 수록, 컴파일러를 만들기 쉽고 버그도 적다.

작업처리량 또는 스루풋(throughput)은 단위 시간에 프로세서 또는 전체 컴퓨터 시스템이 수행할 수 있는 계산량이다. 프로세서가 일초에 5억 개의 명령을 처리할 수 있다고 가정하자. 각각의 명령으로 더 많은 계산을 할 수록 작업처리량은 증가한다. 그렇기 때문에 대부분의 프로세서가 최소한의 명령들 이상으로 여러가지 작업을 하는 명령들을 가지고 있다.

질문: 다음의 컴퓨터 시스템을 향상하는 항목 중에서 컴퓨터 시스템의 작업처리량(throughput)을 증가시키는 것은 무었입니까?

  • 기계주기를 빠르게 한다. (500 MHz에서 1000 MHz로).
  • 시스템 버스가 전달하는 비트의 크기를 늘린다. 더많은 비트를 전달하도록 향상시킨다. (32 bits에서 64 bits로).
  • 주메모리를 증가시킨다 (128 Meg에서 512 Meg로).
  • 하드디스크의 용량을 증가시킨다. (20 Gig에서 40 Gig로).
  • 하드디스크와 메모리사이의 전송비율을 향상시킨다 (40 MBps에서 80 MBps로).
  • 모니터를 큰것으로 구입한다. (17"에서 21"로).
  • 크고 복잡한 기계명령을 여러가지 추가한다.

CISC

http://chortle.ccsu.edu/AssemblyTutorial/Chapter-19/ass19_6.html

답:

  • 기계주기를 빠르게 한다. (500 MHz에서 1000 MHz로).
o 작업처리량을 증가시킬 수 있다.초당 더많은 명령을 수행할 수 있다.
  • 시스템 버스가 전달하는 비트의 크기를 늘린다. 더많은 비트를 전달하도록 향상시킨다. (32 bits에서 64 bits로).
o 작업처리량을 증가시킬 수 있다. 한번의 이동 동작당 더많은 데이터를 움직일 수 있다.
  • 주메모리를 증가시킨다 (128 Meg에서 512 Meg로).
o 작업처리량을 증가시킬 수 있다. 데이터를 느린 디스크 메모리에 저장하는 것 보다 빠른 주메모리에 저장한다.
  • 하드디스크의 용량을 증가시킨다. (20 Gig에서 40 Gig로).
o 모든 데이터와 소프트웨어가 작은 디스크에 다들어갈 수 있다는 가정하에서 하드디스크의 용량을 증가시키는 것은 작업처리량을 증가시키는데 도움이 안된다.
  • 하드디스크와 메모리사이의 전송비율을 향상시킨다 (40 MBps에서 80 MBps로).
o 작업처리량을 증가시킬 수 있다. 프로세서가 데이터를 기다리는 시간을 줄일 수 있다.
  • 모니터를 큰것으로 구입한다. (17"에서 21"로).
o 상관이 없다.
  • 크고 복잡한 기계명령을 여러가지 추가한다.
o 증가시킬 수 도 있고 그렇지 않을 수 도 있다.

CISC (Complex Instruction Set Computer 또는 복합적인 명령들을 갖춘 컴퓨터) 프로세서는 여러가지 명령을 가지고 있다. 복합적인 명령들 중에서 어떤 명령은 기계주기당 여러가지 일을 한다. RISC (Reduced Instruction Set Computer 또는 간소화된 명령들을 갖춘 컴퓨터) 프로세서는 간소한 명령들을 가지고 있다. 대부분의 명령들이 단순하다. 하나의 CISC 명령이 처리할 수 있는 일을 하기 위해서 여러가지 RISC 명령이 필요할 수 도 있다. MIPS 프로세서는 RISC이다.

명령자체만 보고 모든 조건이 동일하다고 가정한다면 CISC의 작업 처리량이 당연히 더크다. 하지만 복합적인 명령을 구현하기 위해서는 더 큰 실리콘 칩이 필요하다. 그러므로 데이터가 이동하는 거리가 더 길어지고 더 많은 시간이 요구되고 또, 기계주기가 느려진다. 또한 CISC 명령은 여러가지 RISC 명령을 수행하는 것 보다 더 많은 시간이 걸린다. 명령의 종류가 여러가지일 경우 처리 속도를 향상시키기 위해 칩을 최적화하기가 어렵다. 단순한 명령도 복합적인 명령 때문에 최적화하기 힘들어 진다. 단순한 명령들은 칩에서 가장 빈번히 수행되는 명령들이다.

더욱이 컴파일러가 복합적인 명령을 사용하기가 쉽지 않다. 보통 컴파일러는 프로그램을 단순한 기계명령만 사용하는 프로그램으로 컴파일한다. (이 글이 쓰여진 시기를 기준으로) 어떤 컴파일러도 최근에 Pentium 칩에 추가된 MMX(multi-media extension 또는 멀티미디어 연장 명령) 명령을 사용하지 않고 있다.

질문: 여러분이 컴퓨터 게임을 작성할 때 MMX 명령을 사용하고자 한다면 무엇을 해야만 할까요?

RISC

http://chortle.ccsu.edu/AssemblyTutorial/Chapter-19/ass19_7.html

답: 게임의 일부 기능은 어셈블리를 사용하여 작성할 수 있습니다.

RISC(Reduced Instruction Set Computer 또는 간소화된 명령들을 갖춘 컴퓨터) 는 적은 갯수의 명령들를 가지고 있다. 적으면서도 산뜻하고 빠른 명령들이 제대로 상호작동하지 못하면서 다루기도 힘들고 복잡한 명령들을 모아놓은 것보다 좋다라는 생각이 RISC를 만들어 냈다.

만약 적은 숫자의 명령들로 칩을 구현한다면 칩은 좀더 많은 숫자의 범용 레지스터를 가질 수 있고 칩 자체의 메모리 캐쉬(on-chip memory cache)도 더커질 수 있고 명령 파이프라인도 가질 수 있고 속도를 향상시키는 기능을 더할 수 있다.

지난 대략 10년간은 RISC 칩이 CISC 칩 보다 우위에 있었다. 하지만 지금 현대적인 CISC 칩들은 캐쉬나 파이프라인 같은 RISC 칩의 많은 장점들을 포함한다. 현대적인 CISC 칩은 구형의 RISC 칩보다 훨씬 큰 작업 처리량(throughput)을 가지고 있다. 일반 소비자용 또는 사무용 컴퓨터는 Window용 소프트웨어를 사용할 수 있는 CISC 칩을 사용한다. 고급 워크스테이션이나 임베디드 시스템처럼 최근에 디자인된 시스템들은 RISC 칩을 많이 사용한다. 질문: 다음은 프로그램의 일부분 입니다. 프로그램이 정확합니까?
start:   ori   $8,$0,4      # $8 = 4
         ori   $9,$0,12     # $9 = 12
         addu  $10,$8,$9    # $10 = 12+4 = 16
         sll   $10,$10,2    # $10 = 16*4 = 64

버그가 없는 소프트웨어

http://chortle.ccsu.edu/AssemblyTutorial/Chapter-19/ass19_8.html 답: 코멘트가 설명하는 것이 옳다고 가정했을 때 정확한 프로그램이다,
start:   ori   $8,$0,4      # $8 = 4
         ori   $9,$0,12     # $9 = 12
         addu  $10,$8,$9    # $10 = 12+4 = 16
         sll   $10,$10,2    # $10 = 16*4 = 64

위의 답은 start에서부터 프로그램의 실행이 시작 된다고 가정한다. 만일 addu 명령부터 프로그램이 시작했다면 여전히 올바른 프로그램 이겠는가?$8과 $9번은 아마 다른 숫자를 담고있을 것이다. 프로그램의 어떤부분에 다음과 같은 코드가 있다면 addu 명령부터 위의 프로그램이 시작될 수 도 있다.
         ori   $8,$0,99     # $8 = 99
         ori   $9,$0,43     # $9 = 43
         j     start+8      # jump start뒤로 두번째 오는 어셈블리 선언문으로 점프한다.
start는 첫번째 명령을 실행할 때의 주소를 나타내는 심볼주소이다. start+8는 start로부터 8바이트 떨어진 주소를 나타낸다. jump 명령은 제어를 그 주소로 이동시킨다.

QUESTION 8: 멀리 떨어진 명령문에서 코드 블럭 중간으로 점프하여 실행하지 못하게 할 방법이 있습니까?

버그가 없는 코드블럭

http://chortle.ccsu.edu/AssemblyTutorial/Chapter-19/ass19_9.html 답: 방법이 없습니다.

attachment:codeBlock.gif

제어가 코드블럭의 중간으로 점프할 때 버그가 발생한다. 만약 그 코드블럭이 시작부터 끝까지 실행되도록 작성 되었다면, 시작하는 선언문은 반드시 실행되야한다. 실행되지 않는다면 버그가 발생할 수 있다. 다시 말하자면 코드블럭 중간으로 점프하지 말아야 한다. 코드블럭 중간으로 점프한다면 버그가 발생할 것이다.

이러한 생각이 구조를 갖추어 프로그램하자라는 방법론 중에 하나이다. 코드 블럭에서는 블럭에 들어가는 지점 (코드의 실행이 시작되는 지점) 이 유일하며 나가는 지점 (코드블럭의 실행이 종료되는 지점) 또한 유일하다. 들어가는 지점은 들어가는 조건에 의하여 명확하게 정의되고 나가는 지점은 나가는 조건에 의해 명확하게 정의 된다.

코드의 블럭이 정확하게 실행되기 위해서는 코드는 들어가는 조건이 맞을때 들어가는 지점으로부터 실행이 시작되어야 하고 만약 블럭의 코드가 버그가 없고 정확한 코드라면 나오는 조건이 부합할 때 블럭의 실행을 종료하여야 한다. 질문: 자바 C C++는 구조적인 프로그램어(또는 구조를 갖추어 프로그램하는 언어) 입니까?

구조규칙 1:코드 블럭

http://chortle.ccsu.edu/AssemblyTutorial/Chapter-19/ass19_10.html 답: 현대의 고차적인 프로그램어는 모두 구조를 갖추고 있다.

attachment:structureRule1.gif

만일 코드 블럭에 진입하는 조건은 정확하고 빠져나오는 조건이 잘못되었다면 그 블럭에는 버그가 존재하는 것이다. 만약 코드 블럭 중간으로 점프를 하여 실행할 수 있다면 블럭으로 가정하는 것은 사실이 아닐 수 도 있고 버그는 프로그램 어느 부분에서라도 존재할 수 있다. 그런 조건 아래서 버그를 찾아서 해결하기는 매우 힘든 일이다.

구조규칙 1: 코드의 블럭은 구조를 갖추고 있다. 플로우 차트 용어로 설명하자면, 유일하게 들어가는 지점과 유일하게 나오는 지점을 가지고 있는 상자는 구조를 갖추고 있다.

이러한 규칙이 당연한 말을 하는 것처럼 보일 수 도 있지만 그렇게 분명히 하자 라는 것이 기본적인 생각이다. 구조를 갖추어 프로그램하는 것은 프로그램이 정확하다는 것을 명시하는 방법중에 하나이다. 어셈블리어에서는 프로그램의 블럭을 보여주기 위한 문법이 없다. 프로그램을 디자인 할 때와 플로우 차트를 그려볼 때 블럭들을 생각해봐야 한다. 코딩 할때는 생각한 디자인을 따라야 한다.

질문: 어셈블리에서는 어떤 식으로 코드블럭을 구현 합니까?

구조 규칙1 - 구현하기

http://chortle.ccsu.edu/AssemblyTutorial/Chapter-19/ass19_11.html

답: 순차적으로 실행하고자 하는 코드를 작성하고 그 코드들 중간으로는 점프를 하지 않는다.

선언문들은 자동적으로 순서대로 실행된다. 언어 자체적으로 코드블럭의 들어가는 지점과 나가는 지점이 유일하도록 강제할 수 있는 보조적인 장치는 없다. 프로그래머가 의식적으로 이와같은 규칙을 따라야 한다.

이 규칙을 레벨화된 선언문으로만 점프하도록 하면 지켜질 수 있는 것처럼 보일 수 도 있다. 하지만 다음과 같이 코드블럭 중간에 선언문이 레벨을 가지고 있을 수 도 있다.

start:   ori   $8,$0,4      # $8 = 4
         ori   $9,$0,12     # $9 = 12
midblk:  addu  $10,$8,$9    # $10 = 12+4 = 16
         sll   $10,$10,2    # $10 = 16*4 = 64

         ....

         ori   $8,$0,99     # $8 = 99
         ori   $9,$0,43     # $9 = 43
         j     midblk       # start 다음의 midblk로 점프한다.

질문: 파스칼이나 C 또는 자바와 같이 고차원의 언어는 코드블럭을 정의하는 문법이 있습니까?

연속 또는 시퀀스

http://chortle.ccsu.edu/AssemblyTutorial/Chapter-19/ass19_12.html 답: 블럭을 정의하는 문법이 있습니다. Pascal에서는 begin과 end로 블럭을 지정합니다. C나 java에서는 {과 }로 블럭을 지정합니다.

attachment:blockSequence.gif

파스칼(Pascal), C, Java는 구조를 갖춘 언어이다. 이와 같은 언어들에서 선언문들의 코드블럭은 들어가는 지점과 나오는 지점이 유일하다. 그렇다면 두개의 코드 블럭이 연속으로 있는 경우는 어떻겠는가? 첫번째 블럭의 나오는 조건과 두번째 블럭의 들어가는 조건이 정확하다고 가정해보자. 그런 경우 두 블럭이 순서대로 따라올 수 있다.

이런경우 두 블럭의 집합을 하나의 블럭으로 간주할 수 있다. 첫번째 블럭의 들어가는 조건과 나오는 조건이 올바르다면 두번째 블럭의 들어가는 조건도 올바르다. 결과적으로 두번째 블럭의 나오는 조건도 올바르다.

두 블럭을 묶어서 보는 큰 블럭으로 볼 수 있다. 큰 블럭의 들어가는 조건이 정확하다면 큰 블럭의 나온 조건 또한 올바르다.

질문:

점선으로 그려진 큰 블럭을 봐주세요. 큰 블럭의 들어가는 조건이 올바르다면 큰 블럭의 나가는 조건은 어떻습니까?

구조규칙 2 - 연속(sequence)

http://chortle.ccsu.edu/AssemblyTutorial/Chapter-19/ass19_13.html 답: 만약 큰 블럭의 들어가는 조건이 정확하다면, 큰 블럭의 나오는 조건도 정확하다.

attachment:structureRule2.gif

만약 각각의 블럭의 나오는 조건이 다음에 오는 블럭의 들어가는 조건과 일치한다면 그 연속되는 블럭은 올바른 블럭이다. 실행은 각 블럭의 들어가는 지점으로부터 시작되고 블럭의 나오는 지점을 통해서 끝난다

구조 프로그램 규칙2: 둘 이상의 연속된 블럭은 구조를 갖추고 있다. 어셈블리어로 두번째 규칙을 구현하는 방법은 첫번째 규칙을 구현하는 방법과 같다. 프로그래머가 주의 깊게 규칙을 따라야 한다. 다시말하면 다른 지점으로부터 블럭들 내부로 점프하지 말아야 한다.

질문: 어셈블리어에서 if-then-else 구조를 구현하는 것이 가능합니까?

구조규칙 3:선택

http://chortle.ccsu.edu/AssemblyTutorial/Chapter-19/ass19_14.html 답:가능합니다.

attachment:structureRule3.gif

If-then-else 구조는 선택구조라고도 한다. 구조를 갖추어 프로그램하는 경우에 각각의 선택도 하나의 코드 블록이다. 만약 선택구조가 그림의 순서도처럼 배열 되었다면 들어가는 지점도 유일하고 나오는 지점도 유일한 구조이다. 선택구조에서 만약 들어가는 조건이 만족된다면 코드블록에서처럼 나오는 조건도 만족되어야 한다. 구조 프로그램 규칙3 : 두 코드 블록들을 선택하는 것은 구조를 갖추고 있다.

선택 구조의 들어가는 조건의 예를 들어보자. $8은 부호있는 정수를 담고있다. 나가는 조건으로 $8이 담고 있는 부호있는 정수의 절대값이 될 수 있다. 분기구조는 이러한 나가는 조건을 만족해야 한다.

질문: If문에서 볼 수 있는 조건처럼 다이아몬드 박스에 나타나는 조건이 복잡할 수 도 있습니까?

선택구조 구현하기

http://chortle.ccsu.edu/AssemblyTutorial/Chapter-19/ass19_15.html

답:물론입니다. 많은 어셈블리 선언문이 필요할지도 모릅니다.

attachment:ifExample.gif

어셈블리어에서 선택구조를 구현하기 위해 문법 자체에서 명시적으로 지원하는 것은 없다. 다음과 같이 부분적으로 구현하여야 한다. $8과 $9는 a와 b의 값을 담고 있다고 가정하자.

        ...                #   
if:     beq  $8,$9,yes     # is a==b ?
        nop                #    no
        ...                #    거짓인 블럭
        ...                #    
        ...                #  
        j    endif
        nop
yes:    ...                #   yes
        ...                #   참인 블럭
        ...                #
endif:  nop                # 항상 실행 된다.

참인 블럭과 거짓인 블럭의 순서가 고차원 적인 언어의 선택 구조와는 반대라는 것을 주목하여 보자.

이런식으로 선택구조를 구현할 수 있는 것이 유일한 방법은 아니다. 참인 블럭을 먼저 집어넣을 수 도 있다. 하지만 그럴경우 분기문 자체도 바꾸어 주어야 한다. 또한 테스트하는 조건이 복잡해 질 수도 있고 플로우차트에서는 안보여지는 여러가지 분기문과 명령문들이 필요할 수 도있다.

질문: 선택이 단일한 if-endif도 구조를 갖추고 잇습니까?

구조규칙 4:반복

http://chortle.ccsu.edu/AssemblyTutorial/Chapter-19/ass19_16.html

답:그렇다. if-then-else구조에서 else가 없는 것으로 생각하면 된다.

attachment:structureRule4.gif

while 루프같은 반복구조는 그림과 같이 배열할 수 있다. 반복구조 또한 들어가는 지점과 나오는 지점이 유일하다. 들어가는 지점은 만족해야만 하는 조건들을 가지고 있고 나오는 지점은 만족되어질 조건들을 가지고 있다. 코드의 외부 지점으로부터 구조 안으로 점프하는 명령들이 없어야 한다.

구조 규칙 4: 코드블럭의 반복은 구조를 갖추고 있다. 다른 구조들처럼 반복구조도 여러 어셈블리 코드로 만들어 졌다. 여러가지 방식으로 이러한 구조를 구현할 수 있다. 일반적으로 다음과 같이 구현된다.

while:  bltz   $8,endWh

        . . .

        j      while
        sll    $0,$0,0

endWh:  sll    $0,$0,0
어떤 명령이 조건을 시험하는 명령이 될것인가는 상황에 따라 달라질 수 있다.

질문: 파스칼이나 C 또는 Java와 같은 구조를 갖춘 언어에서는 반복구조 안에 선택 구조를 집어넣을 수 있습니까? (다시말해 while 구조 몸체안에 if-then-else 구조를 담을 수 있습니까?)

코드블럭처럼 보이죠

http://chortle.ccsu.edu/AssemblyTutorial/Chapter-19/ass19_17.html 답: 물론입니다.

여태끼지 공부한 모든 구조에서는 윗쪽에 들어가는 지점이 있고 아래쪽에 나오는 지점이 있다. 구조로 들어가거나 나오는 점프명령은 없었다. 들어가는 지점은 들어가기위해 만족해야하는 조건들을 가지고 있고 나오는 지점 또한 나올 때 만족되어야 하는 조건을 가지고 있다. 각각의 구조들을 하나의 코드 블럭으로 간주할 수 있다.

attachment:fourStructures.gif

하나의 구조가 그 구조자체 안에서 jump 명령들을 가지고 있어도 괜찮다. 어셈블리어에서 몇몇구조는 그런 식으로 구현 되었다. 구조 밖에서 보았을 때 각각의 구조는 하나의 코드 블럭으로 볼 수 있다.

질문: 루프 몸체 안에 선택구조를 갖춘 코드블록이 올 수 있습니까?

구조규칙 5:구조안의 구조(Nesting Structure)

http://chortle.ccsu.edu/AssemblyTutorial/Chapter-19/ass19_18.html 답:올 수 있다.

플로우차트를 놓고 보면 어떤 코드 블록도 구조들 중 하나의 형태로 확장시켜 생각할 수 있다. 다르게 생각하자면 플로우 차트에서 유일하게 들어가는 지점과 나오는 지점이 있다면 그 부분을 단일한 코드블록으로 볼 수 있다.

구조 규칙 5: 유일하게들어가는 지점과 나오는 지점을 가지고 있는 구조는 단일한 코드 블록이다.

예를 들자면 부호있는 정수들의 표에서 각각의 정수값의 절대값을 계산하는 프로그램을 디자인 한다고 가정하자. (1)먼저 프로그램을 하나의 블록으로 간주한다. (2)요구되는 반복구조를 그려본다.(3) 반복 구조 몸체의 세부사항를 채워넣는다.

attachment:absIterate.gif

이와는 다른 방식으로 할 수 도 있다. 절대값을 구하는 코드를 작성했다면 그것을 더큰 프로그램의 일부분으로 사용할 수 있는 하나의 코드블록으로 간주할 수 있다.

질문:복잡한 코드 블록을 구현할 때 그 부분을 서브루틴이나 함수로 작성하는 것이 좋은 생각입니까?

구조를 갖추어 프로그램할 때의 계산능력

http://chortle.ccsu.edu/AssemblyTutorial/Chapter-19/ass19_19.html

답:좋은 생각입니다. 나중의 장에서 이것을 공부합니다.

여러분은 이러한 규칙이 안정된 코드를 작성하기는 좋겟지만 너무 제한적이라고 생각할 수 도 있다. 어떤 사람들은 계산력 또한 손해를 보는것이 아닌가 생각할 수 도 있습니다. 하지만 계산능력에서 손해를 보는 것은 없다. Böhm과 Jacopini이라는 두연구가는 구조적인 형태로 어떤 종류의 프로그램도 작성할 수 있다는 것을 증명했다. 구조를 갖추어 프로그램함으로써 제어의 흐름을 제한하는 것이 계산능력을 제한하는 것은 아니다.

do-until,do-while,for 같이 여러분이 이미 알고 있을지도 모르는 다른 제어구조들이 필수불가결한 구조는 아니다. 하지만 그런 구조들은 경우에 따라 편리하게 사용할 수 있다. 그리고 그러한 구조들도 구조를 갖추어 프로그램하는 것으로 간주한다. 어셈블리어에서 그러한 구조를 프로그래머가 직접 구현해야하기 때문에 그러한 구조가 편의성을 제공하는 것은 아니다. 어셈블리어에서는 이 장에서 토론된 구조만 사용할 것을 추천한다.

여러분이 어셈블리로 작성할 필요가 있는 모든 프로그램을 구조적인 형태로 작성할 수 있다. 여러분은 문제에 대해서 생각해보고 고차원의 구조를 갖춘 언어를 사용하여 문제를 푸는 방식으로 생각해 보아야 한다. 해결방법을 찾았다면 구현하는 것은 단지 코딩을 하는 것이다.코팅은 디자인을 코드로 만드는 거의 기계적인 해석작업이다. 디자인과 코딩을 동시에 하지 말아야한다.(이상적인 세계라면 모든 프로젝트가 기한안에 맞추어 진행되고 닷컴회사들은 실패하는 법이 없을 것이다.)

질문: 구조를 갖추어 어셈블리로 프로그램을 작성할 경우 때때로 비구조적인 제어를 사용한다면 속도를 향상 시킬 수도 있습니까?

19장 끝

http://chortle.ccsu.edu/AssemblyTutorial/Chapter-19/ass19_20.html

답: 때때로 그럴 수 있다. 하지만 먼저 구조를 갖춘 버전을 작성해야한다. 구조를 갖춘 버전을 가지고 있다면 속도를 위해 최적화한 버전에 버그가 있더라도 해결할 대안이 있다.

이 장에서 논의 된 것

  • 프로세서의 계산능력.
  • 완벽한 계산력에 필요한 최소한의 명령집합.
  • 컴퓨터의 작업처리량
  • CISC와 RISC
  • 구조규칙 1
  • 구조규칙 2
  • 구조규칙 3
  • 구조규칙 4
  • 구조규칙 5
퀴즈 숙제를 해봅시다.