[Assembly] 01 (기본 상식, 데이터, 레지스터)

dev.kelvin·2024년 7월 1일

Assembly

목록 보기
1/5
post-thumbnail

1. 환경설정

개발 환경은 SASM을 기반으로 설명

HelloWorld를 어셈블리 언어로 출력하는 코드

%include "io64.inc"

section .text
global main
main:
    ;write your code here
    
    PRINT_STRING msg
    
    xor rax, rax
    ret

section .data
    msg db 'Hello World', 0x00

(PRINT_STRING은 SASM에서 사용하는 명령어이다)

SASM에서는 F9로 Build and Run이 가능하며, Ctrl+Shift+E로 exe File 생성이 가능하고
, Ctrl+F9는 에러체크 build가 가능하다, 생성된 exe File은 cmd창에서 그대로 사용이 가능하다

F5로 디버깅모드, F10으로 한줄 한줄 디버깅도 가능하다

SASM에서 ;는 주석처리이다

다음은 윈도우 실행파일 구조를 나타낸 그림이다

Section(".text")에는 작성한 코드가 포함되고 Section(".data")에는 말 그대로 data들이 포함된다 (위에서는 msg db 'Hello World')

이러한 실행파일을 실행하면 오른쪽 그림과 같이 메모리에 올라가게 된다

다음은 컴퓨터 구조를 나타낸 그림이다

하드디스크, 메인 메모리의 가장 큰 차이점은 전원을 껐을 때 하드 디스크의 데이터는 보존되고 메인 메모리의 데이터는 날아간다는 점이다 추가로 메인 메모리는 하드 디스크에 비해 CPU 접근 속도가 빠르다

예를들어 게임을 설치하고 실행한다고 가정하면 실행 파일이 생성되고 해당 실행파일은 메인 메모리에 올라가게 된다


어셈블리 언어는 프로그래밍 언어중 가장 low-level의 언어이다 이는 컴퓨터가 이해하기 가장 쉬운 언어라는 의미이다

2. 데이터

컴퓨터는 데이터를 어떻게 저장할까?

컴퓨터는 0,1 (bit)만 사용한다 0은 false, 1은 true이다, 이러한 비트가 8개로 구성된 것을 byte라고 한다

bit들을 켜고 끄며 값을 나타낼 수 있다 1, 2, 4, 8 16으로 2배씩 커지며 여러개를 켜면 그 수를 전부 합하게 된다

이때 음수를 나타내고 싶다면 최상위 비트를 1로 켜주면 된다 하지만 최상위 비트를 단순 - 부호만 붙히게 사용해서는 안된다

(1byte에서 최상위 비트만 켜면 -128이 나옴 -> 이를 이용해서 다른 음수를 표현할 뿐 -부호만 붙히는 개념이 아님)

인간에게 가장 직관적인 진수는 10진수고 컴퓨터에게 가장 직관적인 진수는 2진수이다
(10진수 = 0,1,2,3.., 2진수 = 0,1)


1, 2, 3...9까지 간 뒤 10이 되는 원리는 9가 최대치에 도달했으니 0으로 초기화 하고 다음 숫자인 1을 앞에 땡겨오는 원리로 10이 되는 것이다 마찬가지로 19다음은 0으로 초기화 후 2를 앞으로 땡겨와 20이 된다

이는 2진수에서 같은 방식으로 작용한다 0은 0, 1은 1이며 10은 2가 된다 이를 b (binary)를 붙혀 표현하는데 0b0은 0, 0b1은 1, 0b10은 2, 0b11은 3, 0b100은 4가 되는 원리이다


하지만 2진수를 사용하게 되면 큰 숫자를 표현하기 굉장히 어렵다 이는 16진수를 사용하여 해결할 수 있다, 16진수는 말 그대로 숫자, 알파벳을 16개를 사용한다 (0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F)

마찬가지로 적용해보면 0은 0이고 F는 15를 의미한다 그렇다면 16은 어떻게 표현할까? 같은 방식으로 0으로 초기화 후 그 다음 숫자를 앞으로 땡겨와 10이 16이 된다
16진수는 2진수에서의 binary와 같이 Hex를 사용하여 x를 사용한다
(0x10은 16)

16진수와 2진수는 서로 전환하기 편하다 예를들어 0b10010101이라는 2진수가 있다고 가정했을 때 이를 16진수로 바꾸려면 4단위로 끊어서 본다 -> 0b 1001 0101 그리고 2진수 계산으로 처리하면 된다 결국 0x95가 된다

3. 레지스터

레지스터는 어디에 사용되나?

레지스터는 위치상 cpu와 가장 가깝게 있다, 따라서 하드 디스크, ram에 비해 아주 빠른 연산을 보여준다
따라서 ALU가 연산을 하고 임시로 데이터를 저장하는 곳이 레지스터이다

다음은 레지스터를 시각화 한 그림이다

여기는 a만 있지만 b,c,d까지 사용한다

rax란 64bit 전체를 사용, eax는 32bit, ax는 16비트 등등으로 레지스터를 쪼개서 사용한다

    mov eax, 0x1234
    mov rbx, 0x12345678
    mov cl, 0xff   

mov는 데이터 복사이다
위 코드는 레지스터 eax에 0x1234, rbx에 0x12345678 데이터를 복사하라는 의미이다


(이때 cl (8bit)에 더 큰 값을 복사시키면 에러가 발생한다)

	mov rax, rdx

이런식으로 rax에 rdx레지스터 값을 복사도 가능하다


Ctrl+R로 디버그 시 레지스터를 보여줄 수 있고 Ctrl+M으로 메모리도 보여줄 수 있다

profile
GameDeveloper🎮 Dev C++, DataStructure, Algorithm, UE5, Assembly🛠, Git/Perforce🌏

0개의 댓글