크래프톤 정글 TIL : 0721

lazyArtisan·2024년 7월 21일
0

정글 TIL

목록 보기
21/147

🎯 To-do List


CSAPP 저자 직강 유튜브 보기
☑️ 운영체제 영상 보기
☑️ 운영체제 블로그 보기
☑️ 월요일 점심 먹고 : 동적 프로그래밍 발표
☑️ 화요일 점심 먹고 : Knapsack Problem 발표

📖 CSAPP


책 말고 저자 직강 유튜브를 보며 정리

📝 01 Overview

추상화는 좋지만 현실을 잊지 마라

Great Reality #1: Ints are not Integers, Floats are not Reals
x^2은 0보다 항상 크거나 같은가?
컴퓨터로 계산하면 항상 그렇지는 않을 수 있다.
50000 * 50000 이런거 하면 오버플로우돼서 -175933 어쩌구 숫자 됨.

-> 수학의 기본적인 원칙들이 항상 맞을거라 기대하지 마라

Great Reality #2: You've got to know Assembly
어셈블리어로 코드 짤 필요는 없는데(그런 건 컴파일러가 더 잘함) 이해할 줄 알아야 기계 수준에서 실행되는 원리들을 알 수 있다. 그래야 버그 고치거나 성능 개선하거나 시스템 소프트웨어 만들거나 멀웨어 만들거나 퇴치할 수 있음.

Great Reality #3: Memory Matters
메모리를 잘 알아야 버그(ex. Memory Referencing Errors)도 잘 잡고 성능도 개선할 수 있다. 캐시나 가상 메모리같은 메모리 시스템 아는거 성능 개선에 중요함.

📝 02 Bits, Bytes, and Integers

모든 비트가 0 또는 1인 것의 장점 : 노이즈같은거 무시됨

1바이트 = 8비트

C에서 &&, &, |, || 의 차이점을 주의하라

비트 연산자

& (비트 AND): 대응되는 비트가 모두 1일 때 결과 비트가 1.
| (비트 OR): 대응되는 비트 중 하나라도 1이면 결과 비트가 1.
^ (비트 XOR): 대응되는 비트가 서로 다를 때 결과 비트가 1.
~ (비트 NOT): 각 비트를 반전시켜 0은 1로, 1은 0으로.
<< (왼쪽 시프트): 모든 비트를 왼쪽으로 이동시키고 오른쪽에 0을 채움.
>> (오른쪽 시프트): 모든 비트를 오른쪽으로 이동시키고 왼쪽에 부호 비트를 채움.

왼쪽 시프트 연산 예시

#include <stdio.h>

int main() {
    int a = 5;  // 0101 in binary
    int result = a << 1;  // 1010 in binary (10 in decimal)
    printf("a << 1 = %d\n", result);  // Output: 10
    return 0;
}

논리 연산자

&& (논리 AND): 두 피연산자가 모두 참일 때 결과가 참.
|| (논리 OR): 두 피연산자 중 하나라도 참이면 결과가 참.
! (논리 NOT): 피연산자가 거짓이면 결과가 참, 참이면 결과가 거짓.

정수 표현법

1. 부호 없는 정수(Unsigned Integers)

모든 비트가 값의 일부로 사용되는 형식

2. 2의 보수 형식(Two's Complement)

2의 보수는 주어진 이진수의 모든 비트를 반전(0을 1로, 1을 0으로)시킨 다음 1을 더하여 얻음. 양수의 2의 보수를 음수라고 취급하는게 2의 보수 형식.


이미지 출처

1의 보수: 이진수에서 각 비트를 반전.
2의 보수: 1의 보수에 1을 더한 것. 음수를 표현하는 표준 방법.
2의 보수의 장점: 덧셈과 뺄셈의 통합, 유일한 0 표현.

부호 비트(Sign Bit)

  • 2의 보수 형식에서 맨 앞의 비트 1개인 가장 중요한 비트(MSB)는 부호를 나타냄.
  • MSB가 0이면 양수, 1이면 음수를 나타냄.

x = 15213

  • 10진수: 15213
  • 2진수: 0011 1011 0110 1101
  • 16진수: 3B 6D

y = -15213

  • 10진수: -15213
  • 2진수: 1100 0100 1001 0011
  • 16진수: C4 93

Numeric Ranges

2의 보수 형식은 비트 하나를 부호 표현에 써서 부호 없는 정수 형식보다 표현할 수 있는 숫자가 반 정도 줄어든다.

Casting Surpises


(-1과 부호 없는 0을 비교했더니 왼쪽이 더 크다고 나온다)

C에서 부호 있는 정수(signed integers)와 부호 없는 정수(unsigned integers)를 섞어 사용할 때 암묵적으로 부호 없는 값으로 해석됨. 그래서 원하지 않는 결과를 얻을 수 있음.

이진수 사칙연산

사칙연산할 때 오버플로 발생하면 넘어간 비트는 버린다

듣다가 내가 이런걸 왜 듣고 있지? 무슨 소리 하는거지? 칠판에 조막만하게 뭘 적고 있는거지? 라는 생각이 들어서 5강으로 넘어감

📝 Machine Level Programming I : Basics

용어 정의

  • Architecture (+ ISA: Instruction set architecture) : 어셈블리어나 기계어를 이해하거나 작성하기 위해 필요한 프로세스 디자인들
  • Microarchitecture : 아키텍처를 구현한거
  • Machine Code : 프로세서가 실행시키는 바이트 수준 프로그램
  • Assembly Code : 기계어를 글로 쓴거

가상 메모리 : 프로세서에서 돌아가는 각 프로그램들이 독립적인 바이트의 배열을 갖고 있다고 착각하게 해주는거

Turning C into Object Code

  1. C로 코드를 짠다
  2. 컴파일러가 어셈블리어로 바꾼다
  3. 그걸 어셈블러가 기계어로 바꾼다
  4. 링커가 라이브러리랑 이어준다
  5. 컴퓨터가 실행 가능한 파일 완성

어셈블리어 특징

  • Integer 데이터 : 1,2,4,8 바이트
  • Floating 데이터 : 4,8,10 바이트
  • 코드 : CPU가 실행할 수 있는 기계어 명령어들
  • No Aggregate Types : 배열이나 구조체와 같은 집합 타입을 직접 지원하지 않고, 메모리 내에 연속적으로 할당된 바이트로 데이터를 처리함

Disassembled


기계어를 디스어셈블러로 다시 번역해서 어셈블리어하고 기계어 비교한거
c언어에서 변수 이름 설정했던거 기계어나 어셈블리어 수준에선 다 생략된다

나는 컴퓨터가 0이랑 1만 안다고 생각했는데 기계어에 있는 저 16진법 숫자들은 뭐임

기계어는 실제로 0과 1로 구성된 이진수 형태로 CPU에 의해 처리됩니다. 그러나 이러한 이진수들을 사람이 이해하고 다루기 쉽게 하기 위해 16진수로 표현하는 것이 일반적입니다. 16진수는 이진수보다 더 짧고 간결하게 표현할 수 있어 가독성이 좋습니다.

16진수와 기계어

  • 16진수: 0-9와 A-F를 사용하여 0부터 15까지의 값을 표현합니다. 예를 들어, 0xA는 10을, 0xF는 15를 의미합니다.
  • 기계어: CPU가 직접 이해하고 실행할 수 있는 이진수 명령어입니다. 어셈블리어는 이러한 기계어 명령어를 사람이 이해하기 쉽게 표현한 것입니다.

16진수의 역할

  • 가독성: 이진수는 매우 길어질 수 있기 때문에 16진수로 표현하여 가독성을 높입니다. 예를 들어, 1111 1111 1111 1111 1111 1111 1111 1111은 0xFFFFFFFF로 간결하게 표현됩니다.
  • 편리성: 디버깅과 시스템 프로그래밍에서 메모리 주소나 값들을 다룰 때 16진수 표현이 더 편리합니다.

Moving Data

movq : 64비트 데이터 옮기는 어셈블리 명령어. movq 출발지 목적지 형식으로 사용한다.

출발지 목적지의 형식

  • Immediate : $ 붙이면 상수 취급됨. 레지스터 안 거쳐서 Immediate(즉시)라고 하는듯
  • Register : %rax 같은거. 레지스터 가리킨다. %rsp는 스택 포인터만 가리킴.
  • Memory : (%rax) 같은거. 레지스터에 있는 주소가 가리키는 메모리를 가리킴.
  • 메모리에서 메모리로는 절대 못 간다.

Understanding Swap()

변수 2개에 있는 값들 서로 바꿀 때 레지스터에 있던거 메모리에 넣어놓고 서로의 값을 가져오면 된다.

Some Arithmetic Operations


목적지 값에서 출발지 값 빼거나 더하거나 할 수 있다.

leaq : 지정된 메모리의 주소값을 레지스터에 저장한다

📝 Machine Level Programming II : Control

Processor State

레지스터에는 실행중인 프로그램에 대한 정보들도 담긴다.

  • 임시 데이터
  • 런타임 스택 위치
  • 현재 실행중인 코드 명령줄 위치
  • 이전에 수행된 연산 결과 : cmpq 명령어 결과가 담김

1. 임시 데이터 (Temporary Data)

  • 레지스터: %rax, %rbx, %rcx, %rdx, %rsi, %rdi, %r8 ~ %r15
  • 설명: 임시 데이터를 저장하는 데 사용됨. 연산 중간 값이나 함수 호출 시 인자 등을 저장.
  • 역할:
    • %rax: 누산기(accumulator) 레지스터, 주로 연산 결과를 저장.
    • %rbx: 베이스(base) 레지스터, 주로 간접 주소 지정에 사용.
    • %rcx: 카운터(counter) 레지스터, 주로 루프나 반복 연산에 사용.
    • %rdx: 데이터(data) 레지스터, 주로 입출력 작업에 사용.
    • %rsi: 소스 인덱스(source index) 레지스터, 주로 문자열 연산에서 소스 주소로 사용.
    • %rdi: 목적지 인덱스(destination index) 레지스터, 주로 문자열 연산에서 목적지 주소로 사용.
    • %r8 ~ %r15: 추가적인 일반 목적 레지스터.

2. 런타임 스택의 위치 (Location of Runtime Stack)

  • 레지스터: %rsp (Stack Pointer)
  • 설명: 스택의 최상위 위치를 가리킴. 함수 호출 시 인자, 리턴 주소, 지역 변수 등을 저장하는 데 사용됨.
  • 역할:
    • 함수 호출 시 리턴 주소와 로컬 변수를 저장.
    • 함수가 호출될 때 %rsp는 스택의 현재 최상위 주소를 가리키고, 함수가 종료될 때 이전 상태로 복원.
    • 스택 프레임의 관리를 통해 함수 간의 호출 관계를 유지.

3. 현재 코드 제어 지점의 위치 (Location of Current Code Control Point)

  • 레지스터: %rip (Instruction Pointer or Program Counter)
  • 설명: 현재 실행 중인 명령어의 주소를 저장.
  • 역할:
    • 프로그램이 순차적으로 명령어를 실행하면서 %rip의 값이 증가.
    • 분기 명령어(jump, call 등)가 실행되면 %rip의 값이 변경되어 다른 위치의 명령어를 실행.

4. 최근 테스트의 상태 (Status of Recent Tests)

  • 플래그 레지스터: CF (Carry Flag), ZF (Zero Flag), SF (Sign Flag), OF (Overflow Flag)
  • 설명: 이전에 수행된 연산의 결과를 나타내는 플래그(상태 비트).
    • CF (Carry Flag): 산술 연산에서 자리 올림이 발생했는지를 나타냄.
      • 예: 8비트 연산에서 255(0xFF)에 1을 더하면 256이 되어 9비트가 필요하지만, 8비트 레지스터에서는 0이 되고, CF가 1이 됨.
    • ZF (Zero Flag): 연산 결과가 0인지를 나타냄.
    • SF (Sign Flag): 연산 결과의 부호를 나타냄.
    • OF (Overflow Flag): 부호 있는 연산에서 오버플로우가 발생했는지를 나타냄.

Reading Condition Codes

어셈블리 명령어 cmpq의 결과가 CF, ZF, SF, OF에 담기고, 그 결과를 바탕으로 SetX 명령어가 실행됨.

SetX 명령어: 조건 코드 플래그 조합에 따라 목적지 레지스터의 제일 작은 바이트를 0 또는 1로 설정

  • sete: ZF가 설정된 경우 (Equal/Zero).
  • setne: ZF가 설정되지 않은 경우 (Not Equal/Not Zero).
  • sets: SF가 설정된 경우 (Negative).
  • setns: SF가 설정되지 않은 경우 (Nonnegative).
  • setg: SF와 OF가 다르고 ZF가 설정되지 않은 경우 (Greater).
  • setge: SF와 OF가 다른 경우 (Greater or Equal).
  • setl: SF와 OF가 같은 경우 (Less).
  • setle: SF와 OF가 같거나 ZF가 설정된 경우 (Less or Equal).
  • seta: CF와 ZF가 설정되지 않은 경우 (Above).
  • setb: CF가 설정된 경우 (Below).

0개의 댓글