2011년 6월 3일 금요일

asm] 어셈러브 강좌 펌 4

6.5 프로시듀어의 배치--------------------------------------------------------------------------------PROC ~ ENDP 는 사람이 보기 편하기 위한 구분에 불과하다.어셈블러는 실제로 프로시듀어를 구별하지 않는다.예제)CALL2.ASMCODE SEGMENT ASSUME CS:CODEEOF EQU 1AHSTART: CALL GETCH JC EXITP ;--+여기에서 프로시듀어를 호출하고 있다. MOV DL,AL

CALL PUTCH ;--+ JMP STARTEXITP: MOV AH,4CH INT 21HGETCH PROC MOV AH,8 INT 21H CMP AL,EOF JNE GETCHEND STC RETGETCHEND: ;긴이름의 라벨도 사용가능 그때라벨만의 행으로 해도좋다 CLC RETGETCH ENDPPUTCH PROC MOV AH,2 INT 21H RETPUTCH ENDPCODE ENDS END START ;실행시작을 알리는 문장END 문이 가지는 기능: 프로그램의 시작번지를 지정한다.이와같은것은 여러개의 코드 세그먼트를 가진 프로그램을 작성한다든지 ,프로시듀어와 메인 루틴의 순서를 바꾼 프로그램을 작성하는 경우에는 절대로 필요하다.예제)CALL2-2.ASMCODE SEGMENT ASSUME CS:CODEEOF EQU 1AHGETCH PROC MOV AH,8 INT 21H CMP AL,EOF JNE GETCHEND STC RETGETCHEND: ;긴이름의 라벨도 사용가능 그때라벨만의 행으로 해도좋다 CLC RETGETCH ENDPPUTCH PROC MOV AH,2 INT 21H RETPUTCH ENDPSTART: CALL GETCH ; 메인 루틴의 시작 <--------------------+ JC EXITP ;--+여기에서 프로시듀어를 호출하고 있다.
MOV DL,AL

CALL PUTCH ;--+
JMP START
EXITP: MOV AH,4CH
INT 21H

CODE ENDS
END START ;실행시작을 알리는 문장 >------------------+제7장 모듈별 프로그램의 작성법--------------------------------------------------------------------------------7.1 INCLUDE 의 방법--------------------------------------------------------------------------------모듈화의 이점: 프로그램을기능 별로 분활하여 알기쉽게 하는 것과 걔발효율을 향상시킬수있다아무리 같은 루틴을 사용할수있다고 하더라도 ,다른 프로그램을 만들때마다. 같은루틴을 키보드로 부터 입력하지 않으면 안된다는 것은 ,역시귀찮은 작업입니다.그래서 완성된 루틴의 부분을 미리 다른 화일 로 부터 작성해두고,메인 루틴만을 에디터로 부터 입력하여,서브루틴인 부분은 나중에 화일 단위로 결합시키는 방법을 생각해냈읍니다.이것이 어셈블러에 있는 인클루드(INCLUDE) 기능입니다.이기능을 사용할 때에는 우선 ,서브루틴 등의 부분을 독립시킨 화일로서 작성해두고 ,메인 루틴을 작성할때에 그중 필요한 부분으로 INCLUDE 의사명령을 사용하여"INCLUDE 화일 이름 " 으로 한다음 ,결합하는 화일 이름을 지정합니다.이렇게 해두면메인 루틴을 어셈블할때에 자동적으로 필요한 화일이 결합되어 어셈블됩니다.CODE SEGMENT ASSUME CS:CODE,DS:CODE;INCLUDE PUTAL.SUB ; PUTAL.SUB 화일의 내용을 인용한다.;START: MOV AX,CODE MOV DS,AX MOV AL,3FH CALL PUTAL MOV AH,4CH INT 21HCODE ENDS END STARTB 드라이브에 PUTAL.SUB 화일이 들어 있을때INCLUDE B:PUTAL.SUBINCLUDE 로 전개된 부분의 어셈블된리스트 화일은 "C " 가 붙어있다.동일 변수에 ,여러개의 데이터를 나열할때에는 다음 행에 변수이름을 가지지않는DB(define byte) 선언 등을 계속한다. NUM DB 12H,34H는 NUM DB 12H DB 34H라고 한것과 같다.레지스터의 대피:MOV BXSAVE,BX --+CALL PUTAL
BX 레지스터의 값을 대피했다가 복귀한다.MOV BX,BXSAVE --+ ..........BXSAVE DW ? ; 변수 선언7.2 PUSH,POP 명령--------------------------------------------------------------------------------PUSH,POP 명령은 ,스택 영역이라고 부르는 특별한 영역에 대하여 데이터를 기록,읽어내는 명령입니다.스택동작(stack operation)마지막에 넣은 것을 처음에 꺼내는 동작(LIFO,Last In First Out)을 스택동작메모리는 순서대로 나열되어 있으므로 ,현재어디까지 데이터가 쌓여있는지를 나타내기위하여,스택 포인터(stack pointer,ST 레지스터의 일종)에 마지막에 놓여진 데이터가 있는 메모리의 번지를 기억하도록 되어있읍니다.새로운 데이터를 쌓아올리면 SP 값은 감소 하고,데이터를 꺼내면 SP 값은 증가 번지 메모리하위번지

FFFA +-------+ FFFB +-------+ FFFC +-------+ <-- SP(스택포인터)에 의해 FFFD +-------+ 지시되는 메모리(마지막에 넣어진 데이터가 FFFE +-------+ 들어 있다.) FFFF +-------+주의) 보통의 경우와 ,데이터의 저장법과 순서가 거꾸로 되어 있으므로 주의가 요함8086의 PUSH, POP 명령에서는 반드시 2 바이트의 데이터가 한번에 읽어들여지고 꺼내어지므로, SP 의 값은 항상 2씩 증감합니다.스택영역은 보통 메모리의 최상위 번지로 설정되지만 이것은 8비트 CPU 와 같이 메모리공간이 좁은 시스템에 있어서 프로그램과 스택상의 데이터가 충돌하지 않게 하기위해서 였읍니다.8086에서는 보다 넓은 메모리 공간을 사용할수 가 있으므로 ,스택 동작을 위해서 스택 세그먼트를 독립하여 설정하고 있읍니다.SP 가 가리키는번지는 실제는 스택 세그먼트(SS)가 가리키는 베이스 번지로 부터의 오프셋 번지입니다.스택 세그먼트의 설정법에 의해 프로그램이나 데이터와 스택롸를 독립하여 배치할수도 있고,또한 8지트 CPU와 같이 프로그램과 스택을 동일한 메모리 공간에 배치할 메모리 공간에 배치할수도 있읍니다.어느경우에서도 스택 포인터의 초기치를 적당하게 설정함으로써 적당한 번지를 스택영역의 시작 번지로 할수가 있는데 ,보통은 최상위 번지로 부터시작합니다.CS -->+--------+--- 프로그램

+--------+ CS,SS ->+------------
+--------+

프로그램SS -->+--------+ +------------+ +--------+ SP스택영역 +------------+<-- SP +--------+ +------------+ 스택영역CS와 SS 를 독립시킨 경우 CS와 SS를 일치시킨 경우 ( 8비트 CPU 와 같은 사용법 )+-----------------------------------------+
PUSH +- 16비트 범용 레지트터 -+


세그먼트 레지스터


+- 16비트 메모리 -+

POP +- 16비트 범용 레지스터 -+


세그먼트 레지스터


+- 16비트 메모리 -+
+-----------------------------------------+*.POP CS 명령만은 존재하지 않는다. IP를 PUSH, POP 하는 명령은 없다. 플레그 레지스터를 PUSH, POP 하는 명령으로는 위와 별도로 PUSHF, POPF명령을 사용PUSH, POP 명령의 실제 사용 예:레지스터의 대피가 필요 하게 된것은 서브루틴 중에서 레지스터의 내용이 파괴 되기 때문입니다. 어느 레지스터의 내용이 파괴되는지는 서브루틴의 내용을 보지않고서는 알수없읍니다. 그래서 레지스터의 대피, 복귀는 메인 루틴쪽이 아니라 서브루틴 쪽에서 하는 것이 적절 합니다.+--------------+ +--------------+
메인루틴

메인루틴

........

.....

PUSH BX

CALL PUTAL

CALL PUTAL
<--+
.....

POP BX



+--------------+
+--------------++--------------+
+---------------+
서브루틴 +-----+
서브루틴
+--------------+
PUSH BX
PUSH ,POP 를 메인루틴쪽에서
.....
행한경우의 프로그램
POP BX
+---------------+ PUSH,POP를 서브루틴쪽에서 행한 경우의 프로그램완전히 같은 동작을 하지만 오른쪽이 더 좋은 프로그램입니다.메인 루틴쪽에서 어느 레지스터가 서브루틴 내에서 변경이나 파괴되는가를 생각하지않아도 되기 때문입니다.서브루틴을 완전히 블랙 박스 로서 사용할수가 있기 때문입니다.이와 같이 함으로써 서브루틴의 모듈화가 점점 효율적으로 됩니다.예제)PUSH1.ASMBL에 초기치로 주어진 어떤 8비트 값()을 1배,2배,..., F배 한수치를 출력한다.CODE SEGMENT ASSUME CS:CODE,DS:CODE;INCLUDE PUTAL2.SUBINCLUDE CRLF.SUB;ENTRY: MOV AX,CODE -+ MOV DS,AX -+DS설정; MOV BL,SEED ;초기 데이터 21H를 BL 에 지정한다. MOV CL,1NEXT: CMP CL,10H ;10H배이면 끝남. JE EXITP MOV AL,CL -+초기 데이터의 BL배를 구한다. MUL BL, -+ PUSH AX --+ MOV AL,AH -+-+---- 상위 바이트 출력 CALL PUTAL -+
POP AX --+-- AX레지스터를 보존(출력에 AL 레지스터를 사용하기 CALL PUTAL ;하위 바이트 출력 때문 ) CALL CRLF ;개행 INC CL UMP NEXTEXITP: MOV AH,4CH -+ INT 21H -+끝내고MS-DOS 로 귀환;SEED DB 21H ;초기 데이터CODE ENDS END ENTRYPUTAL2.SUBPUTAL: +--- PUSH AX -+;서브루틴 속에서 레지스터
+-- PUSH BX
AX,BX,DX 를 대피하고 있다

+- PUSH DX -+


MOV BL,10H


MUL BL


MOV DL,AH


CALL PUTHEX ; 상위자리를 출력


MOV AH,0


MOV BL,10H


DIV BL


MOV DL,AL


CALL PUTHEX ;하위자리를 출력

+- POP DX -+ AX,BX,DX 를 복귀
+-- POP BX
(PUSH와 의 역순) +--- POP AX -+ RET;PUTHEX: PUSH AX PUSH DX CMP DL,0AH JAE HEX2 ADD DL,'0' JMP HEX3HEX2: ADD DL,'A'-0AHHEX3: MOV AH,2 INT 21H POP DX POP AX RETCRLF.SUBCRLF: +-- PUSH AX
+- PUSH DX

MOV DL,0DH ;CR(복귀)을 출력

MOV AH,2 -+

INT 21H -+

MOV DL,0AH

MOV AH,2 -+ ;LF(개행)을 출력

INT 21H -+
+- POP DX +- POP AX RETPUSH,POP 명령은 16비트로 된 레지스터에 ,혹은 메모리에 대피,복귀밖에 하지 못하므로 ,서브루틴 내의 DL레지스터 밖에 사용하지 않는경우에도 DX레지스터로서 대피한다. PUSH AX ; AX의 내용을 BX에 전송 POP BX직접 전송을 허용하지 못하는 세그먼트간의 값을 전송하는데 유효합니다.예) PUSH CS POP DS가장주의 해야할점:하나의 서브루틴 중에서 PUSH 한것은 그 루틴 내에서 반드시 POP 한다.7.3 프로그램의 모듈화와 링클방법--------------------------------------------------------------------------------모듈화된 프로그램을 따로 별도로 어셈블하고 ,LINK에 의해 결합 할수도 있읍니다.+-----------------------------------------------------------------------------+
메인 프로그램 서브프로그램 메인 프로그램 서브프로그램



\/ \/

+-> MASM <-+ MASM MASM

\/ \/ \/

오브젝트 프로그램 오브젝트 프로그램 오브젝트 프로그램

\/ \/

LINK LINK

\/ \/

실행가능 프로그램 실행가능 화일



어셈블단계에서 결합하는경우 링크 단계에서 결합하는 경우
+-----------------------------------------------------------------------------+오브젝트 단계에서 링크가 가능하기 때문에 ,MS-DOS에서느 공동형식ㅇ의 오브젝트 화일을 작성하는 어셈블러나컴파일러의 출력을 합쳐서 하나의 실행가능 프로그램하는것이 가능하다.이때문에 어셈블러와 C 언어와 의 링크 등이 가능하게 됩니다.그러나 링크의 기능을 잘 사용하기 위해서는 ,많은 형식사의 약속이나 링커의 동작을 이해하지 않으면 안되아서 그 개요를 설명하는 것만해도 상당한 분량을 차지하게 됩니다.프로그램의 개발에 대해서는 메인 프로그램을 포함하는 모듈의 소스 프로그램과 서브루틴으로 이루어지는 소스 프로그램으로 작성합니다.예제)MODULE1.ASM문자열(string) We are the world 를 출력한다.CODE SEGMENT PUBLIC ASSUME CS:CODE,DS:DATA;EXTRN PUTSTR:NEAR 외부에서 참조하는 서브루틴의 선언;START: MOV AX,DATA MOV DS,AX MOV BX,OFFSET MSG CALL PUTSTR MOV AH,4CH INT 21H;CODE ENDS;DATA SEGMENT PUBLICMSG DB 'We are the world',00H;
DATA ENDS +-->끝내기 위해 삽입된 0 이다. END STARTPUTSTR.ASM문자열을 출력하는 서브루틴CODE SEGMENT PUBLIC ASSUME CS:CODE;PUBLIC PUSTR ;다른 모듈에서 참조되는 서브루틴 이름을 PUBLIC 의사명령으로; 선언한다. 즉 다른데서 PUTSTR을 참조할것이라고 선언함.PUTSTR PROC NEAR --+ PUSH AX
PUSH DX
PUSH SI
MOV SI,0
PUT_NET:
MOV DL,[BX+SI]
CMP DL,0 -+-+----->문자열중 0 이 나타나면 끝낸다. JZ PUT_EXIT -+
MOV AH,2
반드시 서브루틴 INT 21H
PROC ~ ENDP 로 INC SI
선언한다. JMP PUT_NEXT
PUT_EXIT:
POP SI
POP DX
POP AX
RET
PUTSTR ENDP ----------+;CODE ENDS 형식상 하나의 세그먼트에 있는 걸로한다. END서브루틴 PUTSTR은 ,BX에 의해 간접지정되는 번지를 선두로 한데이터 열을문자열로서 출력하고 ,0 이 나타나면 종료하는 것입니다.PUBLIC 이라는 지정은 : 다른 모듈과 링크할 때에 같은 이름의 세그먼트가 있다면 그것을 합쳐서 하나로 하라, 라는 지정입니다.EXTRN(external) : 열거된 서브루틴이 외부의 모듈의 모듈 속에 들어있다는 것을 나타내고 있읍니다.어셈블러는 더셈블 단계에서 같은 모듈 내의 서브루틴이나 라벨이 존재하지 않는 경우에는 Symbol not defined 에러를 발생하는데, EXTRN 의사명령에 의해 선언되어 있게되면 ,그서브루틴이나 라벨은 다른 모듈에 있어서 링크할때 결합할수있다고 간주되어 에러를 발생하지 않고 어셈블을 계속합니다.라벨이름이 동일세그먼트 내에 배치되는 것인 경우에는 , : 에 바로 이어서 NER을 붙이고, 라벨의 속성을 선언하지 않으면 안됩니다.만일동일 세그먼트내에 존재하지 않을 때에는 , : FAR 을 붙이지 않으면 안됩니다.서브루틴 :서브루틴에 놓이는 모듈도 하나의 세그먼트로서 형식을 갖추기위해 그 앞뒤를SEGMENT ~ ENDS 로 둘러 쌉니다.여기 에서 세그먼트선언은 메인루틴과 같지않으면 안됩니다.(동일한세그먼트 이름이어야 한다) 데이터 세그먼트를 사용하지않을 때에는ASSUME 문장으로 DS 선언을 하지 않도록 합니다.PUBLIC :의사명령 으로 PUTSTR 이라는 이름의 서브루틴(라벨 이름)이 다른 외부의 모듈에서 참조 가능하다는 것을 선언하고 있읍니다.이것은 이 루틴 중 어느 라벨 이름니 외부참조가 가능 하다는 것을 나타내는 것 입니다.여기서 사용하고 있느 PUBLC 과 세그먼트 선언중에 사용되고 있느 PUBLC과는 다른 것입니다. 그리고 서브루틴 전후를 PROC ~ ENDP 에 의해 둘러싸고, 구조를 명확하게 합니다. 이전과 마찬가지로 단순히 라벨 이름만을 서브루틴으로 할수도 있지만, 별로 추천할만 하지하지는 않습니다. 그리고 PROC 의 다음의 NEAR 은 없어도 상관이 없지만,이것도 동일한 세그먼트 내에서 참조 되는 라벨이라는 것을 나타내고 있읍니다.이상의 것을 정리하여 프로그램에 필요한 구조를 나타내고면 다음과 같이 됩니다.(세그먼트 이름을 CODE , 서브루틴 이름을 PUTSTR 로 한다.)+------------- 메인루틴 -------------------------------------+
CODE SEGMENT PUBLC

ASSUME CS:CODE.......

EXTRN PUTSTR:NEAR

START:

+---------+


본 문


+---------+

CODE ENDS

+----------------------------------+


만일 있다면 데이터 세그먼트 등


+----------------------------------+

END START
+----------------------------------------------------------------++------- 서브루틴 -------------------------+
CODE SEGMENT PUBLC

ASSUME CS:CODE.....

PUBLC PUTSTR

PUTSTR PROC NEAR

+---------+


본 문


+---------+

PUTSTR ENDP

CODE ENDS

END
+----------------------------------------------+오브젝트 화일을 링크할 때에는 화일 이름을 " + " 로 연결하여 지정합니다.반드시 메인 루틴을 포함하는 모듈의 화일 이름을 선두에 지정합니다.A>LINK MODULE1+PUTSTR,,MODULE1;이것으로 실행가능 화일이 완성됩니다.자기가 모듈을 만들어 나갈때에는 위레서 설명한 방법에 따라서 모듈으 개발하면 되는데, 아른 참고서 로 부터 인용할 경우에 반드시 위와 같은 대로 되어 있지 않은 경우가 있읍니다. 그와 같은 경우에는 세그먼트 이름을 고쳐 쓰는 방법 등으로 대처해 주십시오. 그래도 안되는겨우에는 원인을 여러가지로 생각 할수가 있지만,자세하게는 나중에 다루도록 하고 ,할수없이 서브루틴 자체를 맞도록 자기가 다시 베열 하여 고쳐 작성하는 등 시행착오를 해 보십시요.

댓글 없음:

댓글 쓰기

국정원의 댓글 공작을 지탄합니다.

UPBIT is a South Korean company, and people died of suicide cause of coin investment.

 UPBIT is a South Korean company, and people died of suicide cause of coin. The company helps the people who control the market price manipu...