『게임 제작 강좌-프로그래밍 강좌 (go NGM)』 411번 제 목:[옮김] 어셈블리 기초명령 소개 올린이:nowngm (게임제작) 97/11/27 14:11 읽음:520 관련자료 없음 ----------------------------------------------------------------------------- 『게임 제작 강좌-프로그래밍 강좌 (go NGM)』 27번 제 목 : 어셈블리 기초명령 소개 올린이 : 유씨가족(유용수 ) 95/07/11 17:43 읽음 : 568 관련자료 없음 ----------------------------------------------------------------------------- 어셈블리 명령의 개략적인 명령 본지에서는 어셈블리어 명령들을 간략하게 나열하고자한다. 상세한 설명은 다음에 하기로 한다. 1)데이터 전송 명령 해설:[메모리와 레지스터,레지스터와 레지스터,메모리와 메모리사이에서 데이터를 전송하는 명령이다.] 이 전송을 위해 사용하는 명령어가 MOV,MOVS 명령이다. 이 MOV명령은 레지스터와 메모리,레지스터와 레지스터사이에 사용된다. MOV명령내에는 레지스터나 메모리에 직접 수치를 전송(대입)할 수도 있다. CF) MOV AX,1234H MOV DS,SI MOV BX,[1234H] MOV [BX+SI],AH 메모리로부터 메모리로 데이터를 전송 할때에는 스트링 명령이라고 하는 명령중에서 MOVS(move string)명령을 사 용한다. 2)사칙 연산 명령 8086(16BIT)에서는 가감승제의 사칙연산을 할 수 있다. 덧셈에는 ADD(adding)명령,자리올림을 고려한 덧셈인 ADC(addition with carry)명령,뺄셈을 하는 SUB(subtract) 명령,자리받아내림을 고려한 뺄셈인 SBB(subtract with borrow)명령,4개의 명령은 모두 범용 레지스터 간 및 메 모리간에서 실행할 수가 있다.덧셈,뺄셈에서는 직접 숫자를 지정할 수도 있다. CF) ADD AX,BX ADC BP,4567H SUB [3AB4H],CX SBB [DL],530AH 곱셈을 하는 MUL(multiply)명령,부호가 달린 수치를 곱셈하는 IMUL(integer multiply)명령, 나눗셈을 하는 DIV(divide)명령,부호가 달린 나눗셈을 하는 IDIV(integer division)명령을 수행하기 위해서는, 미리 AX레지스 터(혹은 AX REGISTER와 DX REGISTER의 쌍)에 피승수 혹은 피젯수를 설정해 두고, 명령을 실행할 때에는 승수 혹 은 젯수가 들어가 있는 레지스터 또는 메모리를 지정한다. 직접 수치와의 사이에서의 연산은 불가능하다. CF) MUL CX IMUL BYTE PTR [BX] DIV WORD PTR [1234H] IDIV BH 연산 명령이라고 말할 수 있을지 모르겠지만,AL레지스터의 부호가 달린 8비트 수치를 AX레지스터의 부호가 달 린 16비트 수치로 확장하는 CBW(convert byte to word)명령, 마찬가지로 ax레지스터로부터 dx레지스터와 ax레지 스터의 쌍으로 확장하는 cwd(convert word to doubleword)가 있다. 덧셈,뺄셈 명령의 특수한 예로서 레지스터 혹은 메모리의 내용을 하나만 증가 시키는 INC(increment)명령과 1만 큼 감소시키는 DEC(decrement)명령 등이 있다. 횟수의 카운터 등에 사용된다. 3) 논리 연산.시프트 명령 논리연산명령은 8비트 내지 16비트 수치를 각 비트 단위로 연산하는 명령이다. 또한 비트 단위로 시프트나 회 전을 하는 명령도 있다. AND(and)명령,OR(or)명령,XOR(exclusive or)명령은 2개의 레지스터간, 레지스터와 메모리간,레지스터와 수치 간,메모리와 수치간으로 각 비트마다 AND혹은 OR 혹은 XOR을 취하는 명령이다.NOT 명령은 레지스터 혹은 메모리 의 내용을 반전시키는 명령어이다.또한 NEC(negative)명령은 2의 보수를 취하는 것이다. CF) AND AL,01001011B OR [BX],SI XOR AX,AX NOT BH NEG DI 비트단위로 시프트 하는 명령은 레지스터 혹은 메모리의 데이터를 2진수로 나타내고, 각 비트를 오른쪽 혹은 왼 쪽으로 하나씩 비껴 나간다. 비껴나갈 때에는 공백으로 되는 비트에 무엇을 채울것인가에 따라서 다양한 명령의 종류가 있어 0을 집어넣는것, 시프트에의해 빠져나온 비트를 집어넣는 것 등 여러종류가 있다. 주로 수치의 2배,4배,...,혹은 1/2,1/4,...을 할 때 사용되지만 목적은 가지가지이다. 명령의 첫번째 문자가 시프트(S)인가 로테이트(R)인가를, 두번째 문자에 0을 집어넣을 것인가(H),빠져나온 비트 를 넣을 것인가(O),캐리 플러그를 넣을 것인가(C),부호의 비트를 넣을 것인가(A)를 나타내고, 세번째 문자가 회 전의 방향이 오른쪽인가(R) 왼쪽인가(L)를 나타내고 있다. 조합하는 방법은 표를 보면서 외우는 수 밖에 없다. 그런데 시프트(shift)혹은 로테이트(rotate)를 몇 비트 씩 한꺼번에 실행할때에는 CL레지스터에 그 시프트 혹은 로테이트하는 횟수가 되는값을 넣은다음,다음과 같이 지정한다. CF) SHL AX,1 SHR AL,1 SAR BX,CL ROL DL,1 ROR WORD PTR [BX],1 RCL BYTE PTR [1234H],CL RCR CH,CL 4) 비교 분기 명령 레지스터간, 레지스터와 메모리,레지스터와 수치,메모리와 수치의 대소를 비교하는 명령으로서는 CMP(compare) 명령이 있다. 이 멸령은 단순히 데이터의 대소를 비교하는 것으로써 레지스터나 메모리의 내용은 변화하지 않는다. 비교의 결과는 플래그 레지스터에 보존되어, 이어서 설명하게 되는 조건분기명령을 제어하는 데에 사용된다. CF) CMP AX,1234H CMP [SI],BL CMP BYTE PTR [BX],80H 분기 명령에는 무조건 분기명령과 조건 분기명령 등이 있다. 무조건 분기명령의 JMP(jump)는 실행하면 반드시 지정한 번지로 분기한다. 분기할 번지는 보통 레이블을 사용하여 지정한다.(레이블의 지정방법은 나중에 설명) CF) JMP LABEL1 JMP SHORT EXIT 조건 분기명령은 직전의 연산 결과 혹은 비교명령의 결과에 따라서 조건에 만족한 경우에 한해서 분기를 하고, 만족하지 않을 때에는 그 다음 명령을 실행한다. 비교방법에는 단순대소 비교,부호 달린 대소 비교,직접 플래그참조 등이 있다. 또한 같은 판단 조건에 두가지로 부르는 방법이 있을 경우도 있다. 예를 들면 ,A>=B라는 것을 [A는 B보다 크거나 같다]라든지 [A는 B보다 작지않다]라고 표현할 수가 있다. 그래서 기본적으로 Above(크다),Below(작다),Greater(부호를 포함해서 크다), Less(부호를 포함해서 작 다),Equal(같다),Not(부정)의 조합으로 이루어진다.분기하는 장소는 레이블을 사용하여 지정한다. CF) JAE J1 JNE ERROR NEXT PAGE..... JG CASE1 JNGE QUIT 비교명령의 특수한 예로서 두개의 레지스터 혹은 메모리의 AND를 취하는 것이 있다. TEST 명령이 바로 그것이다. AND 명령과 다른점은, AND를 취한 결과는 플래그만을 변화시켜 원래의 데이타가 그대로 보존된다는 점이다. CF) TEST CX,11111001B 조건 분기명령은 어떤 횟수만큼 같은 루프를 반복하는데 자주 사용된다. 그래서 카운터가 0일 될 때까지 루프를 반복하는 조작을 하나로 정리한 것으로써 LOOP명령이 있다. 이 명령은 CX레지스터를 카운터로써 사용한다. 또한 CX레지스터의 값 뿐만 아니라 직전의 비교, 연산의 결과도 참고로 하여 루프할것인지 하지 않을 것인지를 정하는 LOOPE(loop if equal),LOOPNE(loop if not equal)명령도 있다. CF) LOOP LABELA LOOPE WAITING LOOPNE SEARCH 서브루틴으로 분기하는 명령으로서는 CALL명령이 있다. 조건에 따라 분가할까 말까를 결정하는 명령은 없으므 로, 조건판단이 필요하다면 조건분기명령과 함께 사용된다. CF) CALL SUBROUTINE CSLL FAR FARSUB 서브루틴에서 원래의 루틴으로 돌아올 때에는 RET(return)명령을 사용한다. 단 이 때에 인수를 전달하는데 사 용한 스텍을 돌려주기 위해서 스택 포인터(SP)에 더해주는 수치를 지정할 수도 있다. CF) RET RET 4 5)스트링 명령 데이터 전송명령과 루프 명령을 조합시킨 것으로서 스트링 명령이 있다. 스트링 명령에는 메모리로부터 레지스터 에 데이터를 로드하는 LODS(load string)명령,레지스터로부터 메모리에 데이터를 저장하는 STOS(store string)명 령이 있다. 이들 명령에서는 메모리의 번지지정방법이 SI 혹은 DI 레지스터를 사용하여 간접적으로 정해지기 때 문에 미리 SI 혹은 DI레지스터레 번지를 세트해 두어야 한다. 또한 사용할 수 있는 레지스터도 AX레지스터 혹은 AL레지스터레 한정된다. 이와 같이 번지의 지정법이 한정되어 있기 때문에, 이명령은 조작하는 데이터가 바이트(B)인가 워드(W)인가를 나타내는 한 문자를 후미에 붙이기만 하 는 오퍼랜드를 가지지 않는 명령으로 되어 있다. CF) LODSB STOSW MOVSB MOVSW 이들 스트링 명령은 단독으로서는 1바이트 혹은 1워드의 데이터를 전송하는 것 뿐이지만,REP(repeat)명령과 조 합시켜 사용하면 CX레지스터가 지정하는 횟수만큼 반복하여 데이터를 전송한다. 이때 번지는 자동적으로 갱신되 어가므로 한명령으로 연속된 여러 데이터를 전송할 수가 있다. CF) REP STOSB REP MOVSW 스트링 명령에서는 그밖의 데이터의 전송은 하지 않고 레지스터와 메모리의 내용을 비교만 하는 SCAS(scan- string)명령과 메모리끼리의 내용을 비교만하는 CMPS(compare string)명령이 있다. 이들 명령은 REPE(repeat until equal)명령 혹은 REPNE(repeat until not equal)명령과 조합함으로써 일치하는 데이터가 얻어질 때까지 메모리상의 데이터를 탑재 할 수가 있다. CF) SCASB REPE SCASW REPNE CMPSB REPE CMPSW 6) I/O 명령 마이크로 컴퓨터에 있어서는 CPU외에도 그래픽 디스플레이 컨트롤러 (GDC)나 플로피 디스크 컨트롤러(FDC)등의 입출력을 실행하기 위해 다양한 LSI(Large Scale Integeration)가 사용되고 있다. 이들 LSI에 명령을 보낸다던지 에이터를 얻는다든지 하기 위한 명령이 I/O 명령이다. 개념적으로는 이들의 LSI는 CPU나 외부장치와 통신하기위해서 설계된 I/O PORT가 있는 번호의 PORT에 연결되어 있다고 생각할 수 있다. I/O 포트에 에이터를 보내는 명령이 OUT(output)명령,I/O 포트로 부터 데이터를 받는 명령이 IN(input)명령이 다. 포트의 번호는 직접 수치 혹은 DX레지스터를 사용해 지정하고, 데이터는 AX 혹은 AL 레지스터를 사용해 전송 한다. CF) OUT 02H,AL OUT DX,AX IN AX,0A0H IN AX,DX 7)인터럽트 명령 인터럽트 처리란, 프로그램을 실행중에 외부장치로부터의 인터럽트(INTERRUPT, 끼어들기)요구나 연산 에러가 발 생했을 때에,CPU가 프로그램의 실행을 일시 중지하고 인터럽트 처리 루틴으로 분기하는 것이다. 8086에서는 이러한 CPU외부로부터의 인터럽트나 에러 처리를 하는 것외에도 프로그램 상에서 인터럽트 명령을 작성해둠으로서 인터럽트 처리 루틴으로 분기할 수가 있다. 즉, 인터럽트 처리를 일종의 서브루틴으로 사용할 수 있다는 것이다. 인터럽트의 종류는 256개까지 설정할 수가 있어서 그들 중 몇가지는 시스템 프로그램에 의해서 사용된다. 즉, 인터럽트 처리를 사용함으로서 우리가 시스템 프로그램을 사용할 수가 있는 것이다. 소프트웨어 인터럽트는 명령은 INT(interrupt)의 다음에 인터럽트번호를 지정한다. CF) INT 1BH INT 21H 인터럽트 처리 루틴으로부터 원래의 루틴으로 돌아오려면 IRET(interrupt return)명령을 사용한다. CF) IRET 8) CPU제어 명령 CPU제어명령은 주로 8086의 CPU나 8088 CPU가 수치연산 프로세서8087과의 사이에서 데이터를 전송한다든지 주변 장치로 부터 READY신호가 올 때까지 실행을 정지하고 기다린다든지 등을 수행하기 위한 명령이다. CF) WAIT ESC 001000B,AL LOCK HLT NOP 9) 그 밖의 명령 레지스터 혹은 메모리의 내용을 스택 영역으로 대피,복귀시키기 위한 PUSH,POP 등의 명령과 플래그레지스터를 스택으로 대피,복귀하는 PUSHF,POPF,두개의 레지스터 혹은 메모리의 데이터를 교환하는 XCHG(exchange)명령, 한 바이트씩 나열된 데이터의 N번째의 것을 꺼내는 XLAT(translate)명령등이 있다. CF) PUSH AX POP [BX+SI] PUSHF POPF XCHG DX,[DI] XLAT 그밖의 플레그레지스터를 직접 제어하는 STC(set carry flag),CLC(clear carry flag),CMC(complement carry flag),STD(set direction flag),CLD(clear direction flag),STI(set interrupt enable flag),CLI(clearinterrupt-enable flag)플래그 레지스터 하위 8비트와 AH레지스터의 데이터를 전송하는 LAHF(loa AH from flags),SAHF(store AH ti flags),10진 연산 보정을 하는 AAAA(ASCII adjust for addtion),DAA(decimal adjust for subtract),AAM(ASCII adjust for multiply),ADD(ASCII adjust for division)등이 있다.(이상의 명령 은 오퍼랜드를 갖지않는다.) 실효번지를 로드하는 LEA(load effective address),세그먼트 레지스터를 포함하는 실효번지를 로드하는 LDS(load segment register),LES(load es\xtar segment register)명령도 있다. CF) LEA [BX+DI+001A] LDS SI,TABLE1 이상으로 간략한 어셈블리 기본 명령어들 이었습니다. 흔히 어셈블리를 어렵다고들 합니다. 저도 지금 배우는 입장이지만 엄청 어렵습니다. 그렇지만 실망하지 마시고 이런 기본 명령들을 외워두고 베이직 프로그램 짤때처럼 쉽게 명령어가 머리속에서 튀 어 나올수 있도록 노력하시기 바랍니다. 이상의 어셈블리는 MACRO ASSEMBLY(메크로 어셈블리)로서 도스에서 실행가능한 프로그래밍 언어입니다. 이상의 내용은 [ 예제방식으로 배우는 MS-DOS 메크로 어셈블러 (주)교학사] 를 참고한 내용입니다. 다음에 더 좋은 글로 인사드리겠읍니다. 참 ! MASM 어셈블러는 자료실의 프로그래밍에 있는거 아시죠? 끝으로 어셈블리를 잘 이해하시려면 레지스터의 종류와 기능을 알아두시면 좋다고 합니다.