본문 바로가기

운영체제

운영체제)#11 System Call의 이해 : 어셈블리어 (PC버전) (2)



<증가, 감소 명령>

INC (INCrement)

-> 형식 : INC      OP

                       reg //Segment register 사용 불가

                       mem


-> 기능 : OP OP+1


ex) MOV    AX, 5

     INC      AX //결과 AX = 6

 

 

DEC (DECrement)

-> 형식 : DEC     OP

                       reg

                       mem


-> 기능 : OP OP-1


ex) MOV     DL, 10

     DEC      DL //결과 DL = 9

 

 


<키 입력 방법>

에코(echo) 있는 입력 //에코는 내가 입력한 값을 알려주는 것

MOV    AH, 1

INT     21H

//Function code1System call

//입력된 문자의 ASCII 코드는 AL에 저장

 

에코(echo) 없는 입력

MOV    AH, 8

INT      21H

//Function code8System call

//입력된 문자의 ASCII 코드는 AL에 저장


<예시코드 366.asm>

CODE    SEGMENT

ASSUME CS:CODE, DS:CODE

MOV     AX, CODE

MOV     DS, AX


MOV     AH, 8

INT     21H ; 키입력, AL에 저장


MOV     KEEP, AL 

MOV     DL, KEEP ; 입력 결과를 변수에 저장

ADD     DL, 1


MOV     AH, 2

INT     21H


MOV     AH, 4CH

INT     21H


KEEP     DB ?

CODE    ENDS

END

 

 


<비교 명령어>

CMP(Compare) 명령어

-> 형식 : CMP     OP1, OP2

                        reg   reg    

                        reg   mem

                        reg   imm

                        mem reg //Memory 끼리는 안된다. mem mem (x)

                        mem imm

 

-> 기능 : OP1 - OP2의 결과에 따라 Flag register 변화, operand 내용 불변
//Flag register의 상태에 따라 조건 분기 명령 수행, Flag에 영향을 준다.


ex) CMP      CX, 10 //CX 값이 10이면 ZF=1

 

TEST 명령어

-> 형식 : TEST OP1, OP2

                   reg   reg

                   reg   mem

                   reg   imm

                   mem reg //Memory 끼리는 안됨 mem mem (x)

                   mem imm

 

-> 기능 : OP1 AND OP2의 결과에 따라 Flag register의 변화, operand 내용 불변

//Bit 단위의 논리곱

//Flag register의 상태에 따라 조건 분기 명령 수행

 

ex) TEST      CL, 80H

//80H = 1000 0000(2), CLMSB0이면 ZF=1

//AND 연산의 특징

0 AND x = 0

1 AND x = x

 

 

 

<분기 명령어의 비교>


 

 


<분기 명령어>

무조건 분기 명령어 : JMP label

-> 무조건 label로 분기(Jump)

 

ex) CASE1: ... //label

               JMP      CASE1 //goto label


<예제코드 372.asm>

CODE SEGMENT

ASSUME CS: CODE


NEXT: MOV AH, 1 ;1문자 입력

INT 21H


MOV DL, AL

INC DL

MOV AH, 2 ;1문자 출력

INT 21H


JMP NEXT  ;무조건분기


MOV AH, 4CH

INT 21H


CODE ENDS

END

//계속 NEXT라벨로 분기한다.



조건 분기 명령어

-> 조건을 만족하면 label로 분기, 만족하지 않으면 무시

//JBE는 작거나 같을 때 레이블 실행

 


조건 분기 명령의 정리

 


Flag register를 이용한 분기

 

 

대문자 소문자 변환 프로그램

<375Atoa.asm>

CODE SEGMENT ; 소문자를 대문자로 변환해주는 프로그램

ASSUME CS: CODE


NEXT: MOV AH, 1     ;AL에 1문자 키보드 입력(echo)

INT 21H         ;MOV AH,8 → No echo


CMP AL, 20H ;ASCII 코드 20H → space bar

JE EXIT         ;프로그램 종료


CMP AL, 'A'

JB PRINT ;'A'보다 작으면 그대로 출력


CMP AL, 'Z'

JA PRINT ;'Z'보다 크면 그대로 출력

ADD AL, 'a'-'A' ;대문자이면 소문자로 변환 


PRINT:MOV AH, 2 ; 1문자 출력(DL)

MOV DL, AL

INT 21H

JMP NEXT


EXIT: MOV AH, 4CH ; 프로그램 종료

INT 21H


CODE ENDS

END


 

 

<반복 명령어>

LOOP 명령어 : LOOP label

-> CX 반복할 횟수, 자동적으로 1씩 감소하면서, CX = 0 될 때까지 반복

//FOR문과 유사하다.

//LOOP 명령어는 CX레지스터의 값을 1씩 감소시키면서 실행한다.

 

ex) MOV      AX, 0

     MOV      CX, 10 ; 반복 횟수

NEXT: ADD   AX, CX

        LOOP  NEXT

 

ex) MOV     AX, 0

     MOV     CX, 10

NEXT: ADD   AX, CX

        DEC    CX

        JA      NEXT

 

LOOPE / LOOPZ (Loop while Equal)

-> 상한을 CX번으로 정해 놓고, 다른 것이 나타날 때 까지 반복한다.

 

LOOPNE / LOOPNZ (Loop while Not Equal)

-> 상한을 CX번으로 정해 놓고, 같은 것이 나타날 때까지 반복

 

REP (REPete) 명령어

-> 하나의 명령어만을 반복, CX 반복 횟수

 

 

 

<스택의 동작>

Stack의 정의

-> 메모리의 한 영역으로 데이터를 임시 저장했다가(PUSH), 다시 불러들일 때(POP) 사용

ex) 동전 케이스

cf) Stack : LIFO(Last In First Out) 구조

Queue : FIFO(First In First Out) 구조

 

Stack의 사용

-> 서브루틴에서 복귀할 주소 저장

-> 임시 데이터 저장

-> 서브루틴의 인수 전달

SS = CS (default)


PUSHPOP 명령어

-> 형식:

PUSH    OP ; OPstack에 저장

POP      OP ; Stack의 데이터를 OP에 저장

            reg(16bit)

            mem(16bit) //반드시 16bit

            sreg(segment register)

 

-> IP, SS, SPPUSH 불가능(IP는 자동으로)

-> PUSHPOP의 개수 일치, 순서 반대로

-> PUSHF : Flag registerstack에 저장

    POPF : Stack의 데이터를 Flag register의 값으로

-> 16bit (2byte) 단위로 저장


<385.asm>

CODE SEGMENT

ASSUME CS:CODE

MOV AX, 1234H

MOV BX, 5678H ;초기값 ;SP=0

PUSH AX ;SP = FFFEH

PUSH BX ;SP = FFFCH ;Stack에 저장 

PUSHF ;SP = FFFAH


MOV AX, 2468H

MOV BX, 2468H

SUB AX, BX ;값 변화


POPF ;SP = FFFCH ;PUSH의 역순

POP BX ;SP = FFFEH ;Stack에서 복구

POP AX ;SP = 0

MOV AH,4CH

INT 21H

CODE ENDS ;MASM에는 지역변수가 없고

 END ;모두 전역변수이므로 지역변수

;역할이 필요할 때 STACK을 이용


 

 

<서브루틴 사용법>

Subroutine

-> 프로그램 중 일부를 독립된 부분으로 작성한 후 main routine에서 호출(call)해서 사용 //여러 번 호출하는 루틴

-> 복귀할 주소를 stack에 자동 저장

-> 서브루틴 수행 후 호출한 다음 번지로 복귀

 

CALLRET(RETurn)

 -> 형식:


ex) 0~9 숫자를 출력(문자로 바꾸어서)

<382.asm>

CODE SEGMENT

ASSUME CS:CODE

MOV CL, 0 ;초기화

NEXT: CALL PUTNUM ;subroutine 호출

INC CL ;CL = CL+1

CMP CL, 10 ;CL이 10보다

JB NEXT ;작으면(Below) NEXT로 JUMP


MOV AH, 4CH

INT 21H


PUTNUM: 

MOV DL, CL

ADD DL, '0' ;숫자를 문자로 변환('0'=30H)

MOV AH, 2

INT 21H

RET

CODE ENDS

END

 


■ ex) 16진수(8비트 register )를 화면에 표시


<390putal.asm

CODE SEGMENT

ASSUME CS:CODE


MOV AX, CS

MOV DS, AX


MOV AL, 3FH ;출력할 숫자

CALL PUTAL ;PUTAL 호출


MOV AH, 4CH

INT 21H


PUTAL:

MOV BL, 10H

MUL BL ;AX = 03F0H

MOV LEVEL2, AH ;상위보존

MOV AH, 0 ;AX=00FOH

DIV BL ;AL=0FH

MOV LEVEL1, AL ;하위보존


MOV DL, LEVEL2

CALL PUTHEX ;PUTHEX호출

MOV DL, LEVEL1

CALL PUTHEX ;PUTHEX호출

RET         ;return


PUTHEX:

CMP DL, 0AH

JAE HEX

ADD DL, '0'

JMP PRINT


HEX:

ADD DL, 'A'-0AH


PRINT:

MOV AH, 2

INT 21H

RET


LEVEL1 DB ?

LEVEL2 DB ?


CODE ENDS

END

 



<PROC에 의한 서브루틴 작성>

PROC ... ENDP

-> 서브루틴을 보다 구조적으로 표현하는 방법

-> 형식:

            프로시져_이름 PROC [속성] //생략 가능

                                ...

            프로시져_이름 ENDP //END Procedure

 

-> 속성

    NEAR : 동일 세그먼트 내에 존재(default)

    FAR : 다른 세그먼트에 존재


<392proc.asm

CODE SEGMENT

ASSUME CS:CODE


START: MOV AX, CS ;시작 번지를 가리키는 라벨

MOV DS, AX


MOV AL, 3FH

CALL PUTAL ;서브루틴 호출

MOV AH, 4CH

INT 21H


PUTAL PROC ;서브루틴 시작


MOV BL, 10H

MUL BL ;AX = 03F0H

MOV LEVEL2, AH ;상위보존

MOV AH, 0 ;AX=00FOH

DIV BL ;AL=0FH

MOV LEVEL1, AL ;하위보존


MOV DL, LEVEL2

CALL PUTHEX ;PUTHEX호출

MOV DL, LEVEL1

CALL PUTHEX ;PUTHEX호출

RET ;reuturn


PUTHEX:

CMP DL, 0AH

JAE HEX

ADD DL, '0'

JMP PRINT


HEX:

ADD DL, 'A'-0AH


PRINT:

MOV AH, 2

INT 21H

RET


LEVEL1 DB ?

LEVEL2 DB ?


PUTAL ENDP ;서브루틴 끝



CODE ENDS

END START ;시작번지를 지정, 프로시져등으로 인해 메인루틴의 순서가 바뀌는 경우 꼭 필요