레지스터와 어셈블리어 기초 산술 연산

코딩 파인애플·2026년 8월 4일

코딩

목록 보기
3/4
post-thumbnail

안녕하십니까 코딩 파인애플입니다
이번 시간에는 레지스터와 어셈블리어 기초 산술 연산에 관해 알아보겠습니다.

레지스터란? 🥀🥀🥀

레지스터(register)는 중앙처리장치(CPU) 내부에 있는 저장장치를 의미합니다
CPU가 연산을 수행하려고 하면 필요한 데이터를 먼저 레지스터에 저장해야 합니다.

범용-레지스터

다음은 x86-64에서 사용하는 주요 레지스터입니다

레지스터주요 역할
rax연산 결과나 함수의 반환값 저장
rbx일반적인 데이터 임시 저장
rcx반복 횟수나 특정 연산의 횟수 저장
rdx곱셈·나눗셈 또는 함수 인자 전달에 사용
rsi데이터를 옮길 때 원본 주소를 가리킴
rdi데이터를 옮길 때 목적지 주소를 가리킴
rsp현재 스택의 가장 위쪽 위치를 가리킴
rbp현재 함수가 사용하는 스택 영역의 기준 위치
rip현재 또는 다음에 실행할 명령어의 위치를 가리킴

(천천히 외워도 좋습니다)

🔣 세그먼트-레지스터

세그먼트 레지스터는 메모리 영역을 구분하기 위해 사용됩니다

레지스터의미
cs코드가 저장된 영역
ss스택이 저장된 영역
ds일반 데이터가 저장된 영역

🚩 플래그-레지스터

플래그 레지스터는 연산 결과의 상태를 기록합니다

예를 들어 두 숫자를 더한 결과값이 0인지, 음수인지, 범위 초과인지 등을 저장합니다.

플래그의미
CF부호 없는 숫자에서 자리 올림 또는 범위 초과가 발생하면 1.
ZF연산 결과가 0이면 1.
SF연산 결과의 최상위 비트가 1이면 1, 음수인지 확인하는 데 쓰임.
OF부호 있는 숫자의 연산 결과가 표현 범위를 넘으면 1.

CF와 OF의 차이 🌊🌊🌊

CF와 OF는 부호가 있냐 없냐에 따라 범위 초과를 알립니다
예를 들어 8비트 부호 없는 숫자는 0~255까지 표현할 수 있습니다

여기서 255+1이 되면 256이 되는데
8비트로 부호 없는 숫자로 256를 표현할 수 없으므로 CF가 설정됩니다

반면 8비트 부호 있는 숫자는 -128~127까지 표현할 수 있습니다
여기서 127+1이 되면 128이 되는데
8비트 부호 있는 숫자로 128을 표현할 수 없으므로 OF가 설정됩니다

어셈블리어의 기초 산술 연산 🥀

어셈블리어의 기본 연산은 크게 다음과 같이 나눌 수 있습니다

1️⃣ 데이터 이동 연산
2️⃣ 산술 연산
3️⃣ 논리 연산
4️⃣ 비교 연산
5️⃣ 분기 연산

1. 데이터의 이동 연산 ⬆️

데이터 이동 연산은 값을 레지스터나 메모리로 옮기는 연산을 의미합니다
C언어로 비유하면 '='이 있겠습니다

대표적인 명령어는 mov, push, pop 등이 있습니다

mov

mov는 값을 복사하여 다른 위치에 저장하는 명령어입니다

기본 구조는 다음과 같습니다

mov 목적지, 원본

만일 mov rax, 10일 경우 rax = 10이 되겠습니다

또한 mov rax, rbx라면 rax = rbx 정도로도 볼 수 있겠습니다.

+ 리버싱을 하다 보면 lea이라는 것도 자주 볼 수 있는데 이는 주소 계산을 수행하는 mov라 보시면 편합니다

push

push는 값을 스택에 저장하는 명령어입니다

push rax라면 "rax라는 값을 스택에 저장한다"가 되겠습니다

pop

pop는 스택의 가장 위에 있는 값을 꺼내는 명령어입니다

pop rax라면 "스택의 가장 위에 있는 값을 꺼내 rax에 저장한다" 가 되겠습니다

2. ➕➖산술 연산➗✖️

산술 연산은 숫자를 더하거나 빼고, 곱하거나 나누는 연산을 의미합니다

대표적인 명령어로는 add, sub, inc, dec, mul, imul, div, idiv가 있습니다

add➕

add는 두 값을 더하는 명령어입니다

기본 구조는 다음과 같습니다

add 목적지, 원본

만일 mov rax, 10 add rax, 5라고 할 경우
rax=10;
rax+=5; 연산과 같다고 볼 수 있겠습니다

또한 다른 레지스터의 값을 더할 수도 있습니다

mov rax, 10
mov rbx, 20
add rax, rbx

sub➖

sub는 첫 번째 값에서 두 번째 값을 빼는 명령어입니다.

sub 목적지, 원본

예...그냥 -(마이너스) 입니다 마이너스.

inc➕➕

inc는 값을 1 증가시킵니다

mov rax, 5
inc rax

위 예시 처럼 rax=5라는 값을 inc을 통해 1 증가시켜 rax는 6이 됩니다
c언어로 비유하자면 rax++; 정도 되겠습니다

dec➖➖

dec는 값을 1 감소시킵니다

mov rax, 5
dec rax

마찬가지로 rax=5라는 값을 dec을 통해 1 감소시켜 rax는 4가 됩니다
c언어로 비유하자면 rax--; 정도 되겠습니다

mul➗

mul은 부호 없는 숫자의 곱셈을 진행해주는 명령어입니다

mov rax, 5
mov rbx, 3
mul rbx

을 진행하여 rax는 15의 값을 가집니다
(참고로 mul은 항상 rax을 피연산자로 사용합니다)

imul➗

imul은 부호 있는 숫자의 곱셈을 진행해주는 명령어입니다

mov rax, -5
imul rax, 3

을 진행하여 rax는 -15의 값을 가집니다

div✖️

div는 부호 없는 수자의 나눗셈을 진행해주는 명령어입니다
나눗셈에서는 일반적으로 rdx와 rax를 함께 사용합니다

mov rax,10
mov rdx,0
mov rbx,3
div rbx

보편적으로
rax = 몫, rdx = 나머지 으로 사용됩니다
따라서 결과는 다음과 같아집니다
rax = 3, rdx = 1

idiv✖️

idiv는 부호 있는 숫자의 나눗셈을 진행해주는 명령어입니다
div와 사용 방법은 비슷하지만 음수를 처리할 수 있습니다

3. 논리 연산👾

논리 연산은 데이터를 비트 단위로 계산하는 연산입니다

대표적인 명령어로는 and, or, xor, not이 있습니다

and &&

and는 두 비트가 모두 1일 때만 결과값을 1로 만듭니다
반대로 한 비트라도 0이면 결과값은 0이 됩니다

0 AND 0 = 0
0 AND 1 = 0
1 AND 0 = 0
1 AND 1 = 1

만일 rax = 1101, rbx = 1011 일 경우.
and rax, rbx을 하게 된다면

rax = 1001이 됩니다.

또한 and는 특정 비트만 남기고 나머지 비트를 제거할 때 자주 사용됩니다

or ||

or는 두 비트 중 하나라도 1이면 결과값을 1로 만듭니다
반대로 두 비트 전부 0이면 결과값은 0이 됩니다

0 OR 0 = 0
0 OR 1 = 1
1 OR 0 = 1
1 OR 1 = 1

만일 rax = 1100, rbx = 0011 일 경우.
or rax, rbx을 하게 된다면

rax = 1111이 됩니다

xor ^

xor는 두 비트가 서로 다르면 1, 같으면 0이 됩니다

0 XOR 0 = 0
0 XOR 1 = 1
1 XOR 0 = 1
1 XOR 1 = 0

만일 rax = 1100, rbx = 1010 일 경우.
xor rax, rbx을 하게 된다면

rax = 0110이 됩니다

또한 레지스터를 0으로 초기화할 때 자주 사용합니다

not ❗❗❗

not은 모든 비트를 반대로 바꿉니다

C-MOON


즉, 0은 1로 바뀌고, 1은 0으로 바뀝니다
만일 rax = 1010 일 경우
not rax을 하게 된다면

rax = 0101이 됩니다

4. 비교 연산⚖️⚖️⚖️

비교 연산은 두 값을 비교하여 플래그 레지스터를 설정하는 연산입니다

대표적인 명령어는 cmp와 test가 있습니다

cmp

cmp는 두 값을 비교하는 명령어입니다

cmp 값1, 값2

내부적으로는 다음과 같은 계산을 수행합니다

값1 - 값2

하지만 계산 결과를 저장하지 않고 플래그만 설정합니다
만일 mov rax, 10 cmp rax, 10 일 때
내부에서는 10 - 10 = 0 을 계산하여 결과가 0이므로 ZF는 1로 설정되고 참이 되는 겁니다
하지만 만일 ZF가 1이 아니라면 그 결과는 거짓이 됩니다

참고로 cmp는 이후에 나오는 조건 분기 명령어와 함께 사용됩니다

test

test는 두 값을 AND 연산한 뒤 결과를 저장하지 않고 마찬가지로 플래그만 설정합니다
test rax, rax라고 할 경우 rax 와 자기 자신을 and 연산합니다

만일 rax가 0이라면 결과도 0이므로 ZF가 1이 되고
따라서 다음과 같이 사용할 수 있습니다

test rax, rax
jz zero

cmp와 test의 차이점?

cmp와 test 겉보기엔 둘 다 피연산자를 변경하지 않고 플래그만 남긴다는 공통점이 있습니다

하지만 cmp는 연산을 뺄셈으로 진행하므로 주로 두 값의 대소/일치 비교에 쓰이고

test의 경우 and 기반이기에 (a & b) 특정 비트가 켜졌는지 혹은 값이 0인지 확인하기 위해 쓰이는 차이점이 존재합니다.

5. 분기 연산🔀

분기 연산은 어셈블리어에서 프로그램의 흐름을 제어하는 연산입니다

대표적인 명령어는 jmp,je,jne,jg,jl이 있습니다.

jmp (jump)

jmp는 무조건 분기하는 명령어입니다 어떠한 경우에도 따지지 않고 지정된 주소로 이동합니다
jmp 1 ; 1번 코드로 점프
C언어로 비유하면 return 1이 있겠습니다

je (jump if equal)

je는 두 값이 같으면 점프합니다

cmp rax, rbx
je 1 ; rax와 rbx의 값이 같으면 점프

jne (jump if not equal)

jne는 je와 반대로 직전 비교한 값이 다르면 점프합니다

cmp rax, rbx
jne 1 ; rax와 rbx의 값이 다르면 점프

jg (jump if greater)

jg는 두 피연산자 중 첫 번째 값이 더 크면 점프합니다
C언어로 비유하자면 if (rax > rbx) 와 같은 의미가 되겠습니다

jl (jump if less)

jl는 jg와 반대로 첫 번째 값이 더 작으면 점프합니다
if (rax < rbx) 와 같은 의미입니다

그 외의 분기문 명령어들

  • jnz (jump if not zero) : 결과가 0이 아니면 점프
  • jz (jump if zero) : 결과가 0이면 점프
  • jle (jump if less or equal) : 작거나 같으면 점프
  • jge (jump if greator or equal) : 크거나 같으면 점프
  • js (jump if sign) : 음수이면 점프
  • jns (jump if not sign) 음수가 아니면 점프

간단 테스트

간단하게 3문제 정도 테스트해보도록 하겠습니다
(정답은 댓글에)

1. 조건 분기 

0x401000:  b8 05 00 00 00       mov    eax, 0x5
0x401005:  83 f8 03             cmp    eax, 0x3
0x401008:  7e 05                jle    0x40100f
0x40100a:  b8 01 00 00 00       mov    eax, 0x1
0x40100f:  c3                   ret

최종 eax 값은? (여기서 ret은 c언어에서 return과 같다)_



2. lea 과 mov

0x401000:  48 8d 47 08          lea    rax, [rdi + 0x8]
0x401004:  48 8b 0f             mov    rcx, [rdi]
0x401007:  48 8b 57 08          mov    rdx, [rdi + 0x8]

rax,rcx의 값은? (단 rdi = 0x404000, 그 주소의 8바이트 내용은 0x00000000deadbeef.)



3. 연산

0x401000:  b8 0a 00 00 00       mov    eax, 0xa
0x401005:  bb 03 00 00 00       mov    ebx, 0x3
0x40100a:  01 d8                add    eax, ebx
0x40100c:  83 c0 05             add    eax, 0x5
0x40100f:  29 d8                sub    eax, ebx
0x401011:  c3                   ret

ret 직전의 eax 값은?







이상으로 글을 마치겠습니다 감사합니다


















🍪🍪🍪🍪💀💀💀💀🥀🥀🥀🥀🥀🥀🥀🥀🥀
profile
안녕하떼요취미로콤푸타배우는고든학교6학년유치원생이빈다주말재외하고(러블럭스해야대요💢💢)주중연재하고안한날애눈이월(February)됨니다(안할수도있음)

1개의 댓글

comment-user-thumbnail
2026년 8월 5일
  1. 1
  2. rax = 0x404008 (주소 계산만), rcx = 0x00000000deadbeef (0x404000의 내용)
  3. 20
답글 달기