본문 바로가기
어셈블리어 공부용/x86 어셈블리어(ASSEMBLY)

emu8086으로 어셈블리어 연습 [16진수를 10진수로 변환 후 출력하기]

by Redoutable 2019. 8. 15.
반응형

이번엔 AX레지스터에 16진수를 입력받았다고 가정하고,

이것을 10진수로 처리하여 출력해보겠습니다.

 

.MODEL SMALL
.CODE
ORG 100h        ;100h번지부터 코드시작

CALL MAIN       ;'MAIN'프로시저 호출
HLT             ;프로그램 중단 (MAIN 프로시저가 실행이 끝나면 HLT로 프로그램을 중단합니다.)
;------------
DECADT DB 7 DUP ('$') ;DECADT라는 바이트크기의 데이터공간을 설정. 메모리에 '$'를 7개 채운다.
;-----------
MAIN PROC NEAR  ;MAIN 프로시저의 시작


MOV AX,1234h    ;1234h라는 수를 입력받았다고 가정했습니다.
MOV BX,10       ;10으로 나누어 주기위해 BX레지스터에 10을 수록.
MOV CX,0        ;CX레지스터값을 아래에서 써야하므로 비워줍니다.

PUSH10:         ;PUSH10 라벨
MOV DX,0        ;DX레지스터를 깨끗이 청소. 여기에 나눈 결과의 나머지가 저장되야 하기때문.
DIV BX          ;AX레지스터에 있는 값을 BX레지스터에 수록되어 있는 값으로 나눕니다.

PUSH DX         ;DX레지스터에 있는 값을 스택에 저장합니다.
INC CX          ;청소해두었던 CX레지스터에 1을 더합니다. 나중에 LOOP문 제어할때 사용.

CMP AX,0        ;몫이 0인지 아닌지 확인합니다.
JNE PUSH10      ;몫이 남아있다면 진수변환을 계속합니다.

MOV SI,OFFSET DECADT ;SI레지스터에 DECADT 데이터영역의 시작주소를 수록합니다.

POP10:          ;POP10라벨
POP AX          ;AX레지스터에 스택에 있던 값을 가져옴. 스택은 나중에 들어간 값이 먼저 나옵니다.
ADD AL,'0'      ;0(30h)를 더해주어서 아스키코드 형태로 만들어줍니다.
MOV [SI],AL     ;SI가 가르키고있는 주소에 방금 아스키코드 형태로 만든 수를 저장합니다.
INC SI          ;SI가 다음 저장공간을 가르키게합니다.
LOOP POP10      ;위에서 계속 더했던 CX값이 0이 될때까지 저장공간에 데이터 수록작업을 계속합니다.

MOV DX,OFFSET DECADT ;DX에 DECADT데이터영역의 주소를 수록합니다.
MOV AH,9             ;9번 기능명령으로 DX레지스터에 수록되어있는 주소(DECADT)의 문자열을 출력.
INT 21h              ;
RET                  ;메인루틴으로 복귀
MAIN ENDP            ;MAIN 프로시저의 끝
;-----------
END

 

재차 설명드리자면, 사용자에게서 수를 입력받는게 아니라

ax레지스터에 프로그래밍으로 값을 입력시켜준 다음 출력하는

단순한 프로그램 입니다.

 

AX 레지스터에 1234h를 수록했더니, 십진수 4660을 출력해줍니다.

 

또한, DIV 명령어는 AX레지스터를 사용자가 원하는 저장소의 데이터값으로 나누는 명령입니다.

또한 DIV는 제수에 따라서 데이터가 저장되는 위치가 다릅니다.

8비트로 나누었을시 (EX: DL레지스터 OR BL 레지스터) 몫: AL 나머지: AH

16비트로 나누었을시 (EX: BX레지스터) 몫:AX 나머지:DX

따라서 자신이 어떤 수로 나누었는지 기억하고 몫과 나머지를 적절하게 처리해야합니다.

그리고 DECADT에 $을 채운 이유는, 숫자가 입력이 끝나면 그것을 문자열로 처리해야하는데

문자열로 처리하려면 반드시 $를 뒤에 붙여야 하기 때문입니다.

그러지 않으면 메모리에서 $를 만날때까지 계속해서 쓰레기값을 출력하게 됩니다.

 

반응형

댓글