2750 - 수 정렬하기
정보
- 문제 보기: 2750 - 수 정렬하기
- 소요 시간: 38분 ??초
- 풀이 언어:
nasm x64 - 체감 난이도: 2️⃣~3️⃣
- 리뷰 횟수: ✅
풀이 키워드
스포주의
정렬
풀이 코드
정보
- 메모리: 4352 KB
- 시간: 0 ms
;#------------------------
;# BOJ_2750 by QPID 0.<❤️
;#------------------------
default rel
global main
extern printf, scanf
section .data
scan_fmt: db "%d", 0
print_fmt: db "%d", 10, 0
section .bss
n: resd 1
arr: resd 1000
section .text
main:
push rbp
mov rbp, rsp
;--- input ---
scan_n:
mov rdi, scan_fmt
lea rsi, [n]
xor rax, rax
call scanf
scan_arr:
xor r12, r12
scan_arr_loop:
mov eax, [n]
cmp r12d, eax ; i < n
jge bubble_sort ; i >= n then sort
mov rdi, scan_fmt
lea rsi, [arr + r12*4] ; arr[i]
xor rax, rax
call scanf
inc r12
jmp scan_arr_loop
;--- sort ---
bubble_sort:
mov r12d, [n]
dec r12d
xor r13, r13 ; idx
bubble_iloop:
cmp r13d, r12d
jge print_res
xor r14, r14 ; jdx
bubble_jloop:
mov eax, r12d
sub eax, r13d
cmp r14d, eax
jge iloop_nxt
; compare arr[j] & arr[j+1]
; ascending order
mov eax, [arr + r14*4]
mov ebx, [arr + r14*4+4]
cmp eax, ebx
jle jloop_nxt
; swap in case of eax > ebx
mov [arr + r14*4], ebx
mov [arr + r14*4+4], eax
jmp jloop_nxt
jloop_nxt:
inc r14
jmp bubble_jloop
iloop_nxt:
inc r13
jmp bubble_iloop
;--- output ---
print_res:
xor r12, r12
print_loop:
mov eax, [n]
cmp r12d, eax
jge cleanup
mov rdi, print_fmt
movsx rsi, dword [arr + r12*4]
xor rax, rax
call printf
inc r12
jmp print_loop
cleanup:
xor rax, rax
leave
ret
풀이 해설
📌 r12부터 사용하는 이유
x86-64 아키텍처에서 레지스터는 크게 두 가지 부류로 나뉜다.
Caller-saved (Volatile)
rax, rcx, rdx, rsi, rdi, r8~r11
함수를 호출하면 값이 변할 수 있는 레지스터들이다.
Callee-saved (Non-volatile)
rbx, rbp, r12, r13, r14, r15
함수 내부에서 사용하더라도, 함수가 끝나기 전 원래의 값으로 복구해 놓아야 하는 레지스터들이다. 안해도 되긴 함
r12~r14를 인덱스 카운터, 데이터 보관용으로 사용한 이유는 다음과 같다.
printf,scanf호출 시에도 데이터를 보존해야 해서- r12~r15는 외부 함수를 호출해도 값 유지가 보장되므로, 반복문의 루프 카운터를 안정적으로 유지할 수 있다.