[Assembly] 숫자 3개를 입력받아 가장 큰수를 16진수로 출력하기

JongHyeon_Seo·2022년 5월 17일
0

문제

화면에서 10진수 숫자(0~65535 사이의 값) 3개를, 차례로 입력 받은 뒤, 그 중에 가장 큰 값을 16진수로 화면에 출력한다

풀이

1. 숫자를 입력받아 저장

어셈블리어는 입력을 받을시 문자열로 저장하기 때문에 입력을 받아서 숫자로 변환을 해주어야 한다

입력을 받기위해서는 인터럽트 21H에서 0AH를 호출하면 된다
문자열이 입력될 때는 [버퍼 크기] + [문자열 길이] + [입력된 문자열] 순으로 저장되기 때문에 이를 염두해두면서 코딩을 해야한다

사용할 변수들을 데이터로 저장해준다

CRLF	DB	0AH, 0DH, "$"			; 줄바꿈을 해주는 역할
msg1	DB	"First Number: ", "$"	; 출력할 문자열을 미리 저장
msg2	DB	"Second Number: ", "$"
msg3	DB	"Third Number: ", "$"
msg4	DB	"Largest Number: ", "$"
msgs	DW	OFFSET msg1, OFFSET msg2, OFFSET msg3, OFFSET msg4	
max_len	DB	6			 			; 문자열의 버퍼의 크기를 저장
act_len	DB	?						; 문자열의 길이를 저장
str1	DB 	6	dup(0)				; 입력된 문자열을 저장
array	DW	0, 0, 0					; 숫자를 저장할 배열

입력을 받으면 문자 '0'만큼을 빼서 숫자 값을 구해준다

	MOV BX, 0			; 인덱스와 반복 횟수로 사용할 레지스터
INPUT:
	MOV	DX, msgs[bx]		
	MOV	AH, 9
	INT	21H

	MOV	DX, OFFSET max_len	; 문자열을 입력 받는다.
	MOV	AH, 10			로 저장
	INT	21H			

	MOV	DX, OFFSET CRLF	
	MOV	AH, 9
	INT	21H

	MOV	SI, OFFSET str1	
	ADD	SI, 4			; 최대 5자리수이므로 1의 자리로 주소 이동
	mov	CX, 1			; 자릿수만큼 곱해주기 위해 cx 1을 줌
CAST:
	MOV	AX, 0			
	MOV	AL, [si]			
	CMP	AL, '0'			; 문자 0과 비교하여 더 작으면 점프
	JB	pass			
	SUB	AX, '0'			; 그렇지 않을 경우 문자 0만큼 빼서 숫자 값을 구함
	MUL	CX				; 자릿수에 해당하는 값을 곱해준다
	ADC	array[bx], AX		
	MOV	AX, CX			
	MOV	CX, 10			
	MUL	CX			
	MOV	CX, AX			
PASS:
	DEC	SI				; 주소를 하나씩 줄여가며 계산
	CMP	SI, OFFSET str1	; 시작 주소와 같으면 탈출한다	
	JB	cast_end			 
	JMP	cast			
CAST_END:
	ADD	BX, 2			; word 단위 이므로 인덱스는 2씩 증가
	CMP	BX, 6			
	JE	input_end		
	JMP	input			

INPUT_END:

2. 가장 큰 수 찾기

조건 점프를 사용하여 가장 큰 수를 구할 수 있다

MOV	BX, array[0]			; 첫번째 수 BX에 저장
	CMP	BX, array[2]		
	JAE	comp				; 같거나 큰 경우 comp로 점프
	MOV	BX, array[2]		; 아니면 BX에 두번째 수를 저장

COMP:	CMP	BX, array[4]	; bx와 세번째 숫자를 비교한다
	MOV	cx, 4				
	JAE	hex					; hex 구간을 4번 반복하기 위해 CX에 4를 준다
	MOV	BX, array[4]		; 비교후 가장 큰 수가 BX에 저장됨

3. 16진수로 변환

출력을 위해 아스키코드를 이용하여 16진수에 해당하는 문자로 변환해준다

HEX:
	MOV AX, BX			
	SHR	BX, 1			; 오른쪽으로 한바이트 쉬프트 해둔다
	SHR	BX, 1
	SHR BX, 1
	SHR	BX, 1
	AND	AX, 0fH			; 하위 4비트를 0xf와 and연산하여 값을 구한다
	
	CMP	AX, 0aH			; 값이 10이 넘으면 알파벳으로 표기하므로 비교
	JL	save			
	ADD	AX, 7			; 아스키코드로 문자 957, A는 65이므로 
						; 10이상이면 7을 더해주어 알파벳출력이 가능하게 해준다
SAVE:	
	PUSH	AX			; 변환된 ax를 스택에 넣어준다
	LOOP	hex			

4. 출력

출력을 하기위해서는 인터럽트 21H에서 02H와 09H를 호출하면 된다
02H는 한 문자를 출력할때 사용하고 09H는 문자열을 출력할 때 사용한다

스택에 저장해둔 값을 POP하여 문자로 변환후 출력해준다

	MOV	DX, msgs[6]		; 저장된 문자열을 출력한다
	MOV	AH, 09
	INT	21H

	MOV	DX, '0'			; 16진수 표기를 위해 0x를 먼저 출력해준다
	MOV	AH, 2
	INT	21H
	
	MOV	DX, 'x'
	MOV	AH, 2
	INT	21H
	
	MOV	CX, 4			; 4바이트이므로 4번 반복하여 출력한다
PRINT:
	POP	DX				; 저장된 값을 dx로 pop한다
	ADD	DX, '0'			; 문자 0만큼 더해주어 문자로 출력되게 한다
	MOV	AH, 2	
	INT	21h

	LOOP	print			

	MOV	AH, 4CH			; 프로그램 종료 인터럽트
	INT	21H

전체 코드

MAIN SEGMENT
	ASSUME	CS:MAIN, DS:MAIN

	MOV	AX, CS
	MOV	DS, AX
	MOV	BX, 0
INPUT:
	MOV	DX, msgs[BX]
	MOV	AH, 9
	INT	21H

	MOV	DX, OFFSET max_len
	MOV	AH, 0AH
	INT	21H

	MOV	CX, OFFSET str1
	ADD	CL, act_len
	ADC	CH, 0

	MOV	DX, OFFSET CRLF
	MOV	AH, 9
	INT	21H

	MOV	SI, OFFSET str1
	ADD	SI, 4
	MOV	CX, 1
CAST:
	MOV	AX, 0
	MOV	AL, [SI]
	CMP	AL, '0'
	MUL	CX
	ADC	array[BX], AX

	MOV	AX, CX
	MOV	CX, 10
	MUL	CX
	MOV	CX, AX
PASS:
	DEC	SI
	CMP	SI, OFFSET str1
	JB	CAST_END
	JMP	CAST
CAST_END:
	ADD	BX, 2
	CMP	BX, 6
	JE	INPUT_END
	JMP	INPUT
INPUT_END:
	MOV	BX, array[0]
	CMP	BX, array[2]
COMP:
	CMP	BX, array[4]
	MOV	CX, 4
	JAE	HEX
	MOV	BX, array[4]
HEX:
	MOV	AX, BX
	SHR 	BX, 1
	SHR	BX, 1
	SHR	BX, 1
	SHR	BX, 1
	AND	AX, 0FH

	CMP	AX, 0AH
	JL	SAVE
	ADD	AX, 7
SAVE:
	PUSH	AX
	LOOP	HEX

	MOV	DX, msgs[6]
	MOV	AH, 9
	INT 	21H

	MOV	DX, '0'
	MOV	AH, 2
	INT	21H

	MOV	DX, 'x'
	MOV	AH, 2
	INT	21H

	MOV	CX, 4
PRINT:
	POP	DX
	ADD	DX, '0'
	MOV	AH, 2
	INT 	21H
	LOOP	PRINT

	MOV	AH, 4CH
	INT 	21H

CRLF	DB	0AH, 0DH, "$"
msg1 	DB	"First Number: ", "$"
msg2	DB	"Second Number: ", "$"
msg3	DB	"Third Number: ", "$"
msg4	DB	"Largest Number: ", "$"
msgs	DW	OFFSET msg1, OFFSET msg2, OFFSET msg3, OFFSET msg4
max_len	DB	6
act_len	DB	?
str1	DB	6	dup(0)
array	DW	0, 0, 0

MAIN	ENDS
		END
profile
코딩 코딩

0개의 댓글