## Function DMS

Bare metal programming in PureBasic, for experienced users
Mesa
Enthusiast
Posts: 216
Joined: Fri Feb 24, 2012 10:19 am

### Function DMS

Do you have in your archive, a function in assembler to convert decimal degrees to degree minutes seconds ?

Like that:
dms(10.50) = 10.30 (10 degrees and 30 minutes)
dms(10.50833333) = 10.3030

Thanks.

M.
Helle
Enthusiast
Posts: 177
Joined: Wed Apr 12, 2006 7:59 pm
Location: Germany
Contact:

### Re: Function DMS

For fun with FPU, SSE and SSE2; PB 64-bit:

Code: Select all

``````;PB 5.61 (x64)
Procedure.s DMS_FPU(DD.d)
!fstcw word[CW_FPU]
!mov ax,[CW_FPU]
!or [CW_FPU],0000110000000000b  ;no rounding, truncation
!fldcw word[CW_FPU]

!fld qword[p.v_DD]         ;no check of range!
!fist word[DMS_FPU]
!fisub word[DMS_FPU]
!fmul qword[V60_FPU]
!fist word[DMS_FPU+2]
!mov [CW_FPU],ax
!fldcw word[CW_FPU]        ;restore ControlWord, rounding seconds
!fisub word[DMS_FPU+2]
!fmul qword[V60_FPU]
!fistp word[DMS_FPU+4]     ;second as rounded integer

DMS_FPU\$ = Str(PeekW(?DMS_FPU)) + "." + RSet(Str(PeekW(?DMS_FPU + 2)), 2, "0") + RSet(Str(PeekW(?DMS_FPU + 4)), 2, "0")
ProcedureReturn DMS_FPU\$

DataSection
DMS_FPU:                 ;Degree Minute Second
!DMS_FPU  dq ?
!V60_FPU  dq 60.0
!CW_FPU   dw ?         ;FPU-ControlWord
EndDataSection

EndProcedure

Debug DMS_FPU(10.50833333)
Debug DMS_FPU(10.50)
Debug DMS_FPU(123.987654)

Debug "============="

Procedure.s DMS_SSE(DD.f)
!cvttss2si eax,xmm0
!mov word[DMS_SSE],ax
!cvtsi2ss xmm1,eax
!subss xmm0,xmm1
!mulss xmm0,[V60_SSE]
!cvttss2si eax,xmm0
!mov word[DMS_SSE+2],ax
!cvtsi2ss xmm1,eax
!subss xmm0,xmm1
!mulss xmm0,[V60_SSE]
!cvtss2si eax,xmm0
!mov word[DMS_SSE+4],ax

DMS_SSE\$ = Str(PeekW(?DMS_SSE)) + "." + RSet(Str(PeekW(?DMS_SSE + 2)), 2, "0") + RSet(Str(PeekW(?DMS_SSE + 4)), 2, "0")
ProcedureReturn DMS_SSE\$

DataSection
DMS_SSE:                 ;Degree Minute Second
!DMS_SSE  dq ?
!V60_SSE  dd 60.0
EndDataSection

EndProcedure

Debug DMS_SSE(10.50833333)
Debug DMS_SSE(10.50)
Debug DMS_SSE(123.987654)

Debug "============="

Procedure.s DMS_SSE2(DD.d)
!cvttsd2si eax,xmm0
!mov word[DMS_SSE2],ax
!cvtsi2sd xmm1,eax
!subsd xmm0,xmm1
!mulsd xmm0,[V60_SSE2]
!cvttsd2si eax,xmm0
!mov word[DMS_SSE2+2],ax
!cvtsi2sd xmm1,eax
!subsd xmm0,xmm1
!mulsd xmm0,[V60_SSE2]
!cvtsd2si eax,xmm0
!mov word[DMS_SSE2+4],ax

DMS_SSE2\$ = Str(PeekW(?DMS_SSE2)) + "." + RSet(Str(PeekW(?DMS_SSE2 + 2)), 2, "0") + RSet(Str(PeekW(?DMS_SSE2 + 4)), 2, "0")
ProcedureReturn DMS_SSE2\$

DataSection
DMS_SSE2:                ;Degree Minute Second
!DMS_SSE2  dq ?
!V60_SSE2  dq 60.0
EndDataSection

EndProcedure

Debug DMS_SSE2(10.50833333)
Debug DMS_SSE2(10.50)
Debug DMS_SSE2(123.987654)
``````
Mesa
Enthusiast
Posts: 216
Joined: Fri Feb 24, 2012 10:19 am

### Re: Function DMS

Woah, very impressive.
Thanx.

DMS_FPU(DD.d) works very well with x86 but not DMS_SSE(DD.f) and DMS_SSE2(DD.d).

Could you tell me why DMS_SSE(DD.f) and DMS_SSE2(DD.d) return 0 with x86 ?
( they use 32b eax and xmm0,1 so they should work in x86, no ?)
Thanx.

M.