News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Arabic to Roman numerals

Started by sheep, January 16, 2005, 07:40:16 PM

Previous topic - Next topic

sheep

Longer than I thought it would turn out:

a2r:
; esp+8 = str_ptr, esp+4 = value
mov eax,DWORD PTR [esp+8]
cmp DWORD PTR [esp+4],0
jnz @F
mov WORD PTR [eax],004eh ; nullae
retn 8
@@:
test DWORD PTR [esp+4],0FFFF0000h
jz @F
mov WORD PTR [eax],003fh ; word values only
retn 8
@@:
push ebp
mov ebp,eax
mov eax,DWORD PTR [esp+8]
mov ecx,1000
xor edx,edx
div ecx
or eax,eax
jz nothousands
@@:
mov BYTE PTR [ebp],'M'
add ebp,1
sub eax,1
jnz @B
nothousands:
mov eax,edx
mov ecx,500
xor edx,edx
div ecx
or eax,eax
jz no5hundreds
@@:
mov BYTE PTR [ebp],'D'
add ebp,1
sub eax,1
jnz @B
no5hundreds:
mov eax,edx
mov ecx,100
xor edx,edx
div ecx
or eax,eax
jz nohundreds
@@:
mov BYTE PTR [ebp],'C'
add ebp,1
sub eax,1
jnz @B
nohundreds:
mov eax,edx
db 0d4h,50 ; aam 50
or ah,ah
jz nofifties
@@:
mov BYTE PTR [ebp],'L'
add ebp,1
sub ah,1
jnz @B
nofifties:
db 0d4h,10
or ah,ah
jz notens
@@:
mov BYTE PTR [ebp],'X'
add ebp,1
sub ah,1
jnz @B
notens:
db 0d4h,5
or ah,ah
jz nofives
@@:
mov BYTE PTR [ebp],'V'
add ebp,1
sub ah,1
jnz @B
nofives:
or al,al
jz noones
@@:
mov BYTE PTR [ebp],'I'
add ebp,1
sub al,1
jnz @B
noones:
mov BYTE PTR [ebp],0
pop ebp
retn 8


I just put this together so I havn't put much thought into it, but what would be the best way to go about doing subtractive notation?

raymond

The easiest way would most probably be the use of lookup tables for units, tens, hundreds, etc.

Raymond
When you assume something, you risk being wrong half the time
http://www.ray.masmcode.com

sheep

Well, it was easy making something that converts Roman numbers (case insensitive) to Arabic that can handle subtractive notation:


.data

r2a_trans1 dw 100,500,0,0,0,0,1,0,0,50,1000,0,0,0,0,0,0,0,0,5,0,10

.code

r2a:
mov edx,DWORD PTR [esp+4]
xor eax,eax
cmp BYTE PTR [edx],'N'
jnz @F
retn 4
@@:
push ebp
xor ebp,ebp
xor ecx,ecx
push ebx
mov ebx,offset r2a_trans1
jmp j
@@:
add edx,1
j:
cmp BYTE PTR [edx],0
jne @B
@@:
cmp edx,DWORD PTR [esp+12]
je @F
sub edx,1
mov al,BYTE PTR [edx]
cmp al,99
js capital_x
sub al,32
capital_x:
sub al,67
mov ax,[ebx+eax*2]
cmp eax,ebp
je next1
jg next2
sub ecx,eax
jmp next
next2:
mov ebp,eax
next1:
add ecx,eax
next:
xor ah,ah
jmp @B
@@:
pop ebx
pop ebp
mov eax,ecx
retn 4


Submitting it here for review because it's somewhat related.

AeroASM


dwtoroman proc dwValue:DWORD,lpBuffer:DWORD

push edi

mov eax,dwValue
mov edi,lpBuffer
mov ecx,eax ;backup of eax

Test50:
sub eax,50 ;is it bigger than 50?
js  Smallerthan50
mov byte ptr [edi],4Ch ;if it is, then put L into the buffer
mov ecx,eax ;make a new backup
add edi,1
jmp Test10
Smallerthan50:
mov eax,ecx ;eax is messed up so restore backup

Test10:
xor edx,edx
Greaterthan10:
sub eax,10 ;is it bigger than 10?
js  Smallerthan10
mov byte ptr [edi],58h ;if it is, then put X into the buffer
add edx,1 ;keep count of the number of X's
add edi,1
mov ecx,eax ;make a new backup
jmp Greaterthan10 ;try again
Smallerthan10:
mov eax,ecx ;eax is messed up so restore backup
sub edx,4 ;did we put in XXXX?
jnz Finish10
sub edi,2 ;if so, then replace it with XL
mov byte ptr [edi-1],4Ch
Finish10:

Test5:
sub eax,5
js  Smallerthan5
mov byte ptr [edi],56h
mov ecx,eax
add edi,1
jmp Test1
Smallerthan5:
mov eax,ecx

Test1:
xor edx,edx
Greaterthan1:
sub eax,1
js  Smallerthan1
mov byte ptr [edi],49h
mov ecx,eax
add edx,1
add edi,1
jmp Greaterthan1
Smallerthan1:
sub edx,4
jnz Finish1
sub edi,2
mov byte ptr [edi-1],56h
Finish1:
mov byte ptr [edi],0

pop edi

ret

dwtoroman endp

AeroASM

Sorry, I clicked Post by accident before saying this:

I hope my comments help you to understand the algorithm.
At the moment, it only works for numbers from 1 to 99, but you can easily extend it by copying the previous code and adjusting the numbers.

I am an amateur, so I have no idea of how to optimize this. If someone could tell me... then thanks in advance.