✅ CSAPP 저자 직강 유튜브 보기
☑️ 운영체제 영상 보기
☑️ 운영체제 블로그 보기
☑️ 월요일 점심 먹고 : 동적 프로그래밍 발표
☑️ 화요일 점심 먹고 : Knapsack Problem 발표
책 말고 저자 직강 유튜브를 보며 정리
추상화는 좋지만 현실을 잊지 마라
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)도 잘 잡고 성능도 개선할 수 있다. 캐시나 가상 메모리같은 메모리 시스템 아는거 성능 개선에 중요함.
모든 비트가 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): 피연산자가 거짓이면 결과가 참, 참이면 결과가 거짓.
모든 비트가 값의 일부로 사용되는 형식
2의 보수는 주어진 이진수의 모든 비트를 반전(0을 1로, 1을 0으로)시킨 다음 1을 더하여 얻음. 양수의 2의 보수를 음수라고 취급하는게 2의 보수 형식.
1의 보수: 이진수에서 각 비트를 반전.
2의 보수: 1의 보수에 1을 더한 것. 음수를 표현하는 표준 방법.
2의 보수의 장점: 덧셈과 뺄셈의 통합, 유일한 0 표현.
2의 보수 형식은 비트 하나를 부호 표현에 써서 부호 없는 정수 형식보다 표현할 수 있는 숫자가 반 정도 줄어든다.
(-1과 부호 없는 0을 비교했더니 왼쪽이 더 크다고 나온다)
C에서 부호 있는 정수(signed integers)와 부호 없는 정수(unsigned integers)를 섞어 사용할 때 암묵적으로 부호 없는 값으로 해석됨. 그래서 원하지 않는 결과를 얻을 수 있음.
사칙연산할 때 오버플로 발생하면 넘어간 비트는 버린다
듣다가 내가 이런걸 왜 듣고 있지? 무슨 소리 하는거지? 칠판에 조막만하게 뭘 적고 있는거지? 라는 생각이 들어서 5강으로 넘어감
가상 메모리 : 프로세서에서 돌아가는 각 프로그램들이 독립적인 바이트의 배열을 갖고 있다고 착각하게 해주는거
기계어를 디스어셈블러로 다시 번역해서 어셈블리어하고 기계어 비교한거
c언어에서 변수 이름 설정했던거 기계어나 어셈블리어 수준에선 다 생략된다
나는 컴퓨터가 0이랑 1만 안다고 생각했는데 기계어에 있는 저 16진법 숫자들은 뭐임
기계어는 실제로 0과 1로 구성된 이진수 형태로 CPU에 의해 처리됩니다. 그러나 이러한 이진수들을 사람이 이해하고 다루기 쉽게 하기 위해 16진수로 표현하는 것이 일반적입니다. 16진수는 이진수보다 더 짧고 간결하게 표현할 수 있어 가독성이 좋습니다.
16진수와 기계어
16진수의 역할
movq
: 64비트 데이터 옮기는 어셈블리 명령어. movq 출발지 목적지
형식으로 사용한다.
$
붙이면 상수 취급됨. 레지스터 안 거쳐서 Immediate(즉시)라고 하는듯%rax
같은거. 레지스터 가리킨다. %rsp
는 스택 포인터만 가리킴.(%rax)
같은거. 레지스터에 있는 주소가 가리키는 메모리를 가리킴.변수 2개에 있는 값들 서로 바꿀 때 레지스터에 있던거 메모리에 넣어놓고 서로의 값을 가져오면 된다.
목적지 값에서 출발지 값 빼거나 더하거나 할 수 있다.
leaq
: 지정된 메모리의 주소값을 레지스터에 저장한다
레지스터에는 실행중인 프로그램에 대한 정보들도 담긴다.
cmpq
명령어 결과가 담김%rax
, %rbx
, %rcx
, %rdx
, %rsi
, %rdi
, %r8
~ %r15
%rsp
(Stack Pointer)%rsp
는 스택의 현재 최상위 주소를 가리키고, 함수가 종료될 때 이전 상태로 복원.%rip
(Instruction Pointer or Program Counter)%rip
의 값이 증가.%rip
의 값이 변경되어 다른 위치의 명령어를 실행.어셈블리 명령어 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).