반응형
Hello World 다음으로 예제로 많이 사용되고있는 99 Bottles of Beer 노래 가사 출력하기 입니다.
.MODEL SMALL
.CODE
ORG 100h
PROG:
JMP MAIN
;------------------------------
BEERS DB 63h ;맥주의 갯수 99개.
BEER1 DB ' BOTTLES OF BEER ON THE WALL, $'
BEER2 DB ' BOTTLES OF BEER.$'
BEER3 DB 'TAKE ONE DOWN AND PASS IN AROUND ,$'
BEER4 DB ' BOTTLES OF BEER ON THE WALL.$'
NOBEER DB 'no more bottles of beer on the wall.$'
NOBEER1 DB 'No more bottles of beer on the wall, no more bottles of beer.$'
NOBEER2 DB 'Go to the store and buy some more, 99 bottles of beer on the wall.$'
CRLF DB 0Dh,0Ah,'$' ;다음줄로 넘어가기
;-----------------------------
MAIN PROC NEAR
TOP:
CMP BEERS,0 ;BEERS에 있는 데이터(맥주 갯수)가 0인지 아닌지 확인.
JE ENND ;0이라면 ENND로 분기.
HEYBEERS: ;맥주 갯수 표시하는 곳.
LEA SI,BEERS ;BEERS가 존재하는 주소를 SI 레지스터에 저장.
MOV AX,[SI] ;SI 레지스터가 가르키고 있는 주소의 데이터를 AX 레지스터에 저장.
AND AX,000000011111111b ; 하위바이트만 필요하므로 상위 바이트는 00으로 만들어줍니다.
MOV CX,0 ;진수변환 앞서 청소.
PUSHDECA: ;
MOV DX,0 ;진수변환 앞서 청소
MOV BX,10 ;10으로 나누어야 하므로 BX레지스터 10 수록.
DIV BX ;AX 레지스터를 BX로 나눔.
PUSH DX ;DX레지스터값(나머지)을 스택에 저장.
INC CX ;CX 레지스터 1 증가시킴.
CMP AL,0 ;AX레지스터(몫)이 0인가?
JNE PUSHDECA ;0이 아니라면 진수변환 계속.
POPDECA:
POP DX ;스택에 있는 값 DX 레지스터로 가져오기.
ADD DX,30h ;DX레지스터에 30h 더해서 아스키코드화 하기.
MOV AH,02 ;1글자를 출력하는 기능번호.
INT 21h ;실행
DEC CX ;CX값 1 감소시키기.
CMP CX,0 ;CX값이 0인가?
JNE POPDECA ;0이 아니라면 출력 계속함.
;-----------------
POP CX ;CX값 가져오기 (가사 옮겨다닐때 필요한 값임.)
CMP CX,1 ;CX값이 1인가?
JE NEXT ;1이라면 다음 가사로.
CMP CX,2 ;CX값이 2인가?
JE NEXT2 ;2라면 다다음 가사로.
;-----------------
LEA DX,BEER1 ;BEER1 데이터영역 주소 DX레지스터로 가져오기.
MOV AH,9 ;문자열을 출력하는 기능번호
INT 21h ;실행
MOV CX,1 ;CX레지스터에 1 수록. (그 다음 가사로 넘어가게 하기위하여.)
PUSH CX ;CX값 스택에 저장.
JMP HEYBEERS ; 맥주 갯수 표시하기.
NEXT:
LEA DX,BEER2 ;BEER2 데이터영역 주소 DX레지스터로 가져옴.
MOV AH,9 ;문자열 출력
INT 21h ;실행
LEA DX, CRLF ;CRLF데이터영역 주소 DX로 가져옴. (줄바꾸기)
MOV AH,9 ;문자열 출력
INT 21h ;실행
LEA DX,BEER3 ;BEER2 데이터영역 주소 DX레지스터로 가져옴.
MOV AH,9 ;문자열 출력
INT 21h ;실행
DEC BEERS ;BEERS데이터영역 값 1 감소시키기. (맥주가 하나 줄었다.)
MOV CX,2 ;다다음 가사로 출력하게 하기 위하여 CX레지스터에 2 수록.
PUSH CX ;CX값 스택에 저장.
OR BEERS,00000000b ;BEERS 데이터영역값이 0인가?
JZ NO ;0 이라면 NO로 분기. (작동메커니즘은 플래그와 관련있음.)
;CMP BEERS.0 ;위 코드는 이 코드와 완벽하게 똑같이 동작합니다.
;JE NO
JMP HEYBEERS ;맥주 갯수를 출력한다.
NEXT2:
LEA DX,BEER4 ;BEER2 데이터영역 주소 DX레지스터로 가져옴.
MOV AH,9 ;문자열 출력
INT 21h ;실행
LEA DX, CRLF ;CRLF데이터영역 주소 DX로 가져옴. (줄바꾸기)
MOV AH,9 ;문자열 출력
INT 21h ;실행
INT 21h ;실행 (엔터키 두 번 누른 효과.)
JMP HEYBEERS ;맥주 갯수 출력
NO: ;맥주가 1개 남았었고 이제 0개일 때.
LEA DX,NOBEER ;NOBEER 데이터영역 주소 DX레지스터로 가져옴.
MOV AH,9 ;문자열 출력
INT 21h ;실행
LEA DX, CRLF ;CRLF데이터영역 주소 DX로 가져옴. (줄바꾸기)
MOV AH,9 ;문자열 출력
INT 21h ;실행
INT 21h ;실행 (엔터키 두 번 누른 효과.)
JMP TOP ;맨 위로 올라가서 맥주갯수가 0인지 아닌지 확인.
;--------------------
ENND:
LEA DX,NOBEER1 ;NOBEER1 데이터영역 주소 DX레지스터로 가져옴.
MOV AH,9 ;문자열 출력
INT 21h ;실행
LEA DX, CRLF ;CRLF데이터영역 주소 DX로 가져옴. (줄바꾸기)
INT 21h ;실행
LEA DX,NOBEER2 ;NOBEER2 데이터영역 주소 DX레지스터로 가져옴.
INT 21h ;실행
HLT ;프로그램 중단.
MAIN ENDP
END PROG
반응형
'어셈블리어 공부용 > x86 어셈블리어(ASSEMBLY)' 카테고리의 다른 글
emu8086으로 어셈블리어 연습 [ROL 명령어로 2의 거듭제곱 단위로 수 나열하기] (5) | 2019.08.18 |
---|---|
emu 8086으로 어셈블리어 연습 [16진수 음수(보수) 10진수로 출력하기] (0) | 2019.08.18 |
emu8086으로 어셈블리어연습 [어셈블리어 구구단] (2) | 2019.08.18 |
emu8086으로 어셈블리어연습 [비디오램에 직접 접근 하여 테트리스 미노 그리기] (0) | 2019.08.18 |
emu8086 어셈블리어 연습 [이중루프문] (0) | 2019.08.18 |
댓글