번역 : 강웅빈 감수 : 프갤ㅤㅎㅛㅇ들

1 11장 직접 피연산자와 비트단위 논리


http://chortle.ccsu.edu/AssemblyTutorial/Chapter-11/ass11_1.html

어떤 기계명령들은 명령의 일부로서 데이터를 담고 있다. 이 데이터를 직접 연산대상(immediate operands)또는 직접 피연산자(immediate operands)라고 부른다. 전 장에서 쓰인 ori명령은 직접 피연산자(immediate operands)을 포함하고 있다.

비트단위 논리 동작으로 두 비트 패턴은 "정렬(lined-up)" 되고, OR이나 AND같은 연산이 정렬된 두 비트 패턴을 사용해 이루어진다.

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

  • 직접 피연산자 (immediate operands)
  • 비트단위 논리 (Bitwise Logic)
  • 비트단위 OR, AND 그리고 XOR 동작
  • 기계명령의 형식
  • 비트패턴을 영으로 확장(Zero Extension)하기
  • 불러오기 동작(load instruction)으로서 $0를사용하여 직접 OR(OR Immediate)하기.

  • 질문 : 32비트 MIPS명령에 16비트 2의 보수 정수를 사용할 수 있을 정도의 공간이 있습니까?

    1.1 직접 피연산자(Immediate Operand)


    http://chortle.ccsu.edu/AssemblyTutorial/Chapter-11/ass11_2.html

    답 : 그렇습니다. 그러나 명령 이외의 남은 비트가 2의 보수 정수를 사용해서 동작을 지정할 정도로 충분해야 합니다.



    비트의 OR연산
    첫번째 피연산자 0011 | 두번째 피연산자 0101 | __ __ __ __ | 결과 0 1 1 주소(address) 기계명령(machine code) 어셈블리(assembly code)
    0x00400000 0x34080002 ori, $8,$0,0x2

    기계명령에서 마지막의 16비트(4개의 16진수)는 피연산자 0x0002를 담고있다. (어셈블리 명령을 그냥 0x2라고 표현할 수 도 있다). 기계명령은 ALU에게 레지스터$0에 담겨진 비트와 직접 피연산자(immediate operand) 0x0002를 가지고 비트단위의 OR연산(bitwise OR)을 하라고 명령한다. 명령의 결과는 $8에 들어간다.

    비트단위 연산에서 논리적 연산은 피연산자의 각 행에서 수행된다. 두개의 8비트 패턴사이에 비트단위 OR연산을 예로 들어보자.

    0110 1100 피연산자(operand)
    0101 0110 피연산자(operand)
    0111 1110 결과

    질문 : 레지스터$0에 어떤 비트 패턴이 들어있습니까? MIPS명령은 몇 비트로 이루어져 있습니까?

    참조: 직접피연산자

    1.2 '0'을 사용하여 확장하기 (Zero Extension)

    http://chortle.ccsu.edu/AssemblyTutorial/Chapter-11/ass11_3.html

    답 : $0 에는 모두 0으로 이루어진 비트패턴이 담겨져 있다. MIPS 명령은 32비트 크기이다.

    명령을 다시 보자

    주소(address) 기계명령(machine code) 어셈블리(assembly code)
    0x00400000 0x34080002 ori, $8,$0,0x2

    16비트의 직접피연산자(Immediate Operand)는 0000 0000 0000 0010이고, 이 직접피연산자(Immediate Operand)가 32비트 크기인 레지스터$0과 비트단위OR연산(bitwise OR)을 한다.

    (레지스터 $0 : 0000 0000 0000 0000 0000 0000 0000 0000)

    보통 이런 동작은 피연산자(operand)가 다른 길이이기 때문에 불가능하다. 그러나 MIPS에선 16비트인 피연산자를 0으로 확장할 수 있다. 어떤 사람들은 이 동작을 '왼쪽에 0을 붙이기' 라고도 부른다.

    영확장
    0000 0000 0000 0000 0000 0000 0000 0010 영을 붙여 확장한 직접피연산자
    0000 0000 0000 0000 0000 0000 0000 0000 레지스터 $0에 있는 데이터
    0000 0000 0000 0000 0000 0000 0000 0010 레지스터 $8에 저장되는 결과

    그리고 OR연산은 각 행마다 행해진다. 32비트 크기의 결과가 $8에 저장된다.

    질문: 명령 ori $8,$0,0x2 를 실행한 후 레지스터$8에는 무엇이 있습니까?

    1.3 직접OR명령(OR Immediate Instruction) 또는 상수형 OR 명령


    http://chortle.ccsu.edu/AssemblyTutorial/Chapter-11/ass11_4.html

    답 : 16비트 크기의 피연산자(operand) 0x2가 0을 붙임으로써 32 비트로 확장 되고 레지스터 $8로 복사됩니다.

    OR연산이 $0과 수행되었기 때문에 결과는 0을 붙여 확장된 직접피연산자(Immediate Operand)의 복사물이다. 비트패턴을 레지스터로 복사하는것을 보통 '레지스터에 올린다 영어로 로딩(loading)한다' 라는 말로 표현한다. 만약 레지스터$8에 32비트 패턴이 로드되어있고 $8에 있는 비트패턴이 양수2를 의미할 때, 레지스터$8에 2가 올려진 것이다. 다음은 레지스터에 데이터를 로딩할 때 사용하는 ori명령에 대한 설명이다.

    ori d,$0,const #상수(const)를 $0와 OR 연산 후 지정된 레지스터 d에 저장하라
    #상수는 16비트 크기이다
    #16비트 이기 때문에 상수의 크기는 0x0000 <= 상수 <= 0xFFFF의 범위 안에 있어야 한다

    만약 상수의 범위를 10진수 양의 정수 크기로 표현하자면 0 <= 상수 <= 65535 의 크기 범위 안에 있어야 한다. 어셈블러의 명령에서 3개의 피연산자(operand)인 d,$0 그리고 상수(const) 는 항상 d,$0,상수 순서로 나타난다.

    질문: ori명령의 직접 피연산자(Immediate Operand)는 양수와 음수 부호를 표현한 정수(signed integer)입니까?

    1.4 일반 직접OR명령 (General OR Immediate Instruction)


    http://chortle.ccsu.edu/AssemblyTutorial/Chapter-11/ass11_5.html

    답: 아니오. 16비트의 수가 32비트로 0을 사용하여 확장 되기 때문에 절대 2의 보수 표현 방식의 음수는 나올 수 없습니다.

    다음은 비트단위 OR연산을 사용하는 ori명령의 설명이다.

    ori d,s,const # 저장하는 레지스터 d, 소스 레지스터 s, 상수(const).
    #소스레지스터 s의 비트패턴과 상수를 OR 연산하여 레지스터 d에 저장하라
    #상수는 16비트이므로
    #0x0000<=상수<=0xFFFF 범위안에 있어야 한다.

    각 명령은 올바른 순서로 나타나야하고 상수는 정해진 범위에서만 사용해야한다. 만약 어셈블리언어의 직접 피연산자(Immediate Operand)가 전장의 0x2의 경우처럼 16비트보다 작다면 어셈블러는 직접 피연산자를 16비트로 확장한다. 만약 직접피연산자가 16비트보다 길면 어셈블러는 에러메세지를 표시한다.

    어셈블러의 상수(const) 부분은 양수 십진수이거나 16진수를 사용할 수 있다. 어셈블러가 상수를 16비트의 비트패턴으로 번역한다. 예를들면, 아래의 두개의 어셈블러는 같은 기계명령으로 번역된다.

    ori $5,$4,0x10 ori $5,$4,16


    질문 : 다음 명령이 맞습니까?
    ori $0,$9,0x32

    1.5 예제


    http://chortle.ccsu.edu/AssemblyTutorial/Chapter-11/ass11_6.html

    답 : 틀렸습니다. $0에 결과를 넣으면 이것은 항상 0이고 다른 결과를 로드할 수 없다.

    스핌 시뮬레이터의 어셈블러 부분은 위와같이 잘못 적힌 명령에 대해 에러메세지를 주지 않는다. 하지만 실행했을때의 레지스터$0값은 변하지 않는다.

    다음은 두 패턴을 비트단위OR하는 작은 프로그램이다. 첫 패턴은 레지스터$8로 로드되고, 레지스터에 올려진 후 직접 피연산자(Immediate Operand)와 OR 연산된다. 그 결과는 레지스터$10에 저장된다.

    
    ## 두 패턴을 OR하는 프로그램
            .text
            .globl  main
    
    main:
            ori      $8,$0,0x0FA5       # 첫 패턴을 $8에 넣는다
            ori     $10,$8,0x368F      # 두번째 패턴과 OR한후 결과를 $10에 넣는다
    
    ## 파일의 끝
    

    곧 우리는 이 프로그램을 어셈블하여 실행시켜 볼것이다. 하고싶으면 지금해도 된다(복사해서 붙여넣기를 이용하라). 먼저 결과를 예상해보자.

    질문 : 이진수와 16진수로 쓰여진 두 패턴을 준비해놓았습니다. 비트단위 OR연산을 해보십시오.(이진수로 먼저 하고 그다음에 답을 16진수로 쓰십시오)

    이진수 16진수
    0000 1111 1010 0101 0FA5
    OR 0011 0110 1000 1111 368F

    1.6 프로그램 실행시키기

    http://chortle.ccsu.edu/AssemblyTutorial/Chapter-11/ass11_7.html

    답 :

    이진수 16진수
    0000 1111 1010 0101 0FA5
    OR 0011 0110 1000 1111 368F
    0011 1111 1010 1111 3FAF


    손으로 계산 해보면 결과는 0x3faf가 나온다. 당연히 프로그램을 실행할 경우 결과는 32비트 길이이다.(0x00003faf) 프로그램을 실행시키려면 아래방법을 따른다.

    1. 소스파일을 만든다 2. 스핌을 시작한다. 3. 소스파일을 올린다(load). 4. 시뮬레이터 스위치를 설정한다(이번엔 여기 나오는것들만 사용한다)
    ON 일반 레지스터를 16진수로(general registers in hexadecimal)
    ON 순수 머신(bare machine)
    OFF 의사명령 허용(allow pseudo instructions)
    OFF 트랩파일 올리기(load trap file)
    5. PC(프로그램 카운터) 를 첫 명령이 있는 주소로 초기화 시킨다. 6. f10을 명령마다 눌러준다. Upload new Attachment "orWork.gif" 위 사진은 실행프로그램의 결과를 보여준다. 레지스터 $10에 들어있는 값은 우리가 예상했던 결과다!


    질문 : 여기에 소스윈도우로부터 첫 명령줄을 가져왔습니다. 0x00400000 0x34080fa5 ori $8, $0, 4005 ori $8,$0,0x0FA5 32비트 기계명령을 보자. 직접 피연산자를 찾을 수 있겠습니까?


    1.7 ORI 기계명령

    http://chortle.ccsu.edu/AssemblyTutorial/Chapter-11/ass11_8.html

    답 : 0x00400000 0x34080fa5 ori $8, $0, 4005 ori $8,$0,0x0FA5 네. 설마 못찾는건 아니겠죠? 끝에 16 비트가 직접 피연산자 입니다.

    다음은 명령을 기계어로 옮겨 놓았다. 세번째 줄에 비트들은 각종 기능을 가진 필드들로 묶여서 나뉘어져 있다. MIPS문서가 각명령에서 필드들이 어떤 기능을 하는지 설명해준다. (열심히 그냥 기계어를 쳐다본다고 기능을 발견할 수 있는것은 아니다.)

    어떻게 작동하는지 보기위해 한번 쭉 훑어보자. 왼쪽에 6개의 비트는 기계동작을 정하는 op코드이다. 다음 5비트는 피연산자(operand) 레지스터를 지정한다. 그 다음 5개는 저장대상 레지스터를 지정한다. 나머지 비트들은 직접피연산자(Immediate Operand)이다.

    3 4 0 8 0 f a 5 --16진수로 된 기계명령
    0011 0100 0000 1000 0000 1111 1010 0101 --비트로 된 기계명령
    001101 00000 01000 0000 1111 1010 0101 -- 기계명령의 기능으로 묶여진 필드
    ori $0 $8 0fa5
    op코드 피연산자 저장대상 직접피연산자 --각 필드의 의미
    ori $8 $0 0x0fa5 --어셈블러 (레지스터의 순서가 기계어와 다르다는 것을 주목)


    질문 : 다음은 ori명령 입니다. 그렇지만 피연산자, 저장대상 그리고 직접 피연산자가 비어있습니다. 피연산자는 $10 저장대상은 $9 그리고 직접피연산자는 0xAFF0가 되도록 채워보십시오.
    001101 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    ori $10 $9 a f f 0
    피연산자(Operand Register) 저장대상(Destination Register) 직접피연산자(Immediate Operand)


    1.8 기계어 비교


    http://chortle.ccsu.edu/AssemblyTutorial/Chapter-11/ass11_9.html

    답:
    001101 01010 01001 1010 1111 1111 0000
    ori $10 $9 a f f 0
    피연산자(Operand Register) 저장대상(Destination Register) 직접피연산자(Immediate Operand)


    아래에 다시 ori명령을 소개한다.

    3 4 0 8 0 f a 5 --16진수 기계명령
    001101 00000 01000 0000 1111 1010 0101 --필드(field)
    op코드 피연산자 저장대상 직접피연산자 --각 필드의 의미
    ori $0 $8 0fa5

    위의 ori 명령의 배열은 10장에서 다루었던 addu 명령과 다르다. addu명령을 다시 살펴보자.

    0 1 0 9 5 0 2 1 --16진수 기계명령
    000000 01000 01001 01010 00000 100001 --필드
    op코드 피연산자 피연산자 저장대상 - - - - 2차 op코드(secondary) --필드의 의미
    ALUop $8 $9 $10 addu

    두 명령 모두 32비트길이이다.(MIPS R2000/R3000의 모든 명령이32비트 길이이다). 첫 6비트는 ALU동작을 부르는 op코드이다. 마지막 6개의 비트는 2차 op코드로서 addu명령을 나타낸다. addu명령은 직접피연산자를 가지지 않는다.

    질문 : 두 다른 기계명령의 필드들의 길이와 의미가 꼭 같아야만 할까요?

    1.9 비트단위논리 사용


    답 : 아니오.

    http://chortle.ccsu.edu/AssemblyTutorial/Chapter-11/ass11_10.html

    첫 6비트는 기계동작을 지정하는 기계명령(op코드)이다. (세컨더리 op코드가 필요할때도 있다) op코드는 나머지 기계명령이 어떤 식으로 배열되는가를 결정한다. 기계어가 무엇인지 알기위해서 MIPS설명서를 봐야한다. MIPS 프로세서는 설명서없이 그 일을 자동적으로 수행한다.

    (2장에서) 2진수의 장점 4번째를 상기해보자

    1. 간단하고, 만들기 쉽다.
    2. 확실한 신호(노이즈에대한 저항력)
    3. 완벽한 복사를 할 수 있다.
    4. 무엇이든지 어떠한 패턴으로 표현될 수 있는것은 비트패턴으로도 표현 가능하다.

    대부분의 컴퓨터들은 정수연산과 부동소숫점연산을 기본적으로 지원한다. 그러나 컴퓨터들은 수치연산에만 사용되는것이 아니다! 비트패턴은 아주 많은것을 표현할 수 있다. 비트단위 논리는 다양한 목적에서 컴퓨팅 할 때 쓰인다.

    예를 들자면 워드프로세서에서 만든 문서는 글꼴과 형식정보를 같이 가지고 있다. 정보들은 워드프로세서 종류마다 다른식으로 저장된다. 워드프로세서는 코드를 처리하기 위해 반드시 비트단위연산을 사용해야한다.

    질문 : ascii로 된 문자열을 읽고 데이터와 기계동작을 비트패턴으로 산출하는 프로그램이 무엇입니까?

    1.10 편리한 AND직접명령(AND immediate Instruction)


    http://chortle.ccsu.edu/AssemblyTutorial/Chapter-11/ass11_11.html

    답 : 어셈블러

    AND동작(AND Operation on Bits)
    1차 피연산자(operand) 0 0 1 1
    2차 피연산자(operand) 0 1 0 1
    결과(result) 0 0 0 1
    어셈블러는 기계명령의 비트패턴을 조합(assemble) 하기위해 비트단위 연산을 한다. 비트를 조작(bit manipulation)고 기계명령을 만들어보는것은 시스템프로그래밍 과목에서 흔한 과제이다. 당연히 여러분은 어셈블러를 c로 작성해보고 c의 비트연산자를 사용할 것이다. 그러나 궁극적으로 c로 쓴 비트연산자들도 프로세서의 비트단위 작동으로 번역된다.

    andi명령은 두개의 32비트 패턴에 대한 비트단위AND연산을 수행한다. 실행시에 16비트의 직접 피연산자는 왼쪽에 0을붙여 32비트 길이의 피연산자로 확장된다.


    andi d,s,const # 직접 피연산자 상수(const)를 소스레지스터 s와 비트단위 AND 작동한후 결과를 레지스터 d에 저장한다
    # 상수(const)는 16비트 패턴이므로
    # 0x0000 <= 상수(const) <= 0xFFFF 범위안에 숫자이다

    명령의 3개 피연산자는 모두 정확한 순서로 쓰여야 하며, 상수(const)는 항상 정해진 범위 안에 있어야한다. 어셈블리언어의 소스에서 직접 피연산자는 항상 16비트 길이이지만 왼쪽의 0은 생략될 수 있다. (예: 0x2)



    질문 : 다음 명령이 올바릅니까? 이것이 무슨일을 합니까?

    andi $8,$0,0xFFFF

    1.11 배타적OR 직접명령(Exclusive-OR Immediate)


    http://chortle.ccsu.edu/AssemblyTutorial/Chapter-11/ass11_12.html

    답 : 문법적으로 올바른 명령이지만 별로 의미있는 일은 아닙니다. 이것은 레지스터$0과 직접 피연산자를 AND연산 후 결과를 $8에 넣습니다. 당연히 결과는 직접피연산자에 관계 없이 0입니다.

    XOR동작(XOR Operation on Bits )
    1차 피연산자(operand) 0 0 1 1
    2차 피연산자(operand) 0 1 0 1
    결과(result) 0 1 1 0

    레지스터를 0으로 채우는것을 레지스터를 지운다(clear)고 한다. 레지스터를 지우는 것은 자주 쓰이는 동작이지만 위의 명령이 제일 좋은방법은 아니다.

    배타적 OR(이하 XOR)은 양쪽 피연산자가 1일때 0을 결과로 내놓는다는 것을 제외하면 일반OR(the inclusive OR-포함적OR)과 같다.

    어셈블리언어에 대한 설명을 적어놓았다. 이 명령에 해당하는 기계어도 ori나 andi와 비슷하다.

    xori d,s,const 소스레지스터 s의 비트를 직접 피연산자인 상수(const)와 비트단위 XOR 연산후 목적레지스터 d에 저장한다
    # 상수(const)는 16비트 패턴이므로
    # 0x0000 <= const <= 0xFFFF 안의 범위여야 한다

    명령의 연산대상 3개 모두 정확한 순서로 쓰여야 하며, 상수(const)는 항상 정해진 범위안에 있어야한다. 어셈블리언어의 소스에서 직접 연산대상은 항상 16비트 길이이지만 왼쪽의 0은 생략될 수 있다. (예: 0x2) 16비트보다 길면 어셈블러는 에러메세지를 보인다.

    질문 : 다음은 이진수와 16진수로 쓰여진 두 패턴입니다. 비트단위 XOR연산을 해보십시오.(이진수로 먼저 하고 그 다음에 답을 16진수로 쓰십시오)

    이진수 16진수
    0000 1111 1010 0101 0FA5
    OR 0011 0110 1000 1111 368F

    1.12 예제 프로그램


    답 :
    이진수 16진수
    0000 1111 1010 0101 0FA5
    OR 0011 0110 1000 1111 368F
    0011 1001 0010 1010 392A

    http://chortle.ccsu.edu/AssemblyTutorial/Chapter-11/ass11_13.html

    여기에 2개의 같은 패턴에 대해 우리가 배운 3개의 비트단위 연산을 하는 예제 프로그램이 있다. 저장대상 레지스터는 각각의 연산마다 다른 곳을 사용했다.

    ## 두개의 패턴을 AND, OR 그리고 XOR하기 위한 프로그램 
            .text
            .globl  main
    
    main:
            ori       $15, $0,0x0FA5        # 비트패턴 0x0FA5를 0번레지스터와 OR연산하여(0확장) $15에 저장.
            ori       $8,$15,0x368F         # $15를 비트패턴 0x368F와 OR 연산하여 $8에 저장.
            andi    $9,$15,0x368F         # $15를 비트패턴 0x368F와 AND 연산하여 $9에 저장.
            xori     $10,$15,0x368F       # $15를 비트패턴 0x368F와 XOR 연산하여 $10에 저장.
    ## 파일의 끝
    

    스핌에서 실행시키면(F10을 4번 누른다) 아래와 같은 결과가 나온다.

    Upload new Attachment "andWork.gif"

    질문 : 같은 패턴을 XOR시키면 무엇이 됩니까? 종이 한장에다가 몇개의 패턴으로 계산해보십시오.


    1.13 11장 요약

    http://chortle.ccsu.edu/AssemblyTutorial/Chapter-11/ass11_14.html

    답 : 모두 0인 비트 패턴. 두 피연산자가 모두 같기 때문에 오직 두가지의 XOR연산이 사용된다 : 0 XOR0 0 = 0 and 1 XOR 1 = 0.

    11장의 끝이다. 다음의 항목을 복습해 보자.

    • 직접 피연산자 (Immediate Operands)
    • 비트단위 논리 (Bitwise Logic)
    • ORI명령 (ORI instruction)
    • ORI명령의 기계어 (Machine code or the ORI instruction)
    • ANDI명령 (ANDI instruction)
    • XORI명령 (XORI instruction)

    11장 퀴즈를 꼭 풀어봅시다.


    1.14 프겔러들의 수다

    1.14.1 Immediate Operand

    1. 스미골ㅤㅎㅐㅎ 한국의 대학교에서는 immediate operand라고 쓰고, 이미디엇 아퍼ㅤㄹㅞㄴ드라고 읽어.
    2. 자바하는넘 명령어 같은 거나 전문용어는 영어로 처리해도 될것같에... 대신에 상응하는 한자글용어가 있으면 첨에 참조 같은 형식으로 링크 걸어주던지 참조 하는말 써주던지... 계속 수고.
    3. Heart 한국 대학 프리젠테이션 자료도 영어 도배...
    4. 전 번역책으로 배워서 피연산자라고 배웠는데....
    5. 변역하기 참 ㅤㅅㅞㅅ한 용어인데... 상수형 피연산자라고 하면 그런가?
    6. 자바하는넘 상수형 피연산자가 내가 보긴 그럴듯한데... 업계에서 쓰는 용어인지 아닌지 모르겠3. 잘못번역하면 더 혼동만 줄 수 있고...
    7. 졸려. immediate operand에서 immediate는 '즉시'가 아니라 '직접적'으로 해석해야한다. register에 메모리 참조나 address pointer를 간접참조해서 값을 읽어와서 연산하는 것이 아니라 direct로 숫자를 연산하는 경우이니까.
    8. 웅빈 며칠후 돌아옵니다. 한말씀ㄳ