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

Contents

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

12장 쉬프트 명령과 논리 명령(Shift Instructions and Logic Instructions)

http://chortle.ccsu.edu/AssemblyTutorial/Chapter-12/ass12_1.html

레지스터 안에서 비트패턴을 좌우로 움직일 필요가 있을 때가 많다. 그런 일을 하는 명령을 자리 옮김 명령 또는 쉬프트 명령(shift instructions)이라고 한다.

이 장에서는 다음과 같은 주제를 다룬다.

  • 논리적 자리옮김 명령-Logical shift instructions(sll과 srl)
  • 자리 옮김 명령을 사용한 무연산 작동(no-op)
  • 비트단위 논리명령 (or, and, xor, nor)
  • NOR 명령을 사용한 NOT 작동
  • OR 명령을 사용한 MOVE 작동
  • 예제프로그램: 명령 어셈블리(instruction assembly)
질문: (복습) 정수 N으로 표현되는(0110 0001 이라하자) 비트패턴을 왼쪽으로 1비트만큼 이동시키면(1100 0010으로) 새로운 비트패턴은 정수 몇을 나타냅니까?

논리적 왼쪽 자리옮김(Shift Left Logical)

http://chortle.ccsu.edu/AssemblyTutorial/Chapter-12/ass12_2.html

답 : 2N, 원래정수의 2배 입니다.

0110 0001 = 97 <10> 1100 0010 = 194 <10> (그러나 1100 0010 패턴에서 만약 다시 한번 왼쪽으로 비트 쉬프트 된다면 결과는 2N이 아닙니다)

1자리의 논리적 왼쪽 쉬프트는 모든 비트를 왼쪽으로 하나씩 옮긴다. 가장 오른쪽에 하위의(low-order) 비트가 0으로 대체되고 가장 왼쪽에 상위의 비트는 버려진다.

2자리만큼 쉬프트하는 것은 1자리 쉬프트를 2번하는 것과 같다. 0만큼 쉬프트하는 것은 비트패턴에 아무 변화도 주지 않는다. N비트길이의 패턴을 N 또는 그 이상의 자리만큼 쉬프트하는 것은 모든 비트를 0으로 만든다.

오른쪽 그림은 8비트에서의 쉬프트 동작을 보여준다. 원래의 패턴은 1010 0111이고 결과는 0100 1110이다.

MIPS프로세서는 항상 쉬프트 동작을 32비트 레지스터에서 수행하고 결과를 32비트 레지스터에 집어넣는다.

sll d,s,shft # 레지스터 s에 있는 비트를 shft 만큼 왼쪽으로 자리이동해서 레지스터 d에 저장한다
# shft만큼 논리적 왼쪽 자리옮김 된다
# shft의 범위는 0 <= shft < 32 이다
이 동작을 수행하는 ALU는 쉬프트하는 비트가 무엇을 의미하는지 고려하지 않는다. 만약 비트들이 부호없는 정수(unsigned integer)를 나타내고 있다면 왼쪽 쉬프트는 곱하기 2를 하는것과 같다.

질문 : 다음은 8비트 패턴 입니다. 이것을 (논리적으로) 왼쪽으로 2자리만큼 쉬프트 해보자. 새로운 8비트패턴을 16진수로 표현해보자.

원래패턴 왼쪽으로 2번 쉬프트 한 후
0110 1111
0x6F

쉬프트하는 프로그램(Shifty Program)

http://chortle.ccsu.edu/AssemblyTutorial/Chapter-12/ass12_3.html

답 :
원래패턴 왼쪽으로 2번 쉬프트 한 후
0110 1111 1011 1100
0x6F 0xBC
만약 원래의 8비트 패턴이 정수를 나타내는 것이었다면 왼쪽으로 2번 쉬프트하는것은 아마 실수일 것입니다. 왜냐하면 쉬프트로 인해 유효숫자를 잃어버리기 때문입니다.

이 프로그램은 질문에서 해본 쉬프트 동작을 수행한다. 32비트 패턴을 가지고 수행하지만 가장 오른쪽의 8개 비트의 결과는 같다.

## shiftTwo.asm
## 
## 비트 패턴을 왼쪽으로 쉬프트하는 프로그램 
        .text
        .globl  main

main:
        ori      $8, $0, 0x6F       # 비트 패턴 0x6F를 $8에 집어넣는다
        sll      $9, $8, 2           # 왼쪽으로 2자리 쉬프트해서 $9에 집어넣는다 

## End of file

프로그램을 실행하면 아래그림과 같은일이 일어난다. 32비트 패턴으로 쉬프트를 했기때문에 상위의 유효숫자는 손실되지는 않았다. attachment:shiftTwo.gif

질문:

레지스터\$8에 있는 내용을 쉬프트하고 그 결과를 레지스터\$8에 넣는것이 괜찮을까요?
        ori      $8, $0, 0x6F       # 0x6F 비트 패턴을 $8에 저장한다.
        sll      $8, $8, 2           # 왼쪽으로 2자리 쉬프트해서 $8에 집어넣는다 

제자리에서 쉬프트하기(Shifting in place)

http://chortle.ccsu.edu/AssemblyTutorial/Chapter-12/ass12_4.html

답: 괜찮습니다.

ALU동작이 수행되었을때 다음과 같은 일이 일어난다.

  1. 데이터가 레지스터에서 ALU로 복사된다.
  2. ALU가 동작을 수행한다.
  3. 결과가 지정된 결과 레지스터에 쓰인다.
피연산자의 데이터가 먼저 ALU에 읽히기 때문에 피연산자 레지스터와 결과 레지스터가 같더라도 괜찮다. sll프로그램을 위한 기계명령을 적었다.
0 0 0 8 4 0 8 0 --16진수로된 기계명령
0000 0000 0000 1000 0100 0000 1000 0000 --비트로 된 기계명령
|| 000000 || 00000 || 01000 || 01000 || 00010 || 000000 ||||||-- 기계명령의 기능으로 묶여진 필드 ||
op코드 피연산자 저장대상 쉬프트 2차op코드 --필드의 의미
ALUop \$8 \$8 2 sll --어셈블러
sll동작은 시작과 끝의 6비트가 0으로 채워지는것으로 정의된다. 나머지 필드들은 피연산자 레지스터(이경우 \$8), 저장대상 레지스터(또한 \$8), 그리고 쉬프트 할 자릿수(2) 를 지정한다.

op코드 뒤 다섯개의 0은 쓰이지않는다. 모든 MIPS명령은 32비트 길이이기 때문에 0으로 채워졌다.

질문 : 위의 명령을 다시한번 읽어보십시오. \$0에 있는 패턴을 0자리만큼 왼쪽 쉬프트 한후 결과를 \$0에 저장하는 기계명령을 작성해 보십시오. sll \$0, \$0, 0 # 기계명령은 재밌다~!

중간고사를 위한 힌트 : 여러분은 중간고사때 머뭇거림없이 바로 32비트 기계명령을 술술 써내려 가야합니다. 당장 외워요!

무연산(No-op)

http://chortle.ccsu.edu/AssemblyTutorial/Chapter-12/ass12_5.html

답 :
0 0 0 0 0 0 0 0 --16진수로된 기계명령
0000 0000 0000 0000 0000 0000 0000 0000 --비트로 된 기계명령
000000 00000 00000 00000 00000 000000 -- 기계명령의 기능으로 묶여진 필드
op코드 피연산자 저장대상 쉬프트 2차op코드 --필드의 의미
ALUop \$0 \$0 0 sll --어셈블러
0을 기억하는건 별로 안어렵지요?

레지스터 \$0은 항상 32비트 0을 가지고 있다(어디서 들어본 기억이 있을 것이다). 그래서 왼쪽으로 0자리 만큼 쉬프트 하고 결과를 \$0에 저장하는것은 아무일도 하지 않는다. \$0을 변경하고자 하는 어떤 명령도 실제로 아무 일도 하지 않지만, 이 명령은 아무것도 안하기 위해 자주 사용되는 방법이다.

어떤 동작도 하지 않는 기계명령은 (공식적 컴퓨터 사이언스 용어로) 무연산 또는 no-op이라고 불린다. 무연산 명령(the no operation instruction)은 특히 MIPS에서 아주 쓸모있다.

질문: 아무것도 하지 않는 사람을 뭐라고 부릅니까?

논리적 오른쪽 자리옮김(Shift Right Logical)

http://chortle.ccsu.edu/AssemblyTutorial/Chapter-12/ass12_6.html

답: 게으름뱅이. (shiftless)

MIPS는 논리적 오른쪽 쉬프트명령도 가지고있다. 이 명령은 32보다 작은 자릿수만큼 오른쪽으로 모든 비트를 이동시킨다. 상위의 비트(high-order bit)는 0을 가지게 되고 하위의 비트(low-order bit)는 버려진다.

만약 비트패턴이 부호없는 정수 또는 2의 보수 표현의 양수라면, 한자리로 오른쪽 쉬프트 하는것은 정수를 2로 나눈것과 같다. N자리만큼의 오른쪽 쉬프트는 정수를 2^N으로 나누는 것과 같은 일을 한다.

오른쪽으로 쉬프트하는 방법을 나중에 다루는 MIPS 산술 나누기명령(arithmetic divide instruction) 대신에 써서는 안된다. 만약 '나누기'를 하고 싶다면 'divide(나누기)'명령을 써야하는것이 정석이다. 그러나 이러한 오른쪽 자리이동은 주로 하드웨어 그리고 가끔씩 몇몇 소프트웨어에서 쓰이기 때문에 알아두어야 한다.

srl d,s,shft # $s를 shft만큼 논리적 오른쪽 쉬프트하여 $d에 그 결과를 저장한다
#shft 는 5비트 정수이므로, 0 <= shft < 32 범위안에 있어야 한다

질문(좀 어려움): 만약 비트패턴을 논리적 왼쪽 쉬프트 2번후 다시 논리적 오른쪽 쉬프트를 한다면 결과가 어떻게 됩니까?

OR명령

http://chortle.ccsu.edu/AssemblyTutorial/Chapter-12/ass12_7.html

답: 왼쪽 2개 비트는 항상 0이고, 나머지는 그대로이다. 급하게 생각해서 아무변화가 없다라고 답하였을 수 있다. 하지만 왼쪽 자리 옮김시 상위의 비트가 1이었다면 그 비트는 버려진다.

MIPS에는 2개의 레지스터를 피연산자로 하고 결과를 레지스터로 저장하는 명령들을 많이 있다. 모든 동작은 프로세서 내에서 이루어진다. 데이터는 레지스터로부터 전달되어, ALU에서 그 동작을 한다. 그리고 결과는 레지스터에 쓰여진다. 이 모든것이 굉장히 빨리 이루어질 수 있다.

어셈블리 언어는 항상 4가지를 (컴퓨터에게) 알려주어야한다.
  1. 동작
  2. 첫 피연산자 레지스터
  3. 두번째 피연산자 레지스터
  4. 결과저장 레지스터
당연히 기계어도 위의 4가지를 비트패턴에 담아야한다.

비트의 OR연산
피연산자1 0 0 1 1
피연산자2 0 1 0 1
결과 0 1 1 1
아래가 OR명령이다.
or d,s,t # $s와 $t의 OR결과를 $d에 저장
or명령의 결과는 모든 피연산자가 0일때 0이 된다는 사실을 기억하자.

질문: 다음 OR연산의 결과가 무엇입니까?
FEED
OR BECA

AND명령

http://chortle.ccsu.edu/AssemblyTutorial/Chapter-12/ass12_8.html

답:
16진수 2진수
FEED 1111 1110 1110 1101
OR BECA 1011 1110 1100 1010
FEEF 1111 1110 1110 1111
비트단위 연산이 16진수로 쓰였을 때 가장 쉬운 계산법은 비트패턴으로 바꿔서 푼 후에 다시 16진수로 바꾸는 것 입니다.

비트의 AND연산
피연산자1 0 0 1 1
피연산자2 0 1 0 1
결과 0 0 0 1
MIPS는 AND 명령도 가지고 있다.
and d,s,t # $s 와 $t의 AND 결과를 $d에 저장
AND명령의 결과는 모든 피연산자가 1일때 1이라는 것을 기억하자.

질문: 다음 AND연산의 결과가 무엇입니까?
FEED
AND BECA

XOR명령

http://chortle.ccsu.edu/AssemblyTutorial/Chapter-12/ass12_9.html

답:
16진수 2진수
FEED 1111 1110 1110 1101
AND BECA 1011 1110 1100 1010
BEC8 1011 1110 1100 1000
비트의 XOR연산
피연산자1 0 0 1 1
피연산자2 0 1 0 1
결과 0 1 1 0
MIPS가 XOR명령도 가지고 있는것은 당연하다.
xor d,s,t # $s 와 $t의 XOR 결과를 $d에 저장
XOR명령의 결과는 오직 하나의 피연산자가 1일때 결과가 1이라는 것을 기억하자.

질문: 다음 XOR연산의 결과가 무엇입니까?
FEED
XOR BDEA

NOR명령

http://chortle.ccsu.edu/AssemblyTutorial/Chapter-12/ass12_10.html

답:
16진수 2진수
FEED 1111 1110 1110 1101
XOR BDEA 1011 1101 1110 1010
4307 0100 0011 0000 0111
비트의 NOR연산
피연산자1 0 0 1 1
피연산자2 0 1 0 1
결과 1 0 0 0
NOR명령이라는것이 있다. NOR명령은 직접명령(immediate operand NOR instruction) 은 없다. NOR명령의 결과는 OR 명령을 실행한 결과의 보수(0과 1을 바꾸는것)이다. 아래에 XOR의 어셈블리 언어를 적어놓았다.
nor d,s,t # $s 와 $t의 NOR 결과를 $d에 저장한다

질문: 다음 NOR연산의 결과가 무엇입니까?
FEED
NOR BDEA

정리

http://chortle.ccsu.edu/AssemblyTutorial/Chapter-12/ass12_11.html

답:
16진수 2진수
FEED 1111 1110 1110 1101
NOR BDEA 1011 1101 1110 1010
0010 0000 0000 0001 0000
아래의 표에 레지스터 비트단위 논리 연산을 정리해놨다. 레지스터 d는 저장대상, s와 t는 양 피연산자이다.

AND OR XOR NOR
and d,s,t or d,s,t xor d,s,t nor d,s,t
동작에 대한 정리도 있다.

피연산자1 0 0 1 1
피연산자2 0 1 0 1
AND 0 0 0 1
OR 0 1 1 1
XOR 0 1 1 0
NOR 1 0 0 0
질문: 먼저 빈 칸을 채우세요.

0 NOR 0 = _ NOT 0 = _ 1 NOR 0 = _ NOT 1 = _

자 이제 질문에 대답하세요. NOT X = X _ _ _ 0

0번 레지스터와의 NOR는 NOT

http://chortle.ccsu.edu/AssemblyTutorial/Chapter-12/ass12_12.html

답 : 0 NOR 0 = 1 NOT 0 = 1 1 NOR 0 = 0 NOT 1 = 0

NOT X = X NOR 0

비트의 NOT연산
피연산자 0 1
결과 1 0
NOT동작은 피연산중 하나를 $0레지스트러를 사용하여 NOR연산을 함으로써 이루어진다.
nor d, s, $0 # $s의 NOT을 $d에 저장한다.
질문: 레지스터 $8이 비트패턴을 가지고 있다고 합시다. OR은 $0과 $8사이에 이루어집니다. 그리고 $9에 결과가 담깁니다. 그 효과가 무엇입니까?

or $9,$8,$0

0번 레지스터와의 OR는 MOVE

http://chortle.ccsu.edu/AssemblyTutorial/Chapter-12/ass12_13.html

답: $8에 있는 비트패턴이 $9로 옮겨지고 $8에는 변화가 없습니다.

or $9,$8,$0 # $8의 내용을 $0과 OR작동 후 $9에 저장

패턴을 한 레지스터에서 다른 레지스터로 복사하는 일을 이동 또는 move라고 한다. ('이동되는' 레지스터는 변하지 않는다)

or d,s,$0 # $s의 내용을 $d로 이동

질문: (복습) 특정한 비트패턴을 레지스터로 복사하는 일반적인 방법은 무엇입니까?

예제프로그램

http://chortle.ccsu.edu/AssemblyTutorial/Chapter-12/ass12_14.html

답: ori명령으로 할 수 있습니다.

ori명령의 필드들을 적어놓았다. 첫번째 줄은 비트들의 자리를 의미하고 자리번호는 오른쪽의 하위비트부터 0으로 시작하여 31까지 번호가 매겨져있다. ori명령을 위한 op코드는 0xD이다. op코드의 길이는 6비트이기 때문에 001101이다. 원본 레지스터는 s이고 저장대상은 d, 그리고 직접피연산자는 const이다.

31....26 25...21 20...16 15...................0
0xD s d unsigned const
예제 프로그램에서는 다음 명령에 해당하는 기계어를 어셈블한다.

ori  $8,$9,0x004A

이 명령을 레지스터 25에 어셈블 시킨다. 프로그램은 비트단위 논리와 쉬프트 동작을 사용 할 것이다. 예들들어 이 예제가 더 큰 프로그램의 일부라고 가정하자. 시작하기위해 레지스터 25를 0으로 먼저 초기화 시켜보자 0으로 초기화 시키는것을 레지스터를 지운다(clear)라고도 표현한다.

질문: 레지스터 25번을 초기화시키는 명령이 무엇입니까?

목표 명령(Target Instruction)

http://chortle.ccsu.edu/AssemblyTutorial/Chapter-12/ass12_15.html

답: or $25,$0,$0 # $25 <-- $0 (다른 방법도 있습니다)

프로그램은 다음과 같이 시작한다

or $25,$0,$0 # $25 초기화

이제 옳은 비트패턴들을 명령의 필드에 집어넣자. 우리가 어셈블할 명령은 다음과 같다.

ori $8,$9,0x004A

질문: 4번째 줄에 들어갈 비트패턴을 채워보십시오. 16진수로 하세요(비트패턴들은 올바른 크기를 맞추기위해 왼쪽이 잘려진다고 가정합니다)

ori $8,$9,0x004A
31....26 25...21 20...16 15...................0
0xD s d unsigned const

각각의 필드 값

http://chortle.ccsu.edu/AssemblyTutorial/Chapter-12/ass12_16.html

답 :
ori $8,$9,0x004A
31....26 25...21 20...16 15...................0
0xD s d unsigned const
0xD 0x9 0x8 0x004A
이 명령에는 4개의 필드가 있다. 각각의 필드에 무슨 비트패턴이 들어가야 할지 알고있다. 그 비트패턴을 레지스터 $11 ,$12, $13 그리고 $14에 집어넣자. 프로그램은 다음과 같다.

or    $25,$0,$0        # $25를 지운다
ori   $11,$0,________  # op코드
ori   $12,$0,________  # 연산대상 $s
ori   $13,$0,________  # 피연산자 $d
ori   $14,$0,________  # 직접 피연산자

질문 : 빈칸을 채우세요.

op코드 쉬프팅하기

http://chortle.ccsu.edu/AssemblyTutorial/Chapter-12/ass12_17.html

답: 아래를 보세요

ori명령은 직접 피연산자를 저장대상 레지스터의 하위(오른쪽)비트에 집어 넣는다. 이제 레지스터는 올바른 패턴을 가지고 있지만 패턴이 필드가 올바르게 맞추어진 것은 아니다.

or    $25,$0,$0        # $25를 지운다
ori   $11,$0,0xD       # op코드
ori   $12,$0,0x9       # 피연산자 $s
ori   $13,$0,0x8       # 저장대상 $d
ori   $14,$0,0x004A    # 직접 피연산자

레지스터 11은 op코드를 아래와 같이 하위 비트에 가지고 있습니다.

31....26 25...21 20...16 15...................0
000000 00000 00000 0000 0000 0000 1101
그러나 op코드는 상위 6비트(26-31)에 위치해 있어야만 한다. sll명령을 사용하여 $11의 내용을 올바른 자리로 옴겨서 필드를 맞추어 보자.

질문: 왼쪽으로 얼마나 쉬프트 해야 하는지 채워 보십시오(힌트: 먼저 어떤 비트가 맨 왼쪽에 와야하는지 결정하십시오. 현재 자리과 올바른 자리와의 수를 세어보십시오)
sll   $11,$11,_____    # $11 을 ______ 자리만큼 왼쪽으로 쉬프트}}}

=== 여태껏 만든 프로그램 ===

http://chortle.ccsu.edu/AssemblyTutorial/Chapter-12/ass12_18.html

답:

sll   $11,$11,26    # $11 을 26 자리만큼 쉬프트}}}

5번째 비트 포지션이 6비트 op코드의 가장 오른쪽 비트를 담고 있다. 이 5번째 비트 포지션에 있는 op코드를 31번째 자리로 옮겨야 합니다. 이동(shift)의 크기는 31-6 = 26 이다.

여기에 현재까지의 프로그램을 적어 보았다. 소스 코드는 윈도우 오른쪽에 있다.

attachment:shiftFirst.gif

끝내주는군! 이제 비트 패턴이 올바른 6비트의 필드에 들어갔다. 한 문제만 남았다. 들어있는 레지스터가 틀렸다. 명령은 레지스터 $25에 있어야 한다.

질문: 
op코드를 레지스터 $25에 넣을 어셈블리 명령을 생각해보세요. 다음과 같이 시작합니다.

or   $25,$___,$___    # op코드를 레지스터로 옮긴다

원본 레지스터

http://chortle.ccsu.edu/AssemblyTutorial/Chapter-12/ass12_19.html

답: