반응형
.MODEL SMALL
.CODE
ORG 100h
PROG:
CALL MAIN ;MAIN 프로시저 불러오기
HLT ;MAIN 프로시저가 끝나면 프로그램을 중단시킨다.
BLANK1 DB 'X$' ;구구단 출력시에 x 출력을 담당하는 데이터영역입니다.
BLANK2 DB '=$' ;구구단 출력시에 = 출력을 담당하는 데이터영역입니다.
CRLF DB 0Dh,0Ah,'$' ;캐리지리턴, 라인피드 (줄바꿈)를 담당하는 데이터영역입니다.
MAIN PROC NEAR ;메인 프로시저 시작.
MOV AL,2 ;구구단의 시작은 2 x
MOV BL,1 ;1 이니까 사용할 레지스터에 데이터를 수록합니다.
MOV CX,0 ;구구단 출력에 앞서서 cx레지스터를 청소합니다.
TOP:
PUSH AX ;AX값을 잠시 스택에 저장합니다. (복사되어 스택에 저장되므로 레지스터값은 변함없음.)
; (X * Y =) 출력하기.
MOV AH,02 ;한 문자 출력하는 기능번호 AH에 수록.
MOV DL,AL ;DL레지스터에 AL레지스터 값을 전달합니다. (이 값은 구구단 X * Y 중 X에 해당합니다.)
ADD DL,30h ;30h를 더해서 아스키코드화 합니다. (2 = 32h)
INT 21h ;실행 (X가 출력됨.)
LEA DX,BLANK1 ;BLANK1 데이터영역 주소를 DX레지스터에 저장합니다. (X * Y 중에서 *에 해당함.)
MOV AH,09 ;문자열을 출력하는 기능번호 AH에 수록.
INT 21h ;실행 (X(*) 출력됨.)
MOV AH,02 ;다시 한 문자를 출력해야 하므로 AH 레지스터에 2 수록.
MOV DL,BL ;DL레지스터에 BL레지스터값을 전달합니다. (이 값은 구구단 X * Y중 Y에 해당합니다.)
ADD DL,30h ;30h를 더해서 아스키코드화 합니다. (1 = 31h)
INT 21h ;실행 (Y이 출력됨.)
LEA DX,BLANK2 ;DX 레지스터에 BLANK2데이터영역의 주소를 저장합니다.
MOV AH,09 ;문자열을 출력하는 기능번호 수록
INT 21h ;실행 ( = 가 출력됨.)
POP AX ;저장해 두었던 값을 스택에서 AX레지스터로 가져옵니다.
PUSH AX ;진수변환 하면서 AX레지스터를 사용해야 하므로 다시한번 스택에 AX레지스터값을 저장합니다.
MUL BL ; AL레지스터를 BL레지스터에 있는 값으로 곱셈(X*Y)합니다. 결과는 AX레지스터에 리턴됩니다.
INC BL ; BL레지스터값을 늘립니다. (X*Y중에서 Y값 늘림.)
PUSH BX ; 진수변환때 BX레지스터를 사용해야 하므로, BX레지스터값을(Y값을) 스택에 저장합니다.
MOV CX,0 ; 진수변환 앞서 청소하기
;16진수 10진수로 변환한다음 스택에 저장하고 스택에 저장한걸 꺼내어 출력하기.
PUSHDECA:
MOV DX,0 ;진수변환 앞서 DX값 청소
MOV BX,10 ;10진수 변환은 10으로 나누어 나머지를 나열하는것이므로 10 수록.
DIV BX ;AX레지스터를 BX레지스터값으로 나눕니다.
PUSH DX ;DX레지스터값(나머지)를 스택에 저장합니다.
INC CX ;CX값을 1 증가시킵니다. (출력할때 자릿수 세는걸로 쓰는용도임.)
CMP AX,0 ;AX레지스터(몫)이 0인가?
JNE PUSHDECA ;아니라면 진수변환 계속.
POPDECA:
POP DX ;스택에서 DX레지스터로 데이터를 가져옵니다. (결과적으로 나머지가 역순으로 꺼내어짐.)
ADD DX,30h ;DX레지스터에 30h를 더하여 아스키코드화함.
MOV AH,02 ;한 글자를 출력하는 기능번호 준비
INT 21h ;실행
DEC CX ;CX값을 1 감소시킵니다.
CMP CX,0 ;CX값이 0인가? (모든 자릿수가 출력되었는지?)
JNE POPDECA ;아니라면 출력을 계속한다.
;여기서 X*Y=XY 가 완전히 출력되었음.
MOV DL,' ' ;DL에 공백(아스키코드로 20h) 수록.
MOV AH,02 ;한 글자를 출력하는 기능번호 준비
INT 21h ;실행
POP BX ;스택에 보전해두었던 데이터(Y)를 BX에 그대로 가져옴.
CMP BL,10 ;BX가 10인가?
JE SEC ;10이라면 SEC로 보냄.(구구단은 9까지이므로 여기서 끊음.)
POP AX ;스택에 보전해두었던 데이터(X)를 AX에 그대로 가져옴.
JMP TOP ;구구단 출력을 계속한다.
SEC:
POP AX ;스택에 보전해두었던 데이터(X)를 AX에 그대로 가져옴.
MOV BL,1 ;BL(Y값)을 1로 초기화한다.
INC AL ;AL(X값)에 1을 더한다.
CMP AL,10 ;그런데 AL이 10인가?
JE ENND ;AL이 10이라면 끝으로 보냄.
PUSH AX ;AX값(X값)을 스택에 보존. 줄바꿀때 AX레지스터 사용해야함.
LEA DX,CRLF ;줄바꿈실행
MOV AH,9
INT 21h
POP AX ;AX값(X값) 다시 가져옴.
JMP TOP
ENND:
RET ;MAIN PROC에서 벗어나서 메인루틴으로 복귀한다.
MAIN ENDP
END PROG
모양이 이쁘지는 않지만 구구단 입니다.
어셈블리어에서 구구단을 짜보니까 상당히 번거롭네요.
반응형
'어셈블리어 공부용 > x86 어셈블리어(ASSEMBLY)' 카테고리의 다른 글
emu 8086으로 어셈블리어 연습 [16진수 음수(보수) 10진수로 출력하기] (0) | 2019.08.18 |
---|---|
emu8086으로 어셈블리어연습 [99 Bottles of Beer] (0) | 2019.08.18 |
emu8086으로 어셈블리어연습 [비디오램에 직접 접근 하여 테트리스 미노 그리기] (0) | 2019.08.18 |
emu8086 어셈블리어 연습 [이중루프문] (0) | 2019.08.18 |
어셈블리어 INT 21h 정리 (0) | 2019.08.17 |
댓글