본 게시물은 책 게임처럼 쉽고 재미있게 배우는 어셈블리 언어 튜토리얼 - 북스 홀릭 - 책을 참고하였습니다.\
IF문 구현해보기
1. CMP, JMP 계열 명령어 이해하기
CMP dst, src
dst를 중심으로 src와 비교 연산 수행
연산 결과는 플래그 레지스터에 저장
결과는 jmp명령문과 연결되어 사용
JMP 계열 명령어 (플래그 레지스터의 플래그를 보고수행)
JE /JNE label : 같거나 / 같지 않다면 label로 Jump (dst == src , dst != src)
JG/JGE label : 크거나 / 크거나 같으면 label로 Jump (dst > src, dst >=src )
JL / JLE label : 작거나 /작거나 같으면 label로 Jump (dst < src, dst <= src )
JMP labe : label로 무조건 jump
C :
ax = 10;
bx = 20;
if(ax == bx)
{
cx= 50;
}else
{
cx = 0;
}
printf(cd);
%include "io64.inc"
section .text
global CMAIN
CMAIN:
mov ax, 10
mov bx, 20
cmp ax, bx
je N_equal
mov cx, 0
jmp N_end
N_equal:
mov cx, 50
N_equal:
PRINT_DEC 2, cx
xor rax, rax
ret
FOR문 구현해보기
mov ECX , 반복횟수
label :
<< 반복내용 >>
LOOP label
- 반복 블록 내에서 ECX 레지스터는 절대 사용 금지
- LOOP 라벨 명령어에 도착시 EXC 값은 1감소 , ECX 값이 0이면 블록을 종료 , 그렇지 않으면 라벨에서 다시 실행.
%include "io64.inc"
section .text
global CMAIN
CMAIN:
mov ax, 0
mov cx, 100
L1 :
add ax, cx
loop L1
PRINT_DEC 2, ax
xor rax, rax
ret
INC para
PARA : 1E 더할 곳의 주소 (reg , mem)
DEC para
para : 1 감소 시킬 곳의 주소 (reg, mem )
WHILE 구현
%include "io64.inc"
section .text
global CMAIN
CMAIN:
mov ax, 0
mov bc, 0
L1:
cmp bx, 10
jg L2
add ax,bx
inc bc
jmp L1
L2:
PRINT_DEC 2,ax
NWELINE
xor rax, rax
ret
배열 선언과 메모리 구조
초기값의 유무로 변수 선언 방법이 나누어 짐
section .bss (c초기 값이 없는 배열 변수 )
변수이름 <예약 데이터 타입 > < 배열 개수 >
section .data (초기 값이 있는 배열 변수 )
변수이름 < 데이터타입> <배열 개수의 값>
변수이름 TIMES 변수개수 데이터 타입 초깃값
- INDEX 로 배열 요소에 접근할 때 주의점
1. 반드시 메모리값으로 접근
- 접근 주소 = 시작주소 + 배열인덱스 * 데이터타입 바이트 크기 .
모듈화
프로시저 : procedure OR 서브루틴
프로시저 선언
프로시저 이름:
.....
ret
< section .text 에서 프로시저를 선언하고 section . text에서 호출 >
< ret 명령어는 일종의 jmp 문 >
프로시저 사용
call 프로시저 이름
.
section .data, section .bss 등의 변수들은 모든 프로시저에서 접근 가능하며 공유된다.
라벨의 이름은 모든 프로시저에서 인신되는 전역 범위이기 때문에 동일한 이름의 라벨이 2개이상의 프로시저 내에서 존재할 수 없다 .
스택에 자료 넣기
- PUSH para : para는 넣고자 하는 자료값으로 2byte 또는 8byte크기의 상수값 또는 레지스터
- para가 상수인경우 크기를 명시적으로 표시해주어야 한다.
자료 뺴기
- POP para : para는 저장된 자료를 받을 곳 2 , 8 byte 크기의 레지스터 또는 메모리.
-para가 메모리인 경우 크기를 명시해야함
* 스택은 메모리 영역에서 일정 크기의 특별한 배열 변수로 생각.
< 마지막 인덱스 부터 앞으로 즉 주소의 높은쪽에서 낮은쪽으로 사용 >
PUSH 의경우 높은 주소에서 낮은 주소로 이루어짐, POP은 그반대 방향으로 연산이 진행.
RSP 레지스터 : 어디 까지 작업했는지 기억하기 위한 레지스터 [ (RSP ) STACK POINTER.]
- PUSH - RSP 레지스터 주소값 데이터 크기 만큼 감소
- POP - RSP 레지스터 주솟값 데이터 크기 만큼 증가
PUSH시 RSP 값 감소 POP시 RSP값 증가
** STACK , - 임시로 로컬 저장소가 필요할 때 사용한다.
- 자체적으로 프로시저를 사용할 때 cALL RET명령어 ) 돌아갈 주소를 잠시 저장하기 위해 사용한다.
** Stack 을 다룰때 유저가 push한 수와 pop한 수를 일치해 야한다 - 주솟값과 그에 대한 내용과 관련이 돼어 있을것 -
프로시저에 스택을 이용하여 파라미터 전달
스택에 파라미터 push -> 서브 프로시저 호출 -> 서브 프로시저에서 파라미터 꺼내어 사용
[ POP 또는 스택 포인터를 이용하여 데이터에 접근 ]
호출 규약 ( Calling Convention) : 파라미터 전달과 결과를 반환받는 서브 프로시저의 운영방식 이다.
C의 경우 : pop을 사용하지 않고 스택 포인터를 이용하여 파라미터에 직접 접근한다.
RBP( BASE POINTER ) : 범용 레지스터와 함께 주솟값을 가지고 연산할 때 사용되는 레지스터이다.
매크로
매크로 함수 선언
%macro <함수이름> <파라미터 개수>
...
%endmacro
매크로 파라미터 사용
%1 : 1번째 파라미터
%2 : 2번째 파라미터
매크로 함수 사용하기
= 매크로 함수 이름 : para1, para2, para3
매크로 함수를 별도 파일에 정의하고 사용하기.
%include "파일 이름"
상수 선언
equ 숫자 상수 선언
<상수 이름> equ <정의값>
도중 변경 불가능
%assign 숫자 상수 선언
%assign <상수 이름> <정의값>
도중에 값을 변경하는 재 선언이 가능
%define 숫자 또는 문자열 상수 선언
%define <상수 이름> <정의값>
도중에 값을 변경하는 재 선언이 가능.
'programming > assembly' 카테고리의 다른 글
어셈블리언어 기초 파해처 보기 - 5 (0) | 2020.10.25 |
---|---|
어셈블리언어 기초 파해처 보기 - 3 (0) | 2020.10.23 |
어셈블리언어 기초 파해처 보기 - 2 (0) | 2020.10.23 |
-어셈블리언어 기초 파해처 보기 - 1 (0) | 2020.10.23 |