오늘 알아볼 것
- 어셈블리어란 무엇인가?
열어가는 글(어셈블리어 돌아보기)
저번 고급언어, 저급언어, 기계어를 다루는 글을 썼을때 어셈블리어를 한번 다뤘었다.
어셈블리어는 기계어와 1:1로 대응되는 기호로 이뤄진 언어라 했었다.
이번에는 이 어셈블리어에 대해 더 자세히 알아볼 예정이다.
어셈블리어란 무엇인가? (A.K.A. 기호 언어)
- 기계어에서 한 단계 위의 언어.
- 기계어와 일대일 대응이 되는 컴퓨터 프로그래밍의 저급 언어.
- CPU안에 명령어 집합체를 사용하기 때문에 아키텍처마다 어셈블리어랑 어셈블러가 다르다.
어셈블리어 명령어 종류와 기능
- mov : 데이터 이동 시에 사용.
- lea : 주소 값을 옮길 때 사용
--> 데이터 이동에 쓰이는 명령어.
- add : 레지스터나 메모리의 값을 덧셈할 때 쓰는 명령어.
- sub : 레지스터나 메모리의 값을 뺄 때 쓰는 명령어.
- dec : 값을 1 감소 시키는 명령어
- inc : 값을 1 증가 시키는 명령어.
--> 논리 연산에 쓰이는 명령어.
- cmp : 레지스터와 레지스터 값을 비교 할때 쓰는 명령어.
- jmp : 특정한 곳으로 분기시키는 명령어.
--> 흐름 제어에 쓰이는 명령어.
- call : 프로시저를 호출시키는 명령어.
프로시저(Procedure)란?
- 특정한 로직을 처리하기만 하고 결과 값을 반환하지 않는 서브 프로그램.
데이터베이스에 대한 일련의 작업을 정리한 절차를 RDBMS가 저장한 것.테이블에서 데이터를 추출, 조작하고 결과를 다른 테이블에 다시 저장하거나 갱신하는 처리를 할때 프로시저를 사용한다고 한다.
결론 - 그냥 지정된 작업을 처리하고 결과값을 반환 하지 않는 프로그램이라 생각한다.
- ret : 호출했던 프로시저를 바로 다음 지점으로 이동시키는 명령어. (call한 주소로 이동.)
--> 프로시저를 조작하는 명령어
- push : 값을 스택에 저장시키는 명령어.
- pop : 값을 스택에서 삭제시키는 명령어
--> 스택을 조작하는 명령어들
etc..
- nop : 아무것도 하지 않는다. 라는 명령어.
- LEAVE : 현재까지의 메모리 스택을 비우고 EBP를 자신을 호출한 메모리 주소로 채우는 명령어.
= 함수를 종료하기 위해 정리하는 작업에 사용.
//
4대 연산자(xor, or, and, not)
사용법 - xor, ~~
CPU내에 있는 범용 레지스터 종류 --> 다시한번 살펴보기.
범용 레지스터?
-> 논리연산, 수리연산에 사용되는 피연산자, 주소 계산 피연산자, 메모리 포인터가 저장되는 CPU 내의 공간.
- EAX(32bit 기준): 피연산자와 연산 결과의 저장소.(a.k.a. 누산기) (<=> RAX = 64bit 전용 레지스터) // 16bit에서는 AX.
- 산술연산자, 논리연산자를 수행해서 함수의 반환값이 이 레지스터에 저장된다.
- EBX : 임의의 번지 지정에 사용되는 어드레스 레지스터 (a.k.a. 베이스 레지스터)
- 메모리 주소를 저장하기 위한 용도.
- ECX : 문자열 처리나 루프를 위한 카운터(a.k.a. 카운트 레지스터)
- 반복 명령어 사용시 반복 카운터로 사용되는 레지스터. (그냥 얼마나 반복했는지 횟수 보여주는 레지스터)
- 여기에 반복할 횟수를 지정하고, 반복 작업을 수행한다 한다.
- EDX : I/O 포인터 (= Extended 데이터 레지스터)
- 부호 확장 명령 등에 쓰이는데, 큰 수의 곱셈 혹은 나눗셈 등의 연산이 이루어질 때 쓰인다.
- EAX 레지스터와 함께 쓰인다.
- ESI
- 문자열 처리에서 source를 가리킨다.
- 데이터를 조작하거나, 복사 시에 소스 데이터의 주소가 저장된다.
- EDI
- 문자열 처리에서 destination(목적지)를 가리킴.
- 복사 시에 목적지 주소가 저장된다.
- ESP : 스택 프레임(아래 더보기 참조)의 끝 지점 주소가 저장되며, push, pop 명령에 따라 ESP의값이 4byte씩 변한다고 한다.
- EBP : 스택 프레임의 시작 지점 주소가 저장되는 명령어.
- 현재 사용되는 스택 프레임이 소멸되지 않는 이상 EBP 레지스터의 값은 변하지 않는다 한다.
메모리 구조.
-> 프로세스를 5가지 논리적 기준으로 잘라낸것.

위 사진과 같이 5가지의 프레임으로 나뉘는데, 각 프레임 마다 부여되는 권한과 위치하는 데이터가 다르다.
위에서 말한 스택 프레임이 저 맨 위 상위 메모리 주소와 인접해있는 프레임을 말한다.

나중에 크게 다룰 예정.
세그먼트 '레지스터'?
-> 16bit 레지스터로 어드레스 영역을 다양한 크기로 구분하는 역할을 함.
범용 레지스터랑 다른거다. 이제 알았다.
cs, ds, ss, es, fs, gs가 있다는데 이건 어디에 쓰이는지 나중에 알아봐야겠다.
어셈블리어의 문법(접두사, 접미사, 오퍼랜드)
크게 어셈블리어는 Intel 문법과 AT&T문법으로 나뉜다.
Intel 문법 규칙
AT&T 문법 규칙
접두사
Intel 문법 - 따로 붙는 접두사가 없지만, 16진수와 2진수 데이터에는 'h'와 'b'접두사를 가진다.
AT&T 문법 - 레지스터는 '%'접두사를, 값들은 '$'접두사가 붙는다.
- mov eax,1 (32bit 기준)
- movl $1 %eax
(아니 근데 저 #은 뭐지 대체.. 구글링해도 안나온다..)
아마 $를 잘못쳐서 #으로 되었나보다.
오퍼랜드(a.k.a. 피연산자) 위치 차이.
Intel 문법 - 목적지(destination) 오퍼랜드가 앞, 원본(source) 오퍼랜드가 뒤.
AT&T 문법 - 반대.
- instr src, dest
- instr dest, src
- mov ebx, offh
- movl $0xff, %ebx
메모리 오퍼랜드
Intel 문법 - 기본 레지스터는 [ebx]와 같이 대괄호 안에 들어가는 방식.
AT&T 문법 - 기본 레지스터는 (%ebx)와 같이 소괄호 안에 들어가는 방식.
- mov eax, [ebx+3]
- movl 3(%ebx), %eax
--> 이러면 곱하기는 어떻게 나타내는가?
- mov eax,[ebx]
- movl (%ebx), %eax
근데 여기서 AT&T의 사칙연산과 같은 수행문법이 인텔문법보다 매우 보기 힘들다는 단점이 있다한다.
ex)
mov eax,[ebx+20h] - intel
movl 0x20(%ebx),%eax - AT&T
즉, ebx+20h라는걸 0x20(%ebx)라고 나타내는 AT&T가 참 복잡하다는것을 알 수 있다.
다른 예시
- instr foo,segreg:[base+index*scale+disp] - intel 문법
- instr %segreg:disp(base,index,scale).foo - AT&T 문법
- sub eax,[ebx+ecx*4h-20h] - intel 문법
- subl -0x20(%ebx,%ecx,0x4),%eax - AT&T 문법
-- 이건 진짜 이해를 못하겠다..
접미사
Intel 문법 - 접미사를 따로 사용하지 않고 의미있는 문장 그대로 사용.
ex) byte ptr, word ptr, dword ptr (dword는 long(32bit)과 같은 크기를 가짐)
AT&T 문법 - 정해진 접미사 규칙을 따르고, 각각의 접미사는 고유의 의미를 가지고 있다.
AT&T ONLY
movl/ movw / movb차이점. -> l, b, w는 mov나 push등의 명령어 뒤에 쓰이는 오퍼랜드의 크기를 지정하는 것.
'l'은 long, 'w'는 word, 'b'는 byte를 저장하기 위해 사용되는 접미사.
ex)
xxxl : 32bit 크기를 다루는 명령어 (ex. movl / pushl)
xxxw : 16bit
xxxb : 8bit
- mov eax, dword ptr[ebx]
- movl (%ebx), %eax
어셈블러 종류
- Microsoft의 MASM(Macro Assembler)
- Intel 어셈블러
- 64bit도 지원.
- 가독성이 좋다 한다.
- visual studio 2008이상부터는 기본적으로 포함되어있다 한다.
++ cross-platform은 지원되지 않는다 한다.
- GAS(GNU Assembler)
- AT&T 어셈블러.
- GCC 안에 기본적으로 사용되는 어셈블러.
- free software
++ cross-platform 지원.
cross-platform?
-> 여러 종류의 컴퓨터 플랫폼에서 동작할 수 있다는 것을 뜻하는 용어.
즉, 저 GAS는 intel syntax도 지원한다는 뜻.
- Cosmos Project 의 X#
- NASM(Netwide Assembler)
출처 및 참고 -
[리버싱] 어셈블리어 설명 및 종류
1. 어셈블리어란? 기계어와 일대일 대응되는 컴퓨터 프로그래밍 저급언어 기계어는 CPU가 직접 해독하고 실행할 수 있는 비트 단위로 쓰여 사람이 이해하기에는 어렵기에 어셈블리어를 통해 기
rninche01.tistory.com
https://yehey-study.tistory.com/7
어셈블리어 명령어와 범용 레지스터
어셈블리어 명령어 종류와 기능 mov: 데이터 이동 시에 사용 lea: 주소 값을 옮길 때 사용 add: 레지스터나 메모리의 값을 덧셈할 때 sub: 레지스터나 메모리의 값을 뺄 때 dec: 값을 1 감소 시킨다. inc:
yehey-study.tistory.com
어셈블러(Assembler)의 종류
MASM(Microsoft Macro Assembler), NASM(Netwide Assembler), FASM(Flat Assembler), GAS(GNU Assembler), YASM 등 정말 다양한 종류가 있습니다. 그럼 여기서 잠시 질문하나 드리겠습니다. 어셈블리(Assembly)는 무엇이고 어셈블
rootfriend.tistory.com
https://blog.hexabrain.net/186
범용 레지스터: EAX, ECX, EDX, ESI, EDI, ESP, EBP
1. EAX(Extended Accumulator Register) 첫번째로, EAX 레지스터에 대해 알아보도록 하겠습니다. EAX 레지스터는 산술(덧셈, 곱셈, 나눗셈 등), 논리 연산을 수행하며 함수의 반환값이 이 레지스터에 저장됩니
blog.hexabrain.net
https://blog.naver.com/PostView.nhn?isHttpsRedirect=true&blogId=ndb796&logNo=221054682271
[ 리버스 엔지니어링 ] 어셈블리어 기본 문법
실제로 복잡한 어셈블리 프로그램은 이전 시간에 다루었던 Hello World 프로그램 소스보다 훨씬 많은 명...
blog.naver.com
https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=rockcrash&logNo=220685116797
세그먼트 레지스터
- 세그먼트 레지스터(Segment Register)는 16비트 레지스터로 어드레스 영역을 다양한 크기로 구분...
blog.naver.com
https://onecellboy.tistory.com/50
AT&T Assembly Code (어셈블리어)
Linux Assembly Code 글쓴이 : 이호 (i@flyduck.com) 최신 글이 있는 곳 : http://linux.flyduck.com/ v0.1.0 2000년 3월 28일 차례 0. 서문 1. GAS와 AT&T 문법 2. Inline Assembly 3. Reference 0. 서문 이 문서는 리눅스에서 사용하
onecellboy.tistory.com
https://www.joinc.co.kr/w/Site/Assembly/Documents/article_LinuxAssemblerHowto
Linux Assembler 하우투
이 문서는 Linux에서의 어셈블리 언어 프로그래밍에 대한 내용을 다룬다. 리눅스에서는 AT&T문법을 따라는 강력한 어셈블러인 as를 제공한다. 또한 리눅스의 핵심인 gcc 컴파일러는 c로된 코드에 어
www.joinc.co.kr
'System & Reversing' 카테고리의 다른 글
어셈블리 핸드레이에 관한 고찰. (0) | 2023.03.13 |
---|---|
함수 프롤로그, 에필로그에 대한 간단한 고찰. (0) | 2023.03.13 |
컴퓨터 메모리 구조에 대한 간단하지 않은 고찰. (1) | 2023.03.12 |
CPU 아키텍쳐에 대한 간단한 고찰. (2) | 2023.03.12 |
고급언어, 저급언어, 기계어 정리. (0) | 2023.03.12 |