본문 바로가기

분류 전체보기

(308)
[어셈블리] 쉬프트 연산 쉬프트 연산 쉬프트 연산은 비트를 좌측이나 우측으로 옮기는 연산인데, 산술 쉬프트 연산에서는 최상위 비트를 그대로 유지함 ex) 1001 1010 >>1 => 1101 0101 어셈블리에서는 shl, shr을 통해 쉬프트 연산을 할 수 있다. mov eax, 0x12345678 처음에 eax에 4바이트의 데이터를 저장한다. shl eax, 8 =>34567800 shr eax, 8 =>345678 왼쪽으로 8비트(2바이트)만큼 이동했다가 오른쪽으로 다시 8비트만큼 이동했다. 쉬프트 연산을 할 때 1을 하면 마찬가지로 양수일 때 값이 원래 값에 2로 나눈 것과 같다. 그래서 컴파일러가 내부적으로 계산을 할 때 사용하기도 한다.
[어셈블리] 입출력, 사칙 연산 입력 - GET_DEC 데이터크기, 저장할 레지스터(변수) GET_DEC 1,al (레지스터) GET_DEC 1,num (변수) 출력 - PRINT_DEC , GET_DEC와 동일 더하기 - add a,b ( a= a+b ) 메모리끼리 더하는 것은 불가능 add al,[num] => al+[num]의 값이 al에 저장됨 곱하기 - mul bl ( ax= al * bl) 연산결과를 ax에 저장 mul bx ( ax * bx 한 결과를 상위 16비트는 dx에, 하위 16비트는 ax에 저장) 좀 자기 멋대로인듯 나누기 - div bl ( ax / bl) 몫은 al, 나머지는 ah에 저장 얘가 제일 지멋대로다
[어셈블리] 변수와 레지스터 변수는 데이터를 담는 바구니이다. 변수는 data 영역과 bss 영역에 담을 수 있는데 data에서는 [변수이름] [크기] [초기 값]으로 초기화 된 데이터를 담는다. [크기]는 db(1바이트) dw(2) dd(4) dq(8)이 있다. ex) a db 0x11 bss에서는 [변수이름] [크기] [개수]로 초기화 되지 않은 데이터를 담는다. [크기]는 resb(1) resw(2) resd(4) resq(8) ex) b resw 0x2222 data영역의 데이터들은 초기 값을 알 수 있지만 bss영역의 데이터들은 초기 값이 0으로 고정된다. 그래서 용량이 줄어든다는 장점이 있다. 이제 메모리의 데이터를 레지스터에 넣을 수 있는지 테스트해보자. 먼저 data에 크기가 다른 변수 a,b,c,d를 만들었다. 그리..
[어셈블리] 레지스터 기초 프로그램의 실행에 가장 핵심적인 역할을 하는 3총사로 ALU, 레지스터, 메모리가 있다. 레지스터는 메모리와 하드디스크에 비해 ALU와의 거리가 가장 가깝기 때문에 접근속도가 가장 빠르다. 그래서 ALU에서 계산을 한 데이터를 임시적으로 저장한다. 레지스터는 저장할 데이터에 따라 쪼개서 저장하는데 데이터의 크기에 따라 위 이미지처럼 공간의 명칭이 다르다. mov A, B 는 B를 A에 입력한다. 위의 경우 0x1234를 a 레지스터의 32비트 공간에 입력한다. 0x12345678을 b 레지스터의 64비트 공간에 입력한다. 0xff를 c 레지스터의 8비트 공간에 입력한다. 0x00을 a 레지스터의 8비트 공간에 입력한다. d 레지스터의 64비트 데이터를 a 레지스터의 64비트 공간에 복사한다.
[C++] 음수를 비트로 표현하는 방법(2의 보수), 진법 표현 비트는 0과 1로 조합되는 데이터를 나타내는 최소 단위이다. 8비트면 -128 ~ 127까지의 정수를 표현할 수 있다. 1번째 자리부터 7번째 자리까지는 양의 정수를 표현하지만 8번째 자리의 비트가 1이 되면 마이너스가 붙는다. 01111111은 127이지만 10000000은 -128이 된다. 여기에 2~8번째 자리의 비트값을 더해서 계산한다. 이 경우는 1바이트일 때 이야기이고 데이터 크기가 커져도 동일하게 최상위 비트가 1이 되면 마이너스가 붙는다. 원래 데이터에 마이너스만 붙이는 방법은 2의 보수를 이용하는데, 1의 보수(1인 비트는 0으로 , 0인 비트는 1로 반전한 후)에 1을 더해준다. ex) 01001010 => 10110101 + 1 => 10110110 1의 보수라고 부르는 이유는 각 자..
[C++] RAII C++는 가비지 컬렉터가 없기 때문에 메모리 관리를 잘해야 한다. 메모리 관리를 쉽게 해주는 디자인 패턴이 RAII (Resource Acquisition Is Initialization)이다. C++에서는 객체를 힙 영역에 동적으로 할당하면 Scope를 벗어나도 스택에서 포인터만 소멸할 뿐이지 힙 영역에 할당된 메모리는 그대로 남는다. 하지만 RAII는 프로그램이 해당 객체의 Scope 범위를 벗어날 경우 메모리를 해제한다. 스택에 할당된 객체들은 모두 소멸자를 호출하는 것을 이용해서 Scope를 벗어나면서 소멸자를 호출해 delete로 동적할당된 메모리를 해제하는 것이다. 이러한 방식을 이용한 포인터 객체가 스마트 포인터이다.
[Unreal] Unfallen 플레이 영상
[Unreal] BTTaskNode에서 ExecuteTask, TickTask 사용법 BTTaskNode는 Behavior Tree에서 사용된다. BTTaskNode는 ExecuteTask로 한번 실행되고 TickTask는 FinishLatentTask가 실행될 때까지 매 틱마다 실행된다. 함수들은 EBTNodeResult를 반환하고 EBTNodeResult의 종류는 Succeded,Failed,InProgress,Aborted 4가지가 있다. EBTNodeResult::Type UMyBTTask::ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) { if (!OwnerComp.GetAIOwner()) { return EBTNodeResult::Failed; } //Do logic here return EBTNodeRes..