1학기때 들었던 컴퓨터 구조 과목의 중간고사 대비 백지 핵심요약 입니다.
2강
컴퓨터 종류 4가지를 쓰시오.
personal, server, supercomputer, embed
컴퓨터 성능향상 아이디어 7가지를 쓰시오.
- 추상화 디자인을 통해 굳이 아래 계층 알 필요 없이 작동하게 함
- 자주 사용하는 걸 빠르게
- 병렬성 처리하기(parallelisim via parallelism)
- 나누어 처리하기(performance piplelining)
- 추측을 통한 예측 (prediction via Speculation)
- 메모리의 계층(Hierarchy of Memories)
- 중복성을 통한 신뢰성 향상 (Dependability via Redundancy)
컴퓨터 계층 구조에 대해 쓰시오.
하드웨어(bits) -> 시스템 소프트웨어(os, 컴파일러) -> application
컴퓨터 performance 성능 지표 2가지는?.
response time, throughput
CPU Time, CPU clock, IC, CPI 가 뭔지 서술하시오.
CPU TIME: 총 반응시간, 걸리는 시간
CPU clock: CPU의 단위 박자
IC: 명령어 개수
CPI: 사이클 당 처리해야 하는 명령어 수
CPU TIME, clock cycles, cycle Time, CPI, performace 유도공식을 쓰시오.
CPU TIME = clock cycles * cycle Time
clock cycles = instruction count * CPI
cycle Time = 1/ Clock rate
CPI = clock cycles / IC
performace = clock rate / CPI
필요한 전략량(power) 공식과 이 공식을 바탕으로 컴퓨터 발전과정을 쓰시오
power(필요한 전력량) = Capactive load * 전압^2* Frequency
freqeuncy는 늘리되 power가 너무 증가하는 걸 막기 위해 전압을 낮추는 방식으로 발전했다.
하지만 이제 전압을 낮추는 것도 한계가 있어 멀티코어 쓰는 방식으로 방향을 바꾸었다.
MIPS란 무엇인가? 공식도 함께 쓰시오.
1초에 얼마나 많은 instruction 들어가는지 백만 단위로 측정한 것. 근데 컴퓨터마다 ISA와 CPI를 고려하지 않아 좋은 지표는 아니다.
MIPS *10^6
= instruction count/ execuation time
= clock rate / CPI
안달의 법칙이란?
시간이 오래걸리는 거 고친다고 전체 성능 향상에는 큰 도움이 안될 수 있다. 자주 쓰는 것 개선하는게 유리하다.
3강
RISC-V 라는 ISA가 가지는 장점은 무엇인가?
임베디드에서 주로 쓰이며 현대적인 구조를 가지고 OPEN ISA이다.
a = b+c ; f = t0 -t1;
를 각각 어셈블리어로 표시하시오
add a, b, c
sub f, t0, t1
레지스터와 메모리에 대해 서술하시오.
레지스터는 CPU에 가장 가까운 프로세서 내부의 메모리라고 보면 된다.
레지스터가 적을 수록 연산수가 빠르다.
레지스터는 x0,x1 이런식으로 x숫자 형식의 이름을 가진다.
복잡한 데이터는 레지스터 말고 메모리에 적재해서 쓴다.
메모리보다 레지스터 처리속도가 훨씬 빠르다. 결국 계산은 레지스터에서 해야만 한다. 메모리에 있는 값으로 계산을 하기 위해서는 load, store 과정을 거쳐야 한다. 근데 그걸 안거치니깐. 그래서 컴파일러는 가능한 자주쓰는 걸 레지스터에 올려서 속도를 최적화 할 수 있다.
메모리와 레지스터 사이 명령어를 쓰시오.
Load(ld): 메모리 -> 레지스터
Store(sd): 레지스터 -> 메모리
즉 ld로 시작하면 sd로 끝이 난다.
ld x5 4(x6) // x6 레지스터가 가르키는 주소에다가 4를 더한 주소를 x5에 로드하시오/
sd x5 4(x6) // x5에 있는 레지스터 데이터를 x6 레지스터가 가르키는 주소에다가 4를 더한 주소에 저장하시오.
즉 항상 레지스터, 메모리 순으로 오며
단순히 x만 있으면 레지스터, 숫자(x숫자) 면 해당 레지스터가 가르키는 메모리 주소가 된다.\
근데 이건 64비트 방식이라서 시험에서 32bit로 나오면
ld대신 다 lw
sd대신 다 sw로 알고있으면 된다.
각 비트 단위에 대해 쓰시오
RISC-V :32bit *32bit의 레지스터
32 bit: word
64bit: doubleword
메모리 8비트 단위를 주소로 사용함.
리틀 인디언 방식과 빅 인디언 방식에 대해 설명하시오.
0x12345678 가 있다면
리틀 엔디언: 적은 자릿수를 앞에 저장하는 방식
0x00에 0x78 저장
0x01에 0x56 저장
0x02에 0x34 저장
0x03에 0x12 저장
RISC-V에서 사용함
빅 엔디언 : 큰 자릿수를 앞에 저장
0x00에 0x12 저장
0x01에 0x34 저장
0x02에 0x56 저장
0x03에 0x78 저장
리틀 엔디언은 하위 먼저 계산하는 산술처리에 유리하며 정렬 잘못되어도 어느정도 읽을 수 있음
빅 엔디언은 읽는 순서와 같아 해석 직관적
A[12] = h +A[8] 이고 , h가 x21에 ,A가 x22에 저장되어있다면
ld x9, 64(x22) // 메모리 64(x22) -> 레지스터 x9에 A[12] 값을적재함. 64(x22)는 레지스터 x22가 가지는 주소에서 64비트 즉 8바이트 떨어져 있다는 말 A[8]이어서 그럼
add x9, x21, x9 // x9에 x21의 값과 x9를 합쳐서 저장함
sd x9, 96(x22) // x9에 있는 값을 96(x22) 디램으로 스토어 함. 96(x22)는 x22에서 96비트 즉 8바이트 떨어져있다는 말 A[12] 여서 그럼.
즉 배열 계산할때는 배열의 시작주소만 레지스터가 저장해 가지고 있다가 offset으로 load한다.
immediate operands 란?
명령어 뒤에 i가 붙어 있음. 자주 사용하는 거 빠르게 하기 위한 명령어, ++ 같은거 이는 make the common case fast 법칙으로 그 예시로는 addi 주소에 있는 값을 불러오는게 아니라 상수 바로 사용 뭐 가령 10이 저장되어 있는 x5가 아닌 그냥 10 때려 넣는 방식n비트일때 unsigned와 signed는 각각 표현 가능한 정수 범위는?
unsigned(부호없는 절대값): 0~2^n -1 signed(부호 있음): -2^(n-1) ~ 2^(n-1) -1signed 방식에서 부호 판단 방식을 쓰시오.
signed는 맨 왼쪽 비트로 0이면 음수, 1이면 양수로 처리.즉 가장 큰수는 0111111...
가장 작은 수는 10000...
맨 앞 부호비트가 1이면(음수이면) 우리가 계산하던 방식으로 숫자 계산하면 안된다는 뜻
어떤 수에서 부호만 바꾸려면 보수(뒤집고) +1 해야한다.
unsigned는 맨 왼쪽도 그냥 수로 처리 알빠노.
비트가 확장될때 어떻게 표현하는가>(8비트->16비트).
맨 왼쪽에 있는 부호비트를 계속 그대로 앞쪽에 복붙하면 된다.0000 0010 -> 0000 0000 0000 0010
1111 1110 -> 1111 1111 1111 1110
각 포맷별 어떻게 표현되는가?
![[Pasted Image 20250325191153_199.png]]4강
시프트 연산자에 대해 설명하고 어셈블리어로 표시하라.
slli: left shift는 i bit 만큼 왼쪽으로 밀면서 0으로 채우는 건데, 이는 2의 i승으로 곱하는 효과가 있다. srli: right shift는 i bit만큼 오른쪽으로 밀면서 0으로 채우는건데, 이는 2의 i승으로 나누는 효과가 있다.예시: slli x14 x19 4는
x19에 있는 값을 4만큼 밀어서 그러니까 16으로 곱해서 x14에 저장하라
and,or 연산자에 대해 설명하고 어셈블리어로 표시하라 . 그리고 각 효과를 쓰시오.
and x9, x10, x11은 x10 과 x11에 and 연산해서 x9에 저장하라.and는 원하는 부분 외에 다 0으로 만드는 mask 효과가 있다.
or x9 x10 x11 은 예상대로 x10과 x11에 or 연산하여 x9에 저장하라
모든걸 그대로 두고 원하는 부분만 1로 바꿀때 or 쓰기도 한다.
그 외
xor은 다르면 True 같으면 false여서,
어떤 값이 있고 xor 연산을 다 1로 채워진 것이랑 하면 반전효과 not과 같은 효과를 얻을 수 있다.
조건문 두가지에 대해 어셈블러로 서술하시오.
beq rs1 rs2 L1 rs1과 rs2가 같으면 L1을 띄워라bne rs1 rs2 L1
rs1과 rs2가 다르면 L1을 띄워라
`if(i==j){` `f = g+h` `}else{` `f=g-h` `}` 를 어셈블리어로 표시하시오. f는 x19, g는 x20, h는 x21, i는 x22에 저장되어 있다
어셈블리어로 다음과 같이 표현된다. else문을 구현하는게 더 편해서f(i!=j){
f=g-h
}
else{
f=g+h
}
로 바꿔서 구현한다.
bne x21 x22 Else
add x19 x20 x21 // 차피 위의 조건이 맞았으면 바로 else로 튀었기에 바로 반대급부 연산 넣어줌
beq x0 x0 Exit// 항상 True인 조건문으로 빠져 나가기 x0은 값을 저장할 수 없어 변형 불가.
else: sub x19 x20 x21
exit:
while(save[i] == k) i+=1;은 어떻게 구현할까 (i는 x22에 k는 x24에 save는 x25에 있다고 가정)
LOOP: slli x10 x22 2 // i의 주소에 4 곱해서 x10에 저장하라. 배열 각 항목은 4바이트 이므로 save[i]의 실제 주소는 save의 시작위치 + i*4에 있음. 즉 offset을 x10에 저장하는 과정임. add x10 x10 x25 // x10에 저장된 값에 (x25)save의 주소만큼을 더하라. 위의 이유와 같음. 그래서 x10은 현재 값이 아닌 더한 주소만큼이 저장됨 .위에서 구한 offset 더해줘서 진짜 배열 위치 알게됨. lw x9 0(x10) // x10의 값을 x9 레지스터에 로드. 즉 주소만 저장되어 있던 x10에서 그 주소에 해당하는 값을 x9로 가져옴. x9는 임의의 값으로 꼭 x9일 필요는 없음. bne x9 x24 Exit // x9(save[i])와 x24(k)가 다른지 비교해 그렇다면 Exit로 addi x22 x22 1 // 만약 같다면 이 행 그대로 진행되어서 i(x22)에 1 추가됨 beq x0 x0 Loop // 무조건 LOOP로 가시오. Exit:basic 블럭이란?
Exit를 제외하고 처음부터 끝까지 순차적으로 아래로 가는 경우를 말한다. 즉 시작을 제외하고 분기되는 가지가 따로 없다. 컴파일러는 이런 basic block 단위로 코드를 최적화 한다. 그러니까 프로그램에서 이 코드만 빼냈을때 독립적으로 논리적 오류 없이 잘 실행되는가로 볼 수 있다. bne나 beq 같은 분기가 아예 없거나 마지막에만 있다면 basic block임대소 비교문에 대해 서술하시오. sigend, unsigned 구분할떄도 쓰시오.
blt rs1, rs2, L1 rs1보다 rs2가 더 크다면 L1 으로 bge rs1 rs2 L1 rs1이 rs2 이상이 라면 L1으로 가라(여기에는 등호가 있다.)if(a>b) a+=1, a가 x22, b가 x23이라면
bge x23 x22 Exit
addi x22 x22 1
Exit:
signed 의 대수 비교는 blt, bge 이고
unsigned의 대수 비교는 u를 붙여서 bltu, bgeu 이다.
프로시저 호출시 작동 순서에 대해 말하시오.
1. x10~x17 사이 레지스터에 파라미터를 사용한다. 2. 함수에 제어권을 넘긴다. 3. 저장공간 확보 4. 함수 내부 코드 실행 5. 레지스터에 return 된 값 저장 6. 함수 호출부 주소로 돌아가고 제어권 넘겨줌함수 호출과 끝에 대해 서술하시오.
procedure call: 함수 호출 jal x1, procedure label x1은 함수 끝나고 돌아올 주소, procedure label은 실행할 함수procedure return: 함수 끝
jalr x0, 0(x1)
x0는 아무 의미 없다. x1 주소로 간다. jalr은 jal과 달리 간접적인 분기를 사용하여, 레지스터에서 주소를 계산하고 그 주소로 분기합니다.
이 명령은 리턴 주소를 저장하지 않기 때문에 x0 레지스터를 사용합니다.
jal -> 함수 -> jalr임.
어셈블리어로 표기하시오. long long int leaf example(long long int g, h, i, j){ long long int f; f = (g+h)-(i+j) ; return f; } f(x20), g(x10), h(x11), i(x12), j(x13) , 계산식의 임시값은 각각 x5,x6 저장
leaf_example: addi sp sp -12 //stack pointer에 함수 내부 변수들 저장할 공간 할당 4바이트 *3 이므로 12만큼 낮춤 sw x5, 8(sp) // stack 순서대로 각각의 위치에 레지스터에 있던 값을 ram에 저장 sw x6, 4(sp) sw x20, 0(sp) add x5, x10, x11 //x5(임시값) 에다가 x10(g)와 x11(h) 더한 값을 저장 add x6, x12, x13 // x6(임시값)에다가 x12(i)와 x13(j) 더한 값을 저장 sub x20, x5, x6 // x20(f) 에다가 위의 두 임시값 뺀 값을 저장 addi x10, x20, 0 //x20에 있는 값을 x10으로 복사해라. x10으로 return 할거임. lw x20 0(sp) //stack 이므로 저장 역순으로 ram에 있던걸 다시 레지스터로 원복 lw x6 4(sp) lw x5 8(sp) addi sp sp 12 //스택포인터 재정렬 jalr x0 0(x1) // 함수 끝. 0(x1)으로 점프메모리 구조에 대해 설명하시오.
stack: 위에서 아래로 가는 구조, 지역 변수 dynamic data:malloc 같은 대용량 자료, 아래에서 위로 가는 heap static data: 전역 변수, static 키워드 text: program code reserved![[Pasted image 20250412171701.png]]
void strcpy(char x[], char y[]){ size_t i; i=0; while((x[i]=y[i]) !='\0') i+=1; } 위는 문자열 x를 y로 복사하는 코드다. x와 y는 x10, x11에 저장되어 있고 i는 x19에 저장
strcpy: addi sp sp -4 //스택포인터에서 사용할 값 i 할당 sw x19 0(sp) //x19를 i로 쓸거니 그전에 스택에 저장되어 있던 값을 저장한다. add x19 x0 x0 // i에 0 저장 L1: add x5 x19 x11 // x5 에 y[i] 주소 저장 lbu x6 0(x5) //x6에 y[i] 저장, add x7 x19 x10 // x7에다가 x[i] 주소 저장 sb x6 0(x7) // x[i]에 y[i] 저장 beq x6 x0 L2 // y[i] 가 0 이라면 탈출해서 L2로 addi x19 x19 1 // i++ // 문자가 1바이트씩 저장되어있는것을 전제로 하기에 *4가 아닌 그냥 바로 +1 jal x0, L1 // L1 반복 L2: lw x19 0(sp) // x19 값 복구 addi sp sp 4 // 스택 정상화 jalr x0, 0(x1) //끝문자표현 방식에 대해 서술하시오
아스키코드: 128개 문자 유니코드: 32비트 캐릭터 문자, 다양한 언어 가능각 한 문자를 byte(8비트), halfword(16비트), word(32비트)로 표현하는 다양한 방식
상수처리할때는 일반적으로 작아서 12비트만으로 충분하지만 32비트짜리를 처리하려면 어떻게 해야할까?
lui는 상수의 상위 20비트를 레지스터의 32비트부터 12비트로 복사하는 명령어다. 그리고 나머지 하위 12비트는 0으로 설정한다.그이후 남은 12비트는 원래대로 add해서 처리
lui x19, 976
addi x19, x19, 1280
branch addressing 할때는 sb format을 쓴다.
그래서 pc-relative addressing 방법에서는
target address는 PC(program counter) + branch offset(immediate *2) 로 결정된다.
더 멀리 뛰고 싶을때 즉, 타겟 범위가 immediate 넘을때 jump addressing이라고 하며
UJ format을 쓴다.
이 경우 lui로 31~12 주소부를 적제하고 이후 jalr로 11:0을 더한다.
각 주소처리 방식에 대해 설명하시오.
immediate addressing: 명령어에 상수값이 있어서 연산할 데이터 상수 포함시 사용 ex) addi register addressing: 연산할 값이 레지스터에 저장되어 있어 두개의 레지스터 값 연산할때 사용 ex) add,sub,and,or,xor base addressing: 메모리에서 데이터 읽거나 저장할때 사용, 특정 베이스 기준 주소 +오프셋, 배열, 메모리에서 불러올때 ex) lw,sw,lb,lh,ld,sb,sh,sd PC-relative addressing: 프로그램 카운터 기준으로만 이동,jump,분기문 즉 함수 점프시 사용 ex)beq,bne,blt,bge,bltu,bgeu![[Pasted Image 20250325190635_888.png]]
5강
atomic operation에 대해 설명하시오.
중간에 다른 동작 interrupt 없는 그 자체로 최소 단위, 이는 하나의 instruction 혹은 그보다 많은 instruction으로 구현 가능 RISC-V는 pair된 instruction으로 구현함. sync 하는데 하드웨어 동기화 지원으로 순서 맞춰야 함.atomic operation과 관련된 어셈블리 명령어에 대해 서술하시오.
load 예약: lr.w rd (rs1), rs1의 주소를 불러올때 메모리를 예약해 둔다. store conditional: sc.w rd rs2 (rs1), rs1은 예약 주소, 그 값이 바뀌지 않았으면 rs2를 저장하고 rd에 정상적으로 0, 바뀌었으면 0이 아닌 값 출력예약 명령어를 활용해 Mem[x20] 와 x23를 swap 하시오.
again: lr.w x10,(x20) // x10 = Memory[x20] sc.w x11,x23,(x20) // X11 = status, Memory[X20] = x23 bne x11,x0,again // branch if store failed addi x23,x10,0 // X23 = loaded value (x10)lock/unlock (0: lock was free, 1: lock was acquired) 을 구현하시오. .
addi x12,x0,1 // copy locked value again: lr.w x10,(x20) // read lock bne x10,x0,again // check if it is 0 yet sc.w x11,x12,(x20) // attempt to store bne x11,x0,again // branch if fails Unlock: sw x0,0(x20) // free lockc코드 작성 후 작동 과정에 대해 서술하시오.
c 코드 작성 -> 컴파일러가 어셈블리어로 바꿈 -> 어셈블러가 기계어로 바꿈 + 불러오는 다른 라이브러리 파일까지 linker가 엮기 ->만들어진 실행 파일 loader가 메모리에 옮김어셈블리어로 만들어진 obj file의 각 부분들에 대해 설명하시오.
어셈블리어로 만들어진 obj file의 부분들 - header: 오브젝트 모듈 컨텐츠 설명 - text segment: 기계어 명령어 저장된 부분 - static data segment: 프로그램 실행 동안 유지되는 전역변수, 등이 저장됨 - relocation info : 실행시 주소 결정하는 코드들에 대한 정보, 오브젝트 파일도 relocate 해야됨. 그래서 링커까지 거쳐서 메모리에 어디 거쳐야 하는지도 relocation info에 들어가서 링커 거쳐야 실행 가능 - symbol table : 함수, 전역변수 등의 정의와 참조 정보 - debug info : 디버깅 정보링커가 하는 일과 그 이유는?
링커: 세그멘트 단위로 모으고, 각 메모리의 위치 정해지고, 메모리 의존적 relocation 해줌. - 재배치를 로더에서 안하고 링커에서 하는 이유: 가상 메모리 사용하면 가능해서.로더가 하는 일과 그 순서를 서술하시오.
로더: 디스크의 이미지 파일을 메모리로 옮겨주는 역할 1. 해더 읽고 크기 계산 2. 가상 주소공간 설정 3. 코드 및 초기화된 데이터 복사 4. 스택 및 레지스터 초기화 5. 프로그램 진입점 실행 => main 함수 호출dynamic 링킹을 하는 이유는?
링커를 static으로 쓰면 라이브러리 다 불러와야 되서 너무 커짐, 라이브러리 파일 업데이트 될때마다 새로 파일 만들어주어야 함, 그래서 dynamic 링킹을 씀: 다른 라이브러리 있는거 쓸때 그때그때 lazy 하게 링킹해서 씀.java의 동작방식과 장단에 대해 서술하시오.
컴파일 하면 자바바이트 코드로 변환하고, JVM이 그때그때 인터프리터형태로 바꿔서 실행. 그래서 CPU아키텍쳐에 따라 컴파일러 바꿀 필요 없다는 장점 그대신 좀 느리다는 단점. 그래서 just in time compiler로 자주 사용하는 거는 바로 기계에 맞게 컴파일해서 응용함.swap, sort 관련해 c언어- > 컴파일러로 바꾼 코드들 이해하기
preserving registers 교안의 sd는 오타이니 다 sw로 바꿔서 이해하기
6강
덧셈과 뺼셈 방법에 대해 설명하시오.
컴퓨터도 똑같이 1과 0끼리 받아올림 해서 덧셈을 계산한다.오버플로우로 판단할 수 있는경우
- 양수 둘 더했는데 최상위 비트가 1인경우(음수로 나온경우)
- 음수 둘 더했는데 최상위 비트가 0인경우(양수로 나온경우)
뺄셈은 양수에 음수를 더한다는 관점으로 보면 된다.
뺄셈에서는 두 연산자 같은 경우 오버플로우 발생할 일 없다.
+에서 -를 뺐는데 음수가 나오는 경우, -에서 +를 뺐는데 양수가 나오는 경우는 오버플로우다.
SIMD 기술에 대해 설명하시오.
멀티미디어 데이터는 8비트, 16비트 등 다양한 비트 크기를 가지지만, CPU는 32비트나 64비트 단위로 연산하기 때문에 낭비가 발생할 수 있다. 이를 해결하기 위해 SIMD 방식으로 여러 데이터를 하나의 레지스터에 담아 동시에 처리하며 효율을 높인다. 또한, 오버플로우가 발생할 경우에는 잘린 값을 쓰지 않고 최대값으로 고정하는 포화 연산(saturating arithmetic)을 사용해 데이터 품질을 유지한다.곱셈 방식에 대해 알고리즘을 작성하시오.
multiplicand(피승수) * multiplier(승수) = product(초기값 0)For (Multiplier의 비트 수)
if multiplier의 최하위 비트 == 1?
product += Multicand
Multiplicand << 1 // 값을 2배로 증가시킴
multiplier >>1 // 최하위 비트 판정을 다음 비트로 이동시킴
return product;
개선된 곱셈 방식에 대해 알고리즘을 작성하시오.
product = multiplier // product에 multiplier 넣고 시작 multiplicand << multiplier의 비트 수 //product의 앞 부분에 적혀야 하니 그에 따른 공간확보하고 시작 For (multiplier의 비트 수) if product의 최하위 비트 == 1? // product의 최하위 비트 확인 product += multiplicand // product에 multiplicand 더하기 product >> 1 // product 오른쪽으로 1비트 시프트 (중간에 결과를 맞추기 위해) return product연산을 더더욱 빠르게 하려면 어떻게 해야하는가?
덧셈기를 31개 두어 병렬로 처리하면서 각각 비트 계산을 병렬로 처리해 시간은 아무튼 빠르게 할 수 있음..RISC-V 에서 지원하는 곱셈 종류 4가지를 쓰시오.
mul: 곱셈 결과의 하위 32비트 제공 mulh: 곱셈 결과의 상위 32비트 제공 (연산자가 signed 일때 제공), 오버플로우 검증 가능 mulhu: 곱셈결과의 상위 32비트 제공(연산자가 unsigned 일때 제공) mulhsu: 곱셈 결과의 상위 32비트 제공(하나는 signed, unsigned 일떄)나눗셈 방식에 대해 알고리즘을 작성하시오.
Divedened / Divisor = Quotent... Remainder Divisor은 왼쪽 절반에 저장 Remainder = Dividend Quotient = 0 For (Divisor의 비트 수) Remainder = Remainder - Divisor if (Ramainder) 0 보다 작은가? (최상위 비트1) Remainder 복구 (Remainder = Remainder + Divisor) Quotient << 1 Quotent 최하위비트 = 0 else (최상위 비트 0) Quotient << 1 Quotient 최하위비트 = 1 Divisor >> 1개선된 나눗셈 방식에 대해 알고리즘을 작성하시오.
dividend / divisor = quotient ... remainder 라고 할때
if(divisor ==0) return error
remainder= 0
quotient = divedened
for(divdend의 비트수 +1)g
(remainder:quotient) <<1
remainder -= divisor
if remainder이 음수?:
remainder = remainder + divisor // 복원
quotient의 마지막 비트 = 0
else:
quotient의 마지막 비트 = 1
return quotient, remainder
더 빠른 나눗셈을 위해서는 어떻게 해야하는가?
다만 더 빠른 나눗셈 연산은 뺄셈결과에 따라 복원해야 되기에 곱셈처럼 단순히 덧셈기 여러개 다쓰는것만으로는 개선 불가능, 그래서 미리 lookuptable로 미리 빼는게 가능한지 아닌지 몇개씩 예측하는 것 두어서 어느정도 해결 가능Risc-V에서의 나눗셈 연산 명령어를 쓰시오.
div, rem : sigend 나눗셈과 나머지 divu, remu: unsigned 나눗셈과 나머지7강
부동 소수점에서 표준화된 형태의 표기와 정의역을 쓰시오.
10진법: a*10^b
1<=|a|<10
2진법: a*2^b
1<=|a|<2
부동 소수점의 3가지 경우와 어떻게 구분하는지 쓰시오,
1. normalized values - 일반적 2. denormalized values - exponent 가 모두 0 3. special values - exponent가 모두 1IEEE 부동소수점 표기 방법과 그 공식을 쓰시오.
실제 비트로 적히는 것
맨앞 S: 부호비트
exponent: 지수 관련
fraction: 곱해지는 수 관련
공식
(-1)^S * (1+fraction) * 2^(exponent-bias)
significand = 1+fraction으로 1이상 2 미만 값
bias는 상수, single일때는 127, double일때는 1023
Single-precision과 double-precision의 절대값의 최소와 최대를 적으시오, single의 경우 exponent와 fraction이 8,23 비트이고, double의 경우 11, 52 비트이다.
singleMin : 1.0 * 2^(-126)
singleMax: 2.0 * 2^127
doubleMin: 1.0 * 2^-1022
doubleMax: 2.0 *2^1023
-0.75를 이진수 부동소수점으로 표시하시오.
Single: 1| 01111110 | 1000…00 Double: 1| 01111111110 | 1000…0011000000101000…00 를 부동 소수점 십진법으로 표시하시오.
-5.0Denormalized Values에서의 공식과 비트를 쓰시오.
s: 그대로 부호 exp: 모두 0 frac: 그대로계산 공식 변경됨 : 지수가 Exponent- bias 가 아니라, 1- bias 즉, 상수 - 상수이니 상수처럼 계산됨.
speical values는 무엇을 표기하는가
exp가 모두 1이다. 근데 여기서 fraction이 모두 0이면 무한대 그렇지 않으면 NaN0.5 + –0.4375 를 부동소수점 이진수로 연산하시오.
1.000 × 2^(–4)0.5 × –0.4375 를 부동소수점 이진수로 연산하시오.
–1.110 × 2^(–3) = –0.21875반올림하는 방식 4가지와 그에 따라서 1.40, 1.60. 1.50, 2.50, -1.50 이 어떻게 변하는지 적으시오.
![[Pasted image 20250415111230.png]]'CS 내용 요약, 지식' 카테고리의 다른 글
데이터베이스 시험 대비 | 백지 문답식 핵심 정리 (1) | 2025.05.02 |
---|---|
Docker, 쿠버네티스 개념 정리 (4) | 2024.10.08 |
데이터 통신 기초 - 3. 물리 계층 (0) | 2024.04.06 |
데이터 통신 기초 - 2. 네트워크 모델 (0) | 2024.03.31 |
데이터 통신 기초 - 1. Overview (0) | 2024.03.31 |