'7-Segment'에 해당되는 글 1건

이것은 예전에 어떤분이 부탁해서 작성하게된 예제입니다.

* 문제: 4개의 DIP 스위치 값을 2진수로 읽어 들이고, 이 값에 대응하는 7-세그먼트 코드를 16진수로 출력하는 프로그램을 작성하시오
* 예를들어 , 스위치가 0000으로 되어 있으면 7-세그먼트의 출력 코드는 X100 1000(세그먼트 a-f는 켜지고 g는 꺼진다)이다. 프로그램은 무한히 반복되어 새로운 값이 스위치에 설정되면 이것을 바로 출력하게 한다. 프로그램 개요도와 주석달린 프로그램 리스트를 작성하라
* HINT: 16개의 7-세그먼트 코드로 번역 표를 만들고. 스위치에서 입력되는 2진수를 이 테이블의 인덱스로 이용하라. 명령어 XLAT를 사용하여 7- 세그먼트 출력을 구할수 있다...

코드:

; 실행하면 "Input code: " 라는 프롬프트가 뜨며
; 여기에 값을 2진수(!)로 0부터 15까지의 입력을 받게 되며
; "Value <입력한 문자열>, <입력한 값을 AX로 변환후 값>"의 형식으로 표시해주고
; "Segment code: <결과값>" 이라고 하여 실제 결과값을 출력 합니다.

; 이 소스의 개선점으로는 범위 밖의 입력에 대한 에러처리가 되어 있지 않습니다.

.386 ; 80x386이상의 머신코드를 생성

                ASSUME CS:CODE, DS:DATA, ES:NOTHING, SS:STACK_AREA
CODE            SEGMENT PARA PUBLIC USE16 'CLASS_CODE'
; ===============================================================================
L_STARTUP:
                ; Data segment를 DATA로 초기화
                MOV AX, DATA
                MOV DS, AX

                ; Logo 문자열 출력
                MOV AH, 09H
                MOV DX, OFFSET DATA:D_MSG_LOGO
                INT 21H
                CALL NEAR PTR CODE:P_CRLF

                ; "Input code"문자열 출력
                MOV AH, 09H
                MOV DX, OFFSET DATA:D_MSG_INPUT
                INT 21H

                ; D_MSG_BUFFER에 문자열을 입력 받음
                MOV AH, 0AH
                MOV BYTE PTR DATA:[D_MSG_BUFFER], 80
                MOV DX, OFFSET DATA:D_MSG_BUFFER
                INT 21H

                ; 입력된 문자열을 AX로 변환하여 저장해줌
                PUSH OFFSET DATA:D_MSG_BUFFER
                CALL NEAR PTR CODE:P_STRTOAX

                PUSH AX ; 세그먼트값 저장            <---------------

                ; "Segment code"문자열 출력
                MOV AH, 09H
                MOV DX, OFFSET DATA:D_MSG_SEGMENT
                INT 21H

                POP AX ; 세그먼트값 복원            ---------------->

                ; 여기에 XLAT를 사용해서 값을 Table에서 값을 찾아서 AL에 넣어줌
                MOV BX, OFFSET DATA:D_TABLE_SEGMENT
                XLAT ; MOV AL, [BX + AL] 과 같은 명령 (Table검색에 용이함)

                ; 우리의 목표인 최종 세그먼트값 출력!
                CALL NEAR PTR CODE:P_PRINT_BIN

                ; 'H'찍고
                MOV AH, 02H
                MOV DL, 'H'
                INT 21H

                ; "Bye" 메세지 출력
                CALL NEAR PTR P_CRLF
                MOV AH, 09H
                MOV DX, OFFSET DATA:D_MSG_BYE
                INT 21H

                ; Program을 종료
                MOV AX, 4C00H
                INT 21H

                ; 만약 종료하지 못하면 시스템을 정지 (생략해도 상관없음)
                CLI
                HLT

                ; 정지도 안되면 (NMI 발생시) 그냥 루프 (생략해도 상관없음)
                JMP SHORT $

; ===============================================================================
; 개행문자를 출력
P_CRLF          PROC NEAR ; void near pascal P_CRLF(void)
                MOV AH, 09H
                MOV DX, OFFSET DATA:D_MSG_CRLF
                INT 21H
                RETN
P_CRLF          ENDP

; ===============================================================================
P_STRTOAX       PROC NEAR ; int near pascal P_STRTOAX(const void near *)
                PUSH BP
                MOV BP, SP

                ; 사용될 레지스터 초기화
                XOR AX, AX
                XOR BX, BX

                MOV BX, WORD PTR [BP + 2 + 2] ; 포인터 인자를 가져옴
                MOV CL, BYTE PTR DATA:[BX + 1] ; 입력된 문자열의 길이를 CL에 대입
                ADD BX, 02H ; 실제 문자열이 저장된 Entry로 BX를 이동

L_STRTOAX_0:
                JCXZ L_STRTOAX_1
                DEC CX
                MOV DL, BYTE PTR DATA:[BX] ; [BX]를 DL에 한바이트 꺼냄
                SUB DL, 30H ; 입력된 값은 ASCII이므로 '0'에 해당하는 30H를 빼줌
                SHL DL, CL ; Shift시킴
                ADD AL, DL ; AH는 항상 0으로 예상되고 (범위가 크지 않으므로)
                INC BX ; BX를 하나 증가시켜서 입력된 다음 문자를 가르키게 함               
                JMP SHORT L_STRTOAX_0
L_STRTOAX_1:

                ; DEBUG CODE: 입력된 문자열을 확인하려고...
                PUSH AX  ; AX값을 저장
                PUSH WORD PTR [BP + 2 + 2]
                CALL P_DEBUG_INPUT
                POP AX ; AX값을 복원

                POP BP
                RETN 2
P_STRTOAX       ENDP

; ===============================================================================
; 이 함수는 AX값을 문자열로 출력하는이고 초기 BX값을 바꾸면 그에 해당하는 진수표기법으로 바뀜
P_PRINT_BIN     PROC NEAR ; void near pascal P_PRINT_BIN(AX)
                MOV BX, 16 ; 16진수 출력 (여기를 바꾸면 진수표기법이 바뀜 2는 2진법, 4는 4진법, 8은 8진법, ...)
                XOR CX, CX
L_PRINT_BIN_0:
                XOR DX, DX
                DIV BX
                CMP DX, 10
                JL L_PRINT_BIN_LESS_0
                SUB DX, 10
                ADD DX, 'A'
                JMP L_PRINT_BIN_LESS_1
L_PRINT_BIN_LESS_0:
                ADD DX, '0'
L_PRINT_BIN_LESS_1:
                PUSH DX
                INC CX
                OR AX, AX
                JNZ L_PRINT_BIN_0

;                PUSH CX
;                MOV AX, CX
;                MOV CX, 8
;                SUB CX, AX
;L_PRINT_BIN_ZERO_0:
;                JCXZ L_PRINT_BIN_ZERO_1
;                DEC CX
;                MOV AH, 02H
;                MOV DL, '0'
;                INT 21H
;                JMP SHORT L_PRINT_BIN_ZERO_0
;L_PRINT_BIN_ZERO_1:
;                POP CX


L_PRINT_BIN_1:
                POP DX
                MOV AH, 02H
                INT 21H
                LOOP L_PRINT_BIN_1
                RETN
P_PRINT_BIN     ENDP

; ===============================================================================
; DEBUG procedure
P_DEBUG_INPUT   PROC NEAR ; void near pascal P_DEBUG_INPUT(const void near *)
                PUSH BP
                MOV BP, SP

                PUSH AX ; 변환된 값을 저장             <------------------

                ; 1개 줄을 넘기고
                CALL NEAR PTR CODE:P_CRLF

                ; "Value: "문자열 출력
                MOV AH, 09H
                MOV DX, OFFSET DATA:D_MSG_CONFIRM
                INT 21H

                ; 입력된값 확인을 위해서 출력
                MOV BX, WORD PTR [BP + 2 + 2]
                ADD BL, BYTE PTR DATA:[BX + 1]
                ADC BH, 00H
                MOV BYTE PTR DATA:[BX + 2], '$' ; '$'를 붙이는 것은 문자열의 끝을 알리는것 !
                MOV AH, 09H
                MOV DX, WORD PTR [BP + 2 + 2]
                ADD DX, 02H
                INT 21H

                ; 'B'찍고
                MOV AH, 02H
                MOV DL, 'B'
                INT 21H

                ; ','찍고
                MOV AH, 02H
                MOV DL, ','
                INT 21H

                ; ' '찍고
                MOV AH, 02H
                MOV DL, ' '
                INT 21H

                ; 실제 입력된 값을 변환하여 AX에 저장했던 것을 확인
                POP AX ; 변환된 값을 복원            ----------------->
                CALL NEAR PTR CODE:P_PRINT_BIN ; AX값 확인

                ; 'H'찍고
                MOV AH, 02H
                MOV DL, 'H'
                INT 21H

                ; 1개 줄을 넘기고
                CALL NEAR PTR CODE:P_CRLF

                POP BP
                RETN 2
P_DEBUG_INPUT   ENDP

CODE            ENDS

                ASSUME DS:DATA
DATA            SEGMENT PARA PUBLIC USE16 'CLASS_DATA'
D_MSG_LOGO      DB "BIN to Segment code convert program : Code by JaeHyuk Cho$"
D_MSG_INPUT     DB "Input code   : $"
D_MSG_CONFIRM   DB "Value        : $"
D_MSG_SEGMENT   DB "Segment code : $"
D_MSG_BYE       DB "Bye"                    ; 최적화를 위해서 반드시 D_MSG_CRLF의 위에 있어야 함.
D_MSG_CRLF      DB 0DH, 0AH, '$'
D_MSG_BUFFER    DB 80 DUP (?)

COMMENT #
*** 7 segment table ***
! a b c d e f g 
---------------
0 0 0 0 0 0 0 1
1 1 0 0 1 1 1 1
2 0 0 1 0 0 1 0
3 0 0 0 0 1 1 0

4 1 0 0 1 1 0 0
5 0 1 0 0 1 0 0
6 0 1 0 0 0 0 0
7 0 0 0 1 1 1 1

8 0 0 0 0 0 0 0
9 0 0 0 1 1 0 0
A 0 0 0 1 0 0 0
b 1 1 0 0 0 0 0

C 0 1 1 0 0 0 1
d 1 0 0 0 0 1 0
E 0 1 1 0 0 0 0
F 0 1 1 1 0 0 0
#

D_TABLE_SEGMENT DB 01000000b, 01111001b, 00100100b, 00110000b
                DB 00011001b, 00010010b, 00000010b, 01111000b
                DB 00000000b, 00011000b, 00001000b, 00000011b
                DB 01000110b, 00100001b, 00000110b, 00001110b

DATA            ENDS

                ASSUME SS:STACK_AREA
STACK_AREA      SEGMENT PARA STACK USE16 'CLASS_STACK'
                DB 1024 DUP (?)
STACK_AREA      ENDS
                END L_STARTUP

; End of source
크리에이티브 커먼즈 라이센스
Creative Commons License
Posted by minzkn

트랙백 주소 :: http://blog.minzkn.com/trackback/33

댓글을 달아 주세요