section .data
STAR db '*'
EMPTY db 0x0a
section .text
global _start
_start:
mov rax, 1
mov rdi, 1
mov rdx, 1
mov r10, 0
mov r9, [rsp + 16]
cmp r9, 0
je _done
mov cl, [r9]
movzx r9, cl
sub r9, 0x30
mov r8, r9
xor r9, r9
call _syscall
_small:
cmp r10, r9
je _up;
mov rsi, STAR ;
syscall
mov rax, 1
inc r10
jmp _small
_up:
cmp r9, r8
je _down
mov rsi, EMPTY
syscall
mov rax, 1
mov r10, 0
add r9, 1
jmp _small
_down:
cmp r9, 0
je _done
mov rsi, EMPTY
syscall
mov rax, 1
mov r10, 0
sub r9
jmp _big
_big:
cmp r10, r9
je _down
mov rsi, STAR
syscall
mov rax,1
inc r10
jmp _big
_done:
mov rax, 60
mov rdi, 0
syscall
_syscall:
syscall
ret
section .data
STAR db '*'
EMPTY db 0x0a
STAR에는 '*'을 가리키는 포인터가 들어간다.
EMPTY에는 '0x0a'가 들어가는데, 이는 아스키 코드에서 줄바꿈을 의미한다.
section .text
global _start
text 세그먼트에서는 _start 함수를 정의한다.
_start:
mov rax, 1
mov rdi, 1
mov rdx, 1
mov r10, 0
mov r9, [rsp + 16]
mov rax, 1은 write 시스템 콜을 설정한다
rdi에 1을 넣어줌으로써 정상적으로 출력할 수 있게 한다.(기본 출력 모드)
rdx에 1을 넣어줌으로써 출력 길이를 설정한다. '*', 줄바꿈 모드 길이가 1이므로..
r10에는 0을 넣어준다. 인덱스
r9는 현재 입력이 된 문자열을 찾는다.
ex) 사용자가 10을 입력하면, 이는 rsp + 16에 저장되고 r9에 넣어진다.
왜 rsp+16이냐> 스택 구조를 보면 rsp 아래에 ret 아래에 7이 쌓여 있을 거임. 내가 7에 접근하고 싶으면 8*2 = 16을 빼준 주소에 접근해야 하는 것
cmp r9, 0
je _done
r9와 0을 비교한다.(입력이 없을 경우, r9에 0이 담김)
r9와 0이 같다면 프로그램 종료
mov cl, [r9]
movzx r9, cl
sub r9, 0x30
cl은 r9가 위치한 문자열에서 오직 한 바이트만을 가져온다. (1-9사이의 층수를 가진 피라미드)
movzx r9, cl
cl에는 하나의 문자가 담겨있다. 이것을 다시 r9에 저장해준다
sub r9, 0x30
16진수 30은 문자 0을 의미한다. 만약 7을 입력했다면 r9에 0x37이 담겼겠지?
그래서 30을 빼주는 거 ㅇㅇ
mov r8, r9
xor r9, r9
call _syscall
r8에 r9 넣어주고, r9 값 초기화
(높이를 r8에 저장, r9=0)
syscall 불러오기
_small:
cmp r10, r9
je _up;
mov rsi, STAR ;
syscall
mov rax, 1
inc r10
jmp _small
피라미드에서 올라가는 부분
n=피라미드 높이=r8
i=큰 반복문=r9
j=작은 반복문=r10
r10과 r9를 비교해서 같을 경우 _up이라는 함수를 불러온다
별을 출력할 수 있도록 rsi에 STAR을 담아준다
syscall(출력)
rax에 1 넣어서 write system call 설정
r10(작은 반복문) 1 증가시킨다
jmp_small 로 자기 자신을 반복한다
_up:
cmp r9, r8
je _down
mov rsi, EMPTY
syscall
mov rax, 1
mov r10, 0
add r9, 1
jmp _small
cmp r9, r8
i==n인 경우 _down 함수를 불러온다
아직 i가 n보다 작다면 rsi에 공백 문자를 넣어주고 출력한다
출력을 했으니 다시 rax에 1 넣어서 write system call 설정해준다
r10(작은 반복문)에 0을 넣어주고
r9(큰 반복문)을 1 증가시킨다
_small로 이동한다.(다시 올라가는 피라미드에서 별 찍으려고)
_down:
cmp r9, 0
je _done
mov rsi, EMPTY
syscall
mov rax, 1
mov r10, 0
sub r9
jmp _big
r9(큰 반복문)과 0을 비교해서 같으면 _done 함수를 실행시킨다
rsi에 공백 문자를 넣어주고 출력한다
출력을 했으니 다시 rax에 1 넣어서 write system call 설정해준다
r10(작은 반복문)에 0을 넣어주고
r9(큰 반복문)을 1 감소시킨다
_big로 이동한다(다시 내려가는 피라미드에서 별 찍으려고)
_big:
cmp r10, r9
je _down
mov rsi, STAR
syscall
mov rax,1
inc r10
jmp _big
r10(작은 반복문)과 r9(큰 반복문)을 비교해서 같으면 _down(공백 문자 출력 함수)로 이동한다
별을 출력할 수 있도록 rsi에 STAR을 담아준다
syscall(출력)
rax에 1 넣어서 write system call 설정
r10(작은 반복문) 1 증가시킨다
jmp_big 로 자기 자신을 반복한다
_done:
mov rax, 60
mov rdi, 0
syscall
rax에 60 넣어서 종료 모드 설정
rdi에 0 넣어준다
syscall(프로그램 종료)
_syscall:
syscall
ret
syscall 불러오고
return