[컴퓨터 구조] Chapter 2 명령어: 컴퓨터 언어 (2)

2021. 12. 2. 04:10·Major/Architecture
728x90

9. 문자와 문자열

1) 문자

- ASCII : 128 문자 (대부분의 컴퓨터에서 사용)

- UNICODE : 32bit 문자셋 ex) UTF-8, UTF-16

 

2) Byte(8bit)/Halfword(16bit) 명령어

- 워드 내의 특정 바이트를 추출

lb rt, offset(rs) #load byte
//메모리에서 한 바이트를 읽어 레지스터의 오른쪽 8비트에 채우는 명령어
//8비트를 가져오면 나머지 24비트는 부호확장으로 채운다
lh rt, offset(rs) #load halfword
 
sb rt, offset(rs) #store byte
// 레지스터의 오른쪽 8비트를 메모리로 보내는 명령
sh rt, offset(rs) #store halfword

lbu rt, offset(rs) #부호없는 lb
lhu rt, offset(rs) #부호없는 lh
//8비트 가져오면 나머지 24비트는 0으로 채움

ex) 문자열 복사 

void strcpy (char x[], char y[]){
	int i;
	i = 0;
	while ((x[i]=y[i])!='\0')
		i += 1;
}
// Addresses of x, y in $a0, $a1
// i in $s0
strcpy:
	addi $sp, $sp, -4 // 1개 저장하기 위해 push
	sw $s0, 0($sp)    // $s0의 값을 $sp에저장
	add $s0, $zero, $zero // i = 0
L1: add $t1, $s0, $a1     // y[i]의 시작주소 계산($t1에저장)
	lbu $t2, 0($t1)       // $t2 = y[i]
	add $t3, $s0, $a0     // x[i]의 시작주소 계산($t3에저장)
	sb $t2, 0($t3)        // x[i] = y[i]
	beq $t2, $zero, L2    // exit loop if y[i] == 0
	addi $s0, $s0, 1      // i = i + 1
	j L1 
L2: lw $s0, 0($sp) # restore saved $s0
	addi $sp, $sp, 4 # pop 1 item from stack
	jr $ra # and return

3) 32bit 수치와 주소를 위한 mips의 주소지정 방식

- 대부분 상수는 작음 (16bit면 충분함)

- 가끔씩 32비트 상수를 로드해야 되는 경우가 있음 이때 사용

lui rt, constant 
// 16비트 상수의 왼쪽 16bit를 rt에 저장
// 나머지 오른쪽 16비트는 0으로 채움

ex) $s0에 32비트 상수 “0000 0000 0011 1101 0000 1001 0000 0000”를 load해라

lui $s0, 61
ori $s0, $s0, 2304 //or연산 해주면 됨

 

4) 분기와 점프 명령에서의 주소지정

ⓐ 분기 명령어

- PC relative addressing(상대 주소지정) : 타켓 주소 = PC+offset*4

=> 분기할 거리를 바이트 단위가 아닌 워드단위로 나타내면서 더 먼 거리까지 분기가 가능해진다.(4배)

 

ⓑ jump 명령어

- j타입 명령어 형식을 사용한다.

- target adderss = pc : address*4 (pc 상위 4비트는 바꾸지않고 하위 28비트만 address로 바꿈)

- 부득이 경계를 넘어가야 되는 경우에는 레지스터에 32비트 주소를 넣은 후 jr명령 사용한다.

 

ex) 기계어에서의 분기 변위

- PC +4 + ( ) = 80024 그러면 ( ) = 8이다. 8은 Byte 단위 이므로

워드 단위로 바꿔주면 (1word=4byte) 2가 된다.

 

- 20000도 워드주소이다. byte단위로 바꿔주려면 4를 곱해주면된다 따라서 80000으로 분기된다.

 

5) 아주 먼 거리로 분기

beq $s0,$s1, L1
↓
bne $s0,$s1, L2
j L1 (더많이 분기 가능)
L2: ...

- 분기목적지로 가는 무조건 점프를 삽입하고, 분기조건을 반대로 만들어 이 점프를 건너뛸지 여부를 결정하게 한다.

 

 

6) MIPS 주소 지정 방식 요약

 

 

 

 

 

1. 수치주소지정 : 피연산자는 명령어 내에 있는 상수

2. 레지스터 주소지정 : 피연산자는 레지스터

3. 베이스 주소지정 : 피연산자가 메모리 내용

- 메모리 주소는 레지스터와 명령어 내 상수 더함

4. PC상대주소지정 : PC값과 명령어 내 상수의 합

5. 의사직접 주소지정 : 명령어 내의 26비트를 PC의 상위 비트와 연접하여 주소를 구한다.

 

 

 

 

 

 

 

EX) 00AF8020H의 MIPS code?
0000 00 00 101 0 1111 1000 0 000 00 10 0000 => add $s0, $a1, $t7

 

11. 동기화(Synchronization)

👉 두 프로세서가 메모리의 한 영역을 공유한 경우

- 접근 순서에 따라 결과가 달라지는 상황 : data race

=> 나눌수 없는 read/write memory 연산자를 제공하는 하드웨어 프리미티브 필요

* 읽고 쓰는 중에 그 영역으로 접근 허용 안함

방법 : single instruction, atomic pair of instruction

1) atomic pair of instruction

ll rt, offset(rs) //Load linked
sc rt, offset(rs) //Store conditional

- ll 명령어가 언급한 메모리 주소의 내용이 sc가 실행될때까지 안바뀌면 1을 return 아니면 0 리턴

 

ex) 레지스터($s4)와 메모리($s1)사이의 값 교환

try: add $t0, $zero, $s4 //$s4에 있는 내용을 $t0에 저장
	 ll $t1, 0($s1) //$s1을 메모리에서 $t1으로 가져옴 
	 sc $t0, 0($s1) //$t0에있는걸 s1에 저장하고 $s1의 내용이 바뀌었는지 안바꼈는지 $t0에 저장
	 beq $t0, $zero, try //$s1의 내용이 바뀌었으면 다시시도 
	 add $s4, $zero, $t1 ;put load value in $s4 //안바꼈다면 $t1내용을 $s4에 저장

 

12. 프로그램 번역과 실행

1) 과정

① 컴파일러 : c프로그램을 어셈블리 언어 프로그램으로 바꾼다.

② 어셈블러 : 어셈블리 언어를 기계어로 바꿈

③ 링커 : 기계어와 라이브러리를 링크함, 실행파일 만듬

④ 로더 : 실행파일을 읽어서 메모리에 넣고 이를 시작함

 

2) 어셈블러 의사명령어

- 대부분의 어셈블러 명령어는 기계어 명령어와 일대일로 표현된다.

- 의사명령어(pseudoinstructions) : 어셈블러가 상상하는 허구

move $t0, $t1 → add $t0, $zero, $t1
blt $t0, $t1, L → slt $at, $t0, $t1
                  bne $at, $zero, L

 

3) 어셈블러

> Unix 시스템의 목적파일의 구성요소
- Header: object module의 contents, 각 부분의 크기와 위치서술
- Text segment: 번역된 명령어들
- Static data segment: 프로그램 수명 동안 할당된 데이터
- Relocation info: loaded program의 절대주소에 의존하는 콘텐츠에 대한 재배치 정보
- Symbol table: global definitions & external refs
- Debug info: 각 모듈의 번역에 대한 간단한 설명, 기계어와source code를 연관 짓고 자료구조를 판독

 

4) 링커 

- 동작과정

ⓐ 코드와 데이터 모듈을 메모리에 심벌 형태로 올려놓는다

ⓑ 데이터와 명령어 레이블의 주소를 결정한다

ⓒ 외부 및 내부 참조를 해결한다

 

5) 로더 

- 디스크에 있는 이미지 파일을 메모리에 로드

① Header를 읽어 텍스트와 데이터 세그먼트의 크기를 결정
② Create virtual address space(텍스트와 데이터 수용할 수 있는 주소공간)
③ Copy text and initialized data into memory
④ Set up arguments on stack
⑤ Initialize registers (including $sp, $fp, $gp)
⑥ Jump to start-up routine
 - Argument들을 $a0 등에 넣고, main을 호출한다.
 - Main에서 startup routine으로 return하면, exit system call을 사용해 프로그램을 종료함.

 

6) 동적 링크 라이브러리

- 정적 링크 라이브러리에 단점 => 동적 링크 라이브러리 

- 프로그램 실행 전에는 라이브러리라 링크되지 않고 적재 되지 않음. 

- 파일에 저장된 추가정보를 이용해서 적절한 라이브러리를 찾고 모든 외부 참조를 갱신함

* 지연 링킹

 

21. 오류

1) 강력한 명령어를 사용하면 성능이 좋아진다. (x)

> 적은 개수의 명령어들이 필요

> 그러나 복잡한 명령어들은 구현하기 어려움(모든 명령어들을 slow down 시킬 수 있다)

* intel x86 명령어가 강력한 이유 중 하나는 명령어 실행 방식을 변경하는 접두사를 가지고 있음

2) 최고 성능을 얻기위해 어셈블리 언어로 프로그램 작성하기 (x)

3) 상업용 프로그램의 이진 호환성이 중요하다는 것은 성공적인 명령어 집합은 변하지 않는 것을 의미한다

4) 인접 워드간의 주소차이는 1이 아니라는 것을 잊는것 (4씩 증가한다)

5) 자동 변수가 정의된 프로시저 외부에서 자동변수에 대한 포인터를 사용하는 것

 

22. 결론

1) 설계원칙 4가지

- 간단하게 하기 위해서는 규칙적인 것이 좋다

- 작은 것이 빠르다(32개의 레지스터)

- 자주 사용하는 것을 빠르게 하기

- 좋은 설계에는 좋은 절충이 필요하다.

* MIPS : RISC ISAs 의 전형적인 예 c.f. x86

728x90
저작자표시 비영리 (새창열림)

'Major > Architecture' 카테고리의 다른 글

[컴퓨터 구조] Chapter 2 명령어: 컴퓨터 언어 (1)  (0) 2021.10.17
[컴퓨터 구조] Chapter 1_컴퓨터 추상화 및 관련 기술 *  (0) 2021.09.28
'Major/Architecture' 카테고리의 다른 글
  • [컴퓨터 구조] Chapter 2 명령어: 컴퓨터 언어 (1)
  • [컴퓨터 구조] Chapter 1_컴퓨터 추상화 및 관련 기술 *
BeNI
BeNI
코딩하는 블로그
  • BeNI
    코딩못하는컴공
    BeNI
  • 전체
    오늘
    어제
    • Menu (253)
      • My profile (1)
      • 회고 | 후기 (8)
      • Frontend (65)
        • Article (11)
        • Study (35)
        • 프로그래머스 FE 데브코스 (19)
      • Backend (0)
      • Algorithm (58)
        • Solution (46)
        • Study (12)
      • Major (111)
        • C&C++ (23)
        • Java (20)
        • Data Structure (14)
        • Computer Network (12)
        • Database (15)
        • Linux (6)
        • Architecture (3)
        • Lisp (15)
        • OS (1)
        • Security (2)
      • etc (2)
  • 링크

    • 깃허브
    • 방명록
  • 인기 글

  • 최근 댓글

  • 최근 글

  • 태그

    파일처리
    C++
    리팩토링
    자료구조
    react
    lisp
    프로그래머스
    Algorithm
    백준
    데브코스
  • hELLO· Designed By정상우.v4.10.2
BeNI
[컴퓨터 구조] Chapter 2 명령어: 컴퓨터 언어 (2)
상단으로

티스토리툴바