카테고리

asm (27) bootloader_x86_grub (1) C (92) compile (11) config (76) CPP (13) CSS (1) debugging (7) gimp (1) Go (1) html (1) Java (1) JavaScript (1) kernel (19) LibreOffice (3) Linux system progamming (21) MFC (1) opencv (4) OpenGL (1) PHP (1) Python (4) qemu (29) shell (3) socket (7) troubleshooting (2) ubuntu18.04 (2) windows (1)

2018/12/16

asm 산술 연산


1. 산술 연산

산술 연산자를 위해 레지스터를 사용 하면, 산술 연산을 할 수 있다.

산술 연산의 형태는 일반적으로 다음과 같다.
operation register, value/register

첫 번째 레지스터가 연산의 대상입니다.

예를 들어:
add rax, 5
sub rbx, rax

수학 연산 리스트
동작 이름
동작 이름(서명)
설명
add a, b
-
a = a+b
sub a, b
-
a = a-b
mul reg
imul reg
rax = rax*reg
div reg
idiv reg
rax = rax/reg
neg reg
-
reg = -reg
inc reg
-
reg = reg +1
dec reg
-
reg = reg – 1
adc a, b
-
a = a+b+CF
add a, b
-
a = a-b-CF


2. ASCII

ASCII는 컴퓨터가 텍스트 문자열을 나타내는 방법.

컴퓨터는 숫자를 저장할 수 있으므로 ASCII는 숫자를 특정 문자 (문자, 숫자, 기호 등)에 매핑하는 방식으로 작동 한다.

ASCII7 비트 이진 코드를 사용 하여 문자를 나타낸다. 그러나 8 비트 1바이트 정보의 기본 단위 이기 때문에 현 컴퓨터는 일반적으로 8비트 코드인 확장 ASCII을 지원한다.

ASCII .

3. 숫자 화면 출력
다음은 09사이의 단일 숫자를 표시하기 위한 매우 간단한 서브루틴이다.

표시되는 숫자는 rax 레지스터에서 가져온다.

section .data
digit db 0,10

...

_printRAXDigit:
add rax, 48
mov [digit], al
mov rax, 1
mov rdi, 1
mov rsi, digit
mov rdx, 2
syscall
ret

rax 레지스터의 값은 48 씩 증가한다.
ASCII 표를 확인하면 48"0"문자 값과 매칭 되며, char형이므로 "1"문자를 표현 할 수 있다.

ASCII 코드 테이블 추가 필요
section .data
digit db 0,10
...
...

_printRAXDig:
add rax, 48 " 0을 의미 함.
mov [digit], al
mov rax, 1
mov rdi, 1
mov rsi, digit
mov rdx, 2
syscall
ret

rax 레지스터의 하위 바이트는 메모리 주소 "digit"로 이동
_printRAXDig:
add rax, 48 " 0을 의미 함.
mov [digit], al " 메모리 주소 이동
mov rax, 1
mov rdi, 1
mov rsi, digit
mov rdx, 2
syscall
ret

"digit"는 실제로 2 바이트로 정의되며, 010, 줄 바꿈 문자, 개형 문자를 의미한다. rax 레지스터의 하위 바이트를 "digit"에 로드하기 때문에 첫 번째 바이트 만 덮어 쓰며 개행 문자에는 영향을 미치지 않는다.

그런 다음 2 바이트를 화면에 출력 한다.
길이가 2로 설정되어 있기 때문에 숫자와 개행 문자가 함께 표시됨.

section .data
digit db 0, 10
...
...
...

_printRAXDigit:
add rax, 48
mov [digit], al

mov rax, 1
mov rdi, 1
mov rsi, digit
mov rdx, 2
syscall
ret

아래 서브 루틴을 사용하여 해당 숫자를 rax 레지스터에 로드 한 다음 서브 루틴을 호출하여 0-9 사이의 숫자를 표시 할 수 있다.

mov rax, 7
call _printRAXDigit
숫자 7을 화면에 출력 한다.

이러한 방법을 통해 산술 연산자를 빠르게 테스트 할 수 있다.
코드
출력
추론
mov rax, 6
mov rbx, 2
div rbx
call _printRAXDigit
3
rax = 6/2
mov rax, 1
add rax, 4
call _printRAXDigit
5
rax = 1+4


4. Stack
레지스터와 마찬가지로 스택은 데이터를 임시로 저장하는 또 다른 방법이다.
데이터를 스택(쌓기)에 저장하기 때문에 "스택"이라고 한다.

서류 더미를 상상해보자. 한 장의 용지를 다른 용지 위에 겹쳐 놓으면 지정된 시간에만 스택의 맨 위에 있는 용지의 내용을 볼 수 있다.

스택 중간에 있는 페이지는 위에 있는 페이지 전부를 제거하지 않고는 중간의 스택을 제거 할 수 없다.

push: 스택의 맨 위에 데이터를 추가.
pop :스택의 맨 위에서 데이터를 제거.
peek: 추가, 제거 없으며 스택을 볼때.


4.1 스택 동작
동작
효과
push reg/value
값을 스택에 밀어 넣는다.
pop reg
스택에서 값을 꺼내서 reg에 저장한다.
mov reg, [rsp]
regpeek(보기) 값을 저장한다.
참고: 일반적으로 레지스터를 사용할 수 있는 위치에서 포인터를 사용할 수도 있다.
"pop reg"대신 "pop [label]"을 사용하여 스택의 값을 메모리의 특정 위치로 직접 pop 할 수 있다.

4.2 push
Peek:NULL

Peek:4

Peek:8

Peek:3




3
8
3
4
4
4
Stack
Stack
Stack
Stack


4.3 pop
Peek:3

Peek:8

Peek:4


Peek:NULL




3
8
8
4
4
4
stack
Stack
Stack
Stack
rax:NULL
rax: 3
rax: 8
rax: 4


예제 코드
push 4
push 8
push 3

pop rax
call _printRAXDigit
pop rax
call _printRAXDigit
pop rax
call _printRAXDigit

출력 예상
3
8
4

댓글 없음:

댓글 쓰기