크리에이티브 커먼즈 라이센스

홈페이지HOME

PHP

JavaScript

HTML

CSS

드롭다운메뉴

제로보드4

도   움   말

백지 건강강좌/자가임상체험

물박사(자가면역질환...)^미러

전동명(천연물질사전)^미러

竹田 장승옥(블로그)^글목록

계산환산(계산기)^ 단위변환

관주성경 TTS 일반파일 TTS

바이블로 Bible_ro 다운로드

다운로드>폰에 복사
>파일선택...설치됩니다.

[도움말 보기] 바로가기

개선 요구, 충고는
아래 관리자 연락
전화/메일 부탁 드립니다.
최대한 빨리 처리하고
업데이트 올리겠습니다.

asm_06.

(루프)



프로그래밍 언어도 하나의 언어입니다.

언어란 하나의 약속입니다.

우리가 약속을 모를 때 우리는 전혀 무능한 사람입니다.

그러나 일단 약속을 알고 나면 우리는 유능한 사람이 됩니다.

우리는 외국 사람들과 대화하기 위하여, 그 외국 사람들 사이의 약속인 해당 외국어를

열심히 배웁니다.

프로그래밍 언어를 배우는 것은 확실히 그보다 쉽습니다.




제 06 장  루프(Loop)

앞에서 우리는 캐리 플래그를 통한 비트 회전을 알아 보았다.

이제 그와 달리 어떤 명령 또는 명령들을 반복해서 실행하기 위하여 사용할 수

있는 루프라는 명령에 관해서 알아 보기로 하자.


제 1 절  순환문

다른 언어에도 일정한 구역의 명령들을 반복 실행하는 순환문이 있다.

디버그에서는 Loop 명령으로 순환 실행문을 만들 수 있다.


1.  예제 프로그램 작성

먼저 루프 명령을 이용한 간단한 프로그램을 하나 만들어 보자.

순환문을 이용하면, 앞에서 우리가 지루하게 실행했던 비트 회전을 훨씬 더 손쉽게

실행할 수 있으며 레지스터 값의 변화도 일일이 눈으로 확인할 수 있다.


     ...> debug <Enter>

     - a 100 <Enter>

     ????:0100mov bx,

    3c5d <Enter>

     ????:0103mov cx,

    0011 <Enter>

     ????:0106rcl bx,

    1 <Enter>

     ????:0108loop0106

    <Enter>

     ????:010Aint 20

    <Enter>

     ????:010C <Enter>

     -





2.  명령 하나씩 실행

위의 프로그램을 정확하게 만들었으면, t <Enter> 명령을 계속하여 보자.

실행 회수와 실행 결과를 간단히 정리하면 다음과 같다.

지면 관계로 화면 표시는 생략하니 각자 실행하여 확인해 보기 바란다.


    # t 1 = bx 레지스터에 3c5d가 저장됨

    # t 2 = cx 레지스터에 0011(10진수 17)이 저장됨

    # t 3 = bx 레지스터 값이 1 비트 왼쪽으로 회전하여 레지스터 값이 변함

    # t 4 = 순환 명령으로 위의 rcl bx,1<Enter> 명령으로 되돌아감

    # t 5 = bx 레지스터 값이 1 비트 왼쪽으로 회전하여 레지스터 값이 변함

    # t 6 = 순환 명령으로 위의 rcl bx,1<Enter> 명령으로 되돌아감

    .......................................................


위에서 # t 3, # t 4 과정이 5와 6, 7과 8 등 계속하여 반복되게 된다.

그러면서 bx 레지스터의 값은 계속 변하는데, 비트 회전은 화면에 보이지 않는

2진수로 이루어지고 화면에는 16진수로 변환된 값만 출력된다.

그러나 그 변화를 분명히 확인할 수 있는 기회가 2 번은 있다.

먼저 비트 회전 명령이 8 번 실행된 후에는 bx 값이 5d??이 된다.

다음으로 비트 회전을 17 번 실행하고 나면 bx 값이 원래대로 3c5d가 된다.

실행해서 그대로 되는지 확인해 보기 바란다.

왜 그렇게 되는지 이해가 되지 않으면, 앞 장에서 설명한 내용을 다시 보라.

t <Enter> 명령의 결과 보이는 레지스터 상태 보고서 셋째 줄에서 다음에

실행될 명령이 int 20으로 보이면 더 이상 실행하지 않는 것이 좋다.

실행 과정을 자세히 살펴 보지 않고 무심코 t <Enter>만 계속하다 보면,

위 프로그램이 끝난 후 메모리의 다른 번지에 다른 프로그램이 남겨 두었던 엉뚱한

명령이 실행되어 예기치 못한 결과를 초래할 우려가 있기 때문이다.




3.  바이트 회전과 워드 회전

앞에서는 바이트(2진수 8자리) 단위로 비트 회전을 시켰다.

????:0100  rcl bl,

1<Enter>

그와 달리, 이번에는 워드(16 비트) 단위로 비트 회전을 시키는 것이다.

????:0106rcl bx,

1 <Enter>

bl은 bx레지스터의 하위 2 자리 16진수이므로 8 비트임을 알 수 있을 것이다.


4.  루프 명령과 반복 회수

이 프로그램의 핵심은 뭐니뭐니 해도 loop 명령이다.

????:0108loop0106

<Enter>

위의 명령에서 loop 뒤에 나오는 0106은 어디서 온 수일까?

그것은 비트 회전 명령이 시작되는 번지를 가리키는 것임을 알 수 있다.

????:0106rcl bx,

1 <Enter>

또 한 가지 중요한 것은 loop 명령을 실행하기 전에 먼저 주가 되는 비트 회전

명령을 몇 번 반복할 것인지를 cx 레지스터에 저장해 두어야 된다.

????:0103mov cx,

0011 <Enter>




5.  반복 회수를 계산하는 방법

그러면, 위의 프로그램에서는 도대체 어떤 과정으로 반복 회수를 계산하여 정확하게

지정한 회수만큼만 실행을 해 주는 것일까?

최초의 실행 구조를 한 번 살펴 본 후, 최후의 실행을 보면 알 것 같다.

먼저 최초의 순환 실행 과정을 추적해 보자.


    # 1 = mov 명령으로 cx 레지스터에 11h(10진수 17) 저장

    # 2 = 비트 회전 명령 실행

    # 3 = loop 명령으로 11h에서 1h를 빼고 10h를 cx 레지스터에 다시 저장한

    후

    제어를 비트 회전 명령으로

    넘김


이후 비트 회전 명령이 한 번 실행될 때마다 loop 명령이 cx 레지스터의 값을

1씩 감소시키고 다시 비트 회전 명령으로 제어를 넘기는 순환 작업이 계속된다.

그러다 보면 cx 레지스터의 값은 점점 감소하여 1이 될 것이다.

그 때 마지막으로 비트 회전 명령이 한 번 실행되고 나면, loop 명령으로 1h에서

1h를 빼면 0이 되므로 이제는 비트 회전 명령으로 제어를 넘기지 않고, loop 명령의

다음 메모리 번지에서 기다리고 있는 int 20 명령으로 제어를 넘기게 된다.

이렇게 하여 loop 순환문은 그 앞의 rcl 비트 회전 명령을 정확하게 우리가 처음에

cx 레지스터에 저장해 두었던 회수만큼만 실행되도록 만드는 것이다.

간단히 정리하자면, loop 명령은 자기에게 전달된 cx 레지스터의 값에서 1h를

빼고 남은 값이 0h가 아니라면 loop 뒤에 나오는 메모리 번지로 제어를 넘겨 주지만,

그 빼고 남은 값이 0h가 되면 뒤에 나오는 다음 명령어로 제어를 넘긴다.


     ????:010Aint 20

    <Enter>


이 명령을 만나, 우리의 프로그램은 실행을 종료하게 되는 것이다.




6.  프로그램 전체를 한 번에 실행

위에서는 우리의 프로그램을 t <Enter> 명령으로 하나의 명령어씩 차례로

실행하여 과정에서 어떤 변화가 일어나는지 자세히 관찰해 보았다.

그와 달리 프로그램 전체를 한 번에 실행하려면 g <Enter> 명령을 사용한다.

먼저 ip 레지스터를 100h로 맞추어 두고 시작하는 것을 잊지 말자.


     - r ip <Enter>

     ip ????

     : 100 <Enter>

     - r <Enter>

     ................(1)

     - g <Enter>

     ................

     - r <Enter>

     ................(2)

     -


실행 전후에 각각 r <Enter> 명령으로 레지스터 상태를 살펴 보자.

그리하여 위 (1)과 (2)에 나오는 레지스터 상태를 비교해 보자.

그러면 프로그램의 실행 후 모든 레지스터가 원래와 같음을 알게 될 것이다.

왜 그런가?

디버그는 g <Enter> 명령을 받으면, 그 명령을 실행하기 전에 모든 레지스터의

값을 보존해 두었다가 모든 명령을 실행하고 나서 int 20h 명령어를 만나면 모든

레지스터의 원래 값을 복구해 주기 때문이다.

t <Enter> 명령을 사용하여 명령어 하나씩을 반복 실행하느냐, 아니면 g

<Enter> 명령으로 프로그램 전체를 한꺼번에 실행하느냐 하는 결정은 사용자가

할 일이다.

우리는 이 프로그램이 우리가 원래 bx 레지스터에 저장해 둔 값을 어떻게 변화시키느냐에

관심이 있으므로 힘이 들지만 t <Enter> 명령을 사용하였다.




제 2 절  2진수 출력

비트 회전으로 2진수의 왼쪽부터 1 자리씩 캐리 플래그에 차례로 저장하고, 캐리

플래그의 값까지 더해 주는 특수한 덧셈 명령어 adc를 이용하면 우리는 16진수를

입력하고 그 값을 2진수로 변환하여 출력하는 프로그램을 만들 수 있다.

암산으로도 2진수를 16진수로 변환할 수 있는 사람에게는 별로 요긴하지 않겠지만,

그렇다 하더라도 이 프로그램을 통해 많은 힌트를 얻을 수 있을 것이다.


1.  기본 프로그램

이론적인 설명을 먼저 하는 것은 우리의 머리를 아프게 만들기 십상이다.

먼저 베껴서라도 프로그램을 만들어 실행해 보면 재미도 붙고 휠씬 쉬워진다.

아주 초보적이지만, bl 레지스터의 16진수를 2진수로 변환하여 출력하는 기본

프로그램을 만들어 보기로 하자.


     - a 100 <Enter>

     ????:0100mov ah,

    02 <Enter>

     ????:0102mov cx,

    0008 <Enter>

     ????:0105mov dl,

    00 <Enter>

     ????:0107rcl bl,

    1 <Enter>

     ????:0109adc dl,

    30 <Enter>

     ????:010Cint 21

    <Enter>

     ????:010Eloop0105

    <Enter>

     ????:0110int 20

    <Enter>

     - g <Enter>

     00000000

     Program terminated normally

     -


위의 프로그램에서 새로운 명령어를 공부하기 전에 먼저 기억을 되살려 보자.

int 21h 명령어는 기본적으로 입출력에 관계하지만, 구체적인 작업은 ah 레지스터의

값을 참조하여 결정한다.

만약 ah 레지스터의 값이 02h라면 int 21h 함수는 dl 레지스터의 값을 출력한다.

따라서, 우리의 목적은 bl 레지스터에 저장된 2진수를 비트 회전시켜 1 비트씩

캐리 플래그에 저장하고, 그 때마다 dl 레지스터의 값을 캐리 플래그의 값과 일치시킨

후 dl 레지스터의 값을 출력하게만 하면 성공할 수 있을 것이다.

그 목적을 위하여 사용된 명령어가 adc(add with carry) 명령어이다.




2.  adc(add with carry) 명령

일반적으로 add 명령어는 add ax,bx와 같이 사용되어 두 값을 더한다.

그 결과는 다시 ax 레지스터에 저장되고 bx 값은 변하지 않는 점을 기억하리라.

우리가 새로 사용한 adc 명령어는 콤마(,)로 구분된 두 값을 더할 뿐 아니라 거기에

케리 플래그의 값까지 보태어 콤마 앞의 레지스터에 저장한다.

위의 프로그램에서 그 명령을 옮겨 두고 생각해 보자.


     ????:0109adc dl,

    30 <Enter>


이 명령은 <dl 값 + 30 + 캐리 플래그 값>을 dl 레지스터에 저장한다.

그 효과는 어떻게 나타나는지를 추적해 보자.

이 명령 직전에 dl 레지스터의 값은 0으로 지정되었다.

바로 앞의 다음 명령이 그 작업을 수행한 것이다.


     ????:0105mov dl,

    00 <Enter>


따라서 dl 값 0에 콤마 뒤의 30을 더하면 항상 30이라는 계산이 나온다.

여기에다가 캐리 플래그의 값을 더하면, 캐리 플래그 값이 0일 때는 30이 되고

캐리 플래그의 값이 1일 때는 31이 되며 그 외 다른 경우는 없다.

부록 아스키 코드표에 나오는 바와 같이, 16진수 코드값 30은 아스키 문자 0을

가리키며 16진수 코드값 31은 아스키 문자로 1을 표시함을 알 수 있다.

따라서 위의 계산으로 나온 16진수 코드값에 해당되는 아스키 문자를 출력해 보면,

캐리 플래그의 값이 0일 때는 아스키 문자 0이 출력되고 캐리 플래그의 값이 1일

때는 아스키 문자 1이 출력된다는 결론이 된다.

이런 관계로 우리는 int 21h 명령으로 캐리 플래그에 들어 있는 2진수 1 자리의

숫자와 동일한 숫자를 출력해 볼 수 있는 것이다.


     ????:010Cint 21

    <Enter>

     ????:010Eloop0105

    <Enter>


위와 같이 한 문자를 출력한 후에는 loop 명령을 만나 메모리 0105 번지로 되돌아

가며 다시 다음의 명령부터 수행하게 된다.

물론 cx 레지스터의 값이 1 이상의 값으로 넘어온 때에 한해서이다.


     ????:0105mov dl,

    00 <Enter>





3.  프로그램 실행 결과

우리의 프로그램을 실행한 결과는 위의 화면에 보이는 바와 같이, 8 차례에 걸쳐서

출력된 0을 연달아 00000000으로 출력해 주고 int 20h에서 끝났다.

원래 bl 레지스터에 16진수 00이 들어 있었으며, 그것을 2진수로 변화해 본다면

00000000이 될 것이니 목적한 대로 16진수 00의 2진수 값을 출력해 준 것이다.


4.  응용 프로그램 작성

기본 프로그램이라고 bl 레지스터에 특정한 값을 입력하지 않고 만들어 보았지만,

그 값을 만들어 넣는 것은 어려운 일이 아니다.


     ????:0105mov dl,

    00 <Enter>


위 명령 이전의 어느 줄에든 mov bl,aa <Enter>와 같이 넣어 주면 되는

것이다.

다만, 그렇게 한 경우에는 mov dl,00 <Enter> 명령의 메모리 번지가 달라진다.

따라서 루프 명령이 지적하는 번지수를 바꾸어 주어야 될 것이다.


     ????:010Eloop0107

    <Enter>


그런 단순한 변형보다는 우리가 키보드로 입력하는 16진수를 받아서 2진수로 변환해

주는 프로그램으로 만들어 보는 것이 더욱 좋을 것이다.

그 문제는 키보드 입력을 받아 들이는 방법을 먼저 알고 나서 풀어야 된다.

따라서 조금 뒤로 미루기로 하자.




5.  명령어 하나씩 실행

위에서 우리는 방금 만든 프로그램을 g <Enter> 명령으로 일괄 실행했다.

만약 t <Enter> 명령으로 한 명령씩 실행하면, 레지스터 상태가 변하는

과정, 그 중에서도 특별히 cx 레지스터의 값이 1씩 줄어드는 것을 확인할 수 있을

것이다.

지면 관계상 화면 설명은 생략하지만, 반드시 실행해 보기 바란다.

다만, 명령어 하나씩 실행할 때 주의할 점이 있다.


1) int 21h와 도스 루틴

int 21h 명령은 t <Enter>로 실행해서는 안 된다.

도스는 int 21h에 대응하여 도스에 내장된 루틴을 통해서 많은 동작을 수행한다.

따라서 int 21h와 같은 명령어가 있을 때는 t <Enter> 명령을 사용할 수

없다.

그렇다면 하나씩 명령어를 실행하는 시도는 포기해야 될 것인가?

방법은 따로 있다.


2) g <번지> <Enter> 명령

g <번지> <Enter> 명령은 go till <번지>의 뜻으로 지정한

메모리 번지 이전까지의 명령만을 실행해 주는 것임을 우리는 알고 있다.

기억이 나지 않으면 앞으로 되돌아 가서 다시 읽어 보기 바란다.

int 21h 명령을 만났을 때, 그 명령만 실행하고 다음 명령 번지에서 실행을 멈추도록

g <번지> <Enter> 명령을 사용하면 문제 없이 실행이 된다.


     ...................... INT 21

     - g 010e <Enter>

     ................................


위와 같이 g 명령과 함께 주소를 입력해 주면, 디버그는 프로그램을 실행하다가

지정된 주소에 이르러서는 실행을 중단하고 그 주소의 명령을 실행하지 않는다.




3) p <Enter> 명령

디버그에는 보다 간편하게 실행할 수 있게 해 주는 명령이 있다.

p <Enter> 명령이 그것이다.

g 명령과 달리 실행 중단점을 지정해 주지 않아도 되기 때문에 간편하다.


     ...................... INT 21

     - p <Enter>

     ................................


이렇게 다양한 방법을 구사하면서라도 하나씩 명령어를 차례로 실행해 보는 것은,

프로그램의 실행에 따라 레지스터의 상태가 변하는 모습을 직접 확인할 수 있기 때문에

우리에게 상당한 유익이 있을 것이다.

간단하게 결과만을 사용하고자 하는 일반인으로 남으려면 수고할 필요는 없다.

그러나, 무언가 내 손으로 프로그램을 만들어 다른 사람이 사용할 수 있도록 제공하는

기쁨과 보람을 느끼려면 힘든 작업을 마다 해서는 안 될 것이다.

되도록 실습 위주로 재미를 붙여 주고, 그러면서 이론적인 내용도 부담없이 이해할

수 있도록 설명해 나가고 있으니 힘을 내어 계속하기 바란다.


== 실습 문제 ==

(문제 1) 위의 프로그램을 변경하여 2진수 마지막에 그 수가 2진수임을 표시하는

영문자 b를 덧붙여 출력해 주는 프로그램으로 만들어 보라.



    ## 힌트 ##


int 21h 함수는 ah 레지스터 값이 02h일 때 dl 레지스터 값에 대응하는 아스키

문자 1 글자를 화면에 출력해 준다.

ID:
PW:

     0 분
     1 분

자유게시판

건강백과 HOME

홈페이지 HOME

조   약     HOME

생활지혜 HOME

서식양식 HOME

법원 전산양식 검색

In Na zum

비공개 HOME

백과넷 포탈 : 건강/법률(메인)/홈피/서식/조약/생활지혜

◁ 2002.9.1.~2018.8.16. ▷

관리자 연락(저작권 의심 신고) : 김병희 010-6204-4973 k8z7@hanmail.net