174 lines
3.5 KiB
Text
174 lines
3.5 KiB
Text
;ROMAN NUMERALS MODULE
|
|
|
|
EncodeRoman:
|
|
;takes a BCD value in AX and stores its Roman numeral equivalent in ram.
|
|
|
|
call UnpackBCD
|
|
|
|
cmp dh,03h
|
|
jng continue_EncodeRoman
|
|
;roman numerals only go up to 3999.
|
|
jmp errorhandler_encodeRoman_inputTooBig
|
|
continue_EncodeRoman:
|
|
mov si,offset StringRam
|
|
;using SI as destination of roman numerals.
|
|
push ax
|
|
push cx
|
|
mov ch,0
|
|
mov cl,dh ;loop counter
|
|
cmp dh,0
|
|
jz skipThousands
|
|
encodeRoman_handleThousands:
|
|
mov al,"M"
|
|
mov [ds:si],al ;store in string ram
|
|
inc si
|
|
; call PrintChar
|
|
loop encodeRoman_handleThousands
|
|
skipThousands:
|
|
pop cx
|
|
pop ax
|
|
|
|
encodeRoman_HandleHundreds:
|
|
pushall
|
|
mov bh,0
|
|
mov bl,dl ;use bx as an offset into Roman_Lookup_Master
|
|
SHL bl,1
|
|
SHL bl,1 ;multiply by 2, we are indexing into a table with 4 bytes per row.
|
|
mov di,offset Roman_Lookup_Master
|
|
mov cx,4
|
|
getChar_Hundreds:
|
|
mov al,[bx+es:di] ;get first char index
|
|
push bx
|
|
push di
|
|
mov di,offset Roman_Hund
|
|
mov bl,al
|
|
mov al,[bx+es:di]
|
|
cmp al,0
|
|
jz skipNullChar_RomanHund
|
|
mov [ds:si],al ;store in ram
|
|
inc si
|
|
; call PrintChar
|
|
skipNullChar_RomanHund:
|
|
pop di
|
|
pop bx
|
|
inc di
|
|
loop getChar_Hundreds
|
|
popall
|
|
|
|
|
|
encodeRoman_HandleTens:
|
|
pushall
|
|
mov bh,0
|
|
mov bl,ah ;use bx as an offset into Roman_Lookup_Master
|
|
SHL bl,1
|
|
SHL bl,1 ;multiply by 2, we are indexing into a table with 4 bytes per row.
|
|
mov di,offset Roman_Lookup_Master
|
|
mov cx,4
|
|
getChar_Tens:
|
|
mov al,[bx+es:di] ;get first char index
|
|
push bx
|
|
push di
|
|
mov di,offset Roman_Tens
|
|
mov bl,al
|
|
mov al,[bx+es:di]
|
|
cmp al,0
|
|
jz skipNullChar_RomanTens
|
|
mov [ds:si],al ;store in ram
|
|
inc si
|
|
; call PrintChar
|
|
skipNullChar_RomanTens:
|
|
pop di
|
|
pop bx
|
|
inc di
|
|
loop getChar_Tens
|
|
popall
|
|
|
|
encodeRoman_HandleOnes:
|
|
pushall
|
|
mov bh,0
|
|
mov bl,al ;use bx as an offset into Roman_Lookup_Master
|
|
SHL bl,1
|
|
SHL bl,1 ;multiply by 2, we are indexing into a table with 4 bytes per row.
|
|
mov di,offset Roman_Lookup_Master
|
|
mov cx,4
|
|
getChar_Ones:
|
|
mov al,[bx+es:di] ;get first char index
|
|
push bx
|
|
push di
|
|
mov di,offset Roman_Ones
|
|
mov bl,al
|
|
mov al,[bx+es:di]
|
|
cmp al,0
|
|
jz skipNullChar_RomanOnes
|
|
mov [ds:si],al ;store in ram
|
|
inc si
|
|
; call PrintChar
|
|
skipNullChar_RomanOnes:
|
|
pop di
|
|
pop bx
|
|
inc di
|
|
loop getChar_Ones
|
|
popall
|
|
|
|
mov al,0
|
|
mov [ds:si],al ;place a null terminator at the end of the string.
|
|
ret
|
|
|
|
|
|
errorhandler_encodeRoman_inputTooBig:
|
|
push ds
|
|
push ax
|
|
LoadSegment ds,ax,@data
|
|
mov al,01h
|
|
mov byte ptr [ds:error_code],al
|
|
mov ax, offset EncodeRoman
|
|
mov word ptr [ds:error_routine],ax
|
|
|
|
LoadSegment ds,ax,@code
|
|
mov si,offset Roman_Error
|
|
call PrintString
|
|
pop ax
|
|
pop ds
|
|
stc ;set carry, allowing program to branch if error occurred.
|
|
ret
|
|
|
|
|
|
|
|
Roman_Lookup_Master db 0,0,0,0 ;0
|
|
db 0,0,0,1 ;1
|
|
db 0,0,1,1 ;2
|
|
db 0,1,1,1 ;3
|
|
db 0,0,1,2 ;4
|
|
db 0,0,0,2 ;5
|
|
db 0,0,2,1 ;6
|
|
db 0,2,1,1 ;7
|
|
db 2,1,1,1 ;8
|
|
db 0,0,1,3 ;9
|
|
|
|
Roman_Ones db 0,"IVX" ;the same pattern is used regardless of what power of 10 we're working with
|
|
Roman_Tens db 0,"XLC"
|
|
Roman_Hund db 0,"CDM"
|
|
|
|
Roman_Error db "ERROR: BAD INPUT",0
|
|
|
|
|
|
UnpackBCD:
|
|
;converts a "packed" BCD value in AX to an "unpacked" value in DX.AX
|
|
;DX is the high byte, AX is the low byte.
|
|
;CLOBBERS DX AND AX.
|
|
mov dx,0
|
|
mov dl,ah
|
|
mov ah,0
|
|
push cx
|
|
mov cl,4
|
|
rol dx,cl
|
|
;BEFORE: DX = 00XYh
|
|
;AFTER: DX = 0XY0h
|
|
ror dl,cl ;DX = 0X0Yh
|
|
|
|
rol ax,cl
|
|
;BEFORE: AX = 00XYh
|
|
;AFTER: AX = 0XY0h
|
|
ror al,cl ;AX = 0X0Yh
|
|
pop cx
|
|
ret
|