반응형

간단 지식/System Programming 10

10. buffer overflow

버퍼 오버플로우란 프로세스가 데이터를 버퍼에 저장할 때 개발자가 지정한 곳 밖에 저장하여, 범위 밖의 데이터가 인접 메모리를 overwrite함으로써 오류가 발생하는 현상을 말한다. 여기서 버퍼란, 일시적으로 데이터를 보관하는 메모리의 영역이다. 대표적으로 버퍼 오버플로우를 일으키는 원인을 제공할 수 있는 함수가 하나 있다. 바로 gets()이다. 아래는 gets()의 원형코드이다. char *gets(char *dest){ int c = getchar(); char *p = dest;----------(1) while(c != EOF && c != '\n'){ *p++ = c; c = getchar(); } *p = '0'; return dest; } 코드라인 (1)에 따라 gets()는 버퍼의 시작주..

09. stack frame, register saving convention

컴파일을 하면 스택에 코드가 쌓인다는 것은 우리가 다 아는 사실이다. 그렇다면 스택의 내부는 어떻게 생겼을까? 이 질문에 대한 해답을 얻기 전에 procedure의 data flow와 메커니즘 3가지에 대해 이해할 필요가 있다. procedure의 data flow는 저장되는 argument가 어디에 어떤 식으로 저장되는지를 말한다. procedure는 레지스터에 총 6개의 argument까지 저장할 수 있다. (저장 순서: %rdi -> %rsi -> %rdx -> %rcx -> %r8 -> %r9) 그리고 별도의 return 값을 저장하는 %rax를 제외하고 나머지 argument는 스택에 저장된다. 즉 인자값이 6개를 넘어가면 7번째 인자부터는 스택에 저장된다는 의미이다. procedure의 메커니..

08. conditional expression - using branch or move

어셈블러가 c코드로부터 jle, jne와 같은 명령어들을 산출해내는 이유는 변환하는 코드에 branch instruction이 있기 때문이다. 그러나 지금 이 시간은 개발자가 아니라 시스템 입장에서 코드를 봐야한다. 잦은 branch의 사용은 파이프라인 구조에 파괴적이기 때문에 CPU 관점에서 좋지 않다. 따라서 우리는 조건식을 branch가 아니라 move 명령어를 사용해서 동일한 효과를 낼 수 있다. 한가지 예제 코드를 보자. long test(long x, long y){ long result; if(x>y) result = x-y; else result = y-x; return result; } 지난 글에도 사용했던 if-else문 예제이다. 보이다 싶이 L2로 이동하는 branch 명령어가 보인..

07. condition code - 상태 레지스터, setX 명령어, jX 명령어

실행 중인 프로그램에 대한 정보(processor state)는 크게 아래 4개로 분리할 수 있다. 1. temporary data 2. location of runtime stack 3. location of current code control pointer 4. status of recent test 임시 데이터는 레지스터 %rax, %rbx 등에 저장되어있다. runtime stack의 위치는 스택포인터 %rsp에 저장된다. 현재 코드의 구조포인터는 %rip 에 저장된다. 최근 테스트에 대한 상태는 상태 레지스터를 조직하는 flag bit들에 저장된다. 이번 글에서 다룰 내용은 4번에 해당하는 상태 레지스터이다. 상태 레지스터는 status register 또는 flag register라고도 하며..

06. Arithmetic operation of register, 레지스터와 변수의 관계

이제까지 movq와 leaq 연산에 대해 알아보았는데, 가장 기본적인 산술연산도 있음을 알아두자. 아래 표는 2개의 피연산자 구조(연산자 src, dest)를 갖는 연산자이다. 연산자 연산식 addq dest = dest + src subq dest = dest - src imulq dest = dest * src salq dest = dest > src (산술) shlq dest = dest > src (논리) xorq dest = dest ^ src andq dest = dest & src orq dest = dest | src 괄호 안에 산술, 논리라고 적힌 연산자들은 연산식은 동일하지만 sign bit 처리에 대해서는 차이가 있다. 산술 연산자들은 shift 연산 후 빈 공간을 이전 수의 sign..

05. movq와 leaq의 address 계산 방식

movq의 주소 지정 방식의 가장 일반적인 형식과 그에 따른 메모리 계산식은 다음과 같다. D(Rb, Ri, S), MEM[Reg[Rb] + S*Reg[Ri] + D] D: 일정 배수. 1, 2, 4 byte중 하나. 임의의 데이터 구조에 대해 임의의 offset을 정해주는 용도. Rb: 베이스 레지스터. %rax를 포함한 16개의 레지스터 중 하나. 명시되지 않으면 0으로, hw가 작동할 때 D, Ri, S가 무슨 값을 갖던 간에 신경쓰지 않는다. 메모리의 base 주소를 알려주는 용도. Ri: 인덱스 레지스터. %rsp를 제외한 모든 레지스터. 명시되지 않으면 0. S: scale, size를 의미. 어셈블리어를 지원하는 정수들. 1, 2, 4, 8 중 하나. 명시되지 않으면 1. 아래는 위 기본 형..

04. Register - movq source, dest

x86-64 bit 컴퓨터의 CPU에는 아래 16개의 레지스터가 저장되어 있다. 8byte 4byte 1byte %rax %r8 %eax %r8d %al %r8b %rbx %r9 %ebx %r9d %bl %r9b %rcx %r10 %ecx %r10d %cl %r10b %rdx %r11 %edx %r11d %dl %r11b %rsi %r12 %esi %r12d %sil %r12b %rdi %r13 %edi %r13d %dil %r13b %rsp %r14 %esp %r14d %spl %r14b %rbp %r15 %ebp %r15d %bpl %r15b 기본적으로 64bit이며, 어셈블리의 특징인 '모든 데이터 타입은 정수형 1, 2, 4, 8 byte 이다'를 만족하기 위해 각각의 레지스터들을 1, 2, 4b..

03. CPU와 Memory의 관계

프로그래머의 입장에서 CPU와 Memory의 관계는 위 그림과 같다. 두 관계에서 address와 instruction은 일방, data는 쌍방으로 주고받는다. 각각을 구성하는 요소들에 대해 자세히 알아보자. CPU는 흔히 아는 intel 7세대 코어i5와 같은 컴퓨터에 내장된 칩을 말한다. 하드웨어의 영역에 포함되며 크게 3가지 요소가 저장되어 있다. PC는 Program Counter의 약자로, 지금 실행 중인 instruction이 끝난 후 실행할 instruction의 주소를 저장한다. 그런 의미에서 x84-64 bit에서는 RIP(Register Instruction Pointer)라고 불린다. 다음에 실행할 코드의 주소를 저장하기 때문에 메모리에서 instruction을 일방적으로 가져온다. ..

02. 시스템의 컴파일 과정

적정한 크기의 소스코드를 컴파일하면 수 초 안에 결과물을 볼 수 있다. 그 수 초 안에는 어떤 과정들이 담겨있는 걸까? 총 4단계로 이뤄지며 각 단계에서 산출한 파일이 순차 처리된다. 가상의 파일 hello.c가 있다고 가정해보자. 1단계, 전처리(Preprocessing) text형식의 c언어 파일(hello.c)를 받아서 modified source program(hello.i)으로 변환한다. 2단계, C언어로 어셈블리 코드 생성(Compilation) text형식의 modifed source program(hello.i)를 assembly code(hello.s)로 변환한다. 3단계, 기계어로 object파일 생성(Assembly) text형식의 assembly code(hello.s)를 reloc..

01. byte 지향 메모리 조직

컴퓨터가 2진수를 사용하는 이유 현재 컴퓨터는 2진 체계를 사용한다. 사람의 입장에선 10진수가 더 좋아 보이는데 왜 2진수를 사용하는 걸까? 그 이유는 10진수를 사용하면 전자/전기적 이행의 문제로 인해 저장,전송이 불편해지기 때문이다. 10진수는 10을 기수로 하는 기수법이기 때문에 10단계 신호를 부호화해야 한다. 따라서 높은 정밀도를 필요로 하며 연산과 같은 디지털 논리 기능 이행의 복잡함이 문제가 된다. 그래서 고안된 방법이 쌍안정 회로의 특징을 이용한 2진 체제이다. 더군다나 컴퓨터에는 최대 5V까지의 전류가 흐르도록 제한되어 있는데 0은 0.0V ~ 0.5V, 1은 2.8V ~ 3.3V까지 저장할 수 있다. 즉 0과 1을 오가며 부호화를 진행해도 아무 문제가 없다. byte 지향 메모리 조직..

반응형