[ASM] 반복문

👻 반복문

특정 조건을 만족하는 동안 반복적으로 실행되는 코드를 의미한다. 어셈블리에서는 loop 명령어를 사용한다. 무한 루프에 빠지지 않으려면 제어식을 필수로 지정해줘야 한다. 이전에 배웠던 addsub를 사용해도 되지만 증감 연산자를 사용해 주는 것이 메모리 절약적인 측면에서 더 좋다.

증감 연산자

  • dec : sub와 동일
    • dec ecx 👉 sub ecx, 1
  • inc : add와 동일
    • inc ecx 👉 add ecx, 1

🌱 loop

Hello World를 10번 출력해야 한다면?

일단 loop 없이 점프 시리즈로만 만들면 이렇게 된다.

    mov al, 10
    
LABEL_LOOP:
    PRINT_STRING msg
    NEWLINE
    dec al
    cmp al, 0
    jne LABEL_LOOP

    xor rax, rax
    ret
section .data
    msg db 'Hello World', 0x00

이전 시간에 배웠던 라벨을 이용해서 범위를 지정해주고 인덱스를 비교하면서 0이 될때까지 점프하여 반복하는 것이다.

loop라는 명령어를 사용하면 ecx에 반복 횟수를 넣어 자동으로 1씩 감소시키며 알아서 반복이 되다 빠져나오게된다. 단, PRINT_STRING이나 PRINT_DEC같은 매크로를 루프 내부에 사용하게 되면 short jump is out of range라는 에러가 나게되는데, 이는 loop가 점프할 수 있는 길이가 정해져있다는 뜻이고 해당 매크로가 의도치않게 점프할 주소값을 멀리 이동시켜버려 이러한 결과가 나오게 되는 것이다.

그래서 위의 예제로는 loop문을 만들 수는 없고, 다른 예제를 통해 loop문을 만들어보기로 하자.

1에서 100까지의 합을 구해서 출력하라.

이번에는 loop를 사용하여 구현해보자.

    mov ecx, 100
    xor ebx, ebx    ; 0으로 초기화
LABEL_LOOP_SUM:
    add ebx, ecx
    loop LABEL_LOOP_SUM
    
    PRINT_DEC 4, ebx
    NEWLINE

결과값은 5050으로 나온다는 것을 알 수 있다.

위의 예제는 loop 없이 구현 가능하다.

mov eax, 100 ; 최종 목적지
  xor ebx, ebx ; mov ebx, 0 / ebx : 결과물
  xor ecx, ecx
  
LABEL_SUM:
  inc ecx ; add ecx, 1과 동일
  add ebx, ecx
  cmp ecx, eax
  jne LABEL_SUM
    
  PRINT_DEC 4, ebx
  NEWLINE

👻 글을 마치며

이번 시간에는 어셈블리어로 반복문을 나타내는 방법에 대해 알아보았다. loop라는 명령어도 있지만 점프를 하는 데에 범위 제한이 있어 print와 관련된 매크로들을 사용할 수 없어서 아쉬웠다. 그래도 loop를 쓰지 않고도 사용하는 방식이 크게 불편하지 않아서 반복문의 내용에 따라 알맞게 사용하는 게 좋을 것 같다.


소스코드 보러가기


출처
인프런 Rookies님 강의

Leave a comment