News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

qword to ascii conversion

Started by allynm, June 06, 2012, 02:36:32 AM

Previous topic - Next topic

raymond

#90
Most Microsoft programmers working on the Windows OS probably don't know anything about FPU instructions. However, they do use (maybe unknowingly) the FPU general registers without preserving their content. I doubt that they would change any of the control registers. If you want to see Windows in action with fpu general registers, write a test program loading some values on the FPU and then use the MessageBox API to display whatever you like. Then run that program with Ollydbg and watch the content of the fpu registers when the API is called.

THEREFORE, I consider all general and control FPU registers as free to use and would personally not preserve any of them because of other external programs which may use them. I may preserve them strictly for the internal needs of my own program. (Because the Fpulib would be used within one's program, and some of the data within registers might be required to be preserved for the user, each of the functions within that library does an initial fpu save and a fpu restore on exit.)

As for using the FINIT at the very beginning of a program, its only function would be to change the precision control from double-precision (64-bit) to extended double-precision (80-bit); all other general and control registers are provided initialized to an exe upon loading it. Obviously, if you need to change any of the controls for specific purposes, you adjust them as needed but there is no need to preserve them unless other parts of your own program expects them to have them preserved.

The ffree st(7) instruction by itself would not necessarily make the fpu behave. It would only guarantee that the next immediately following fld or fild instruction would be carried out without an exception being raised.

To all those other members following this thread without much knowledge about the FPU, you may want to have an initial quick glance at http://www.ray.masmcode.com/tutorial/index.html
Whenever you assume something, you risk being wrong half the time.
http://www.ray.masmcode.com

jj2007

Ray's tutorial is an absolute "must read" indeed. Yes, I had forgotten MessageBox, it erases ST(6) and ST(7). Which is normally not a problem, nobody uses the fpu so deeply and then launches a MsgBox while intermediate results are still in the fpu.

In short: don't worry. Do what you have to do with the fpu.

NoCforMe

Heh; nothing like reviving a 6-year-old thread. Like Lazarus.

So here's my entry for the quadword-to-ASCII conversion contest. Won't win any prizes for speed or cleverness, but I might get an honorable mention for simplicity. Tested and it works. Uses no multiplication or division.

I got the successive-subtraction idea from a link that JJ posted a long time ago.

;===============================================
; Q2A -- Unsigned quadword to ASCII converter
;
; Uses successive subtraction (+ addition),
; no multiplication or division.
;===============================================

        .data

PowersOf10 LABEL QWORD
DQ 10000000000000000000
DQ 1000000000000000000
DQ 100000000000000000
DQ 10000000000000000
DQ 1000000000000000
DQ 100000000000000
DQ 10000000000000
DQ 1000000000000
DQ 100000000000
DQ 10000000000
DQ 1000000000
DQ 100000000
DQ 10000000
DQ 1000000
DQ 100000
DQ 10000
DQ 1000
DQ 100
DQ 10

ASCIIbuffer DB 22 DUP(?)

        .code

;====================================================================
; Q2A()
;
; Convert 64-bit unsigned integer (QWORD) to ASCII decimal string
;
; On entry,
; EDX:EAX = QWORD value to convert
;
; Returns:
; EAX--> buffer containing numeric string (points to 1st non-zero char.)
;
; Tested 8/17/23 --works--
;====================================================================
Q2A PROC

PUSH EBX
PUSH EDI

MOV EBX, OFFSET PowersOf10
MOV EDI, OFFSET ASCIIbuffer

MOV CH, 19 ;Loop counter.
sublp: XOR CL, CL ;Subtraction counter.
resub: INC CL
SUB EAX, DWORD PTR [EBX]
SBB EDX, DWORD PTR [EBX + SIZEOF DWORD]
JNC resub

backup: DEC CL ;CL = this digit.
ADD CL, '0'
MOV [EDI], CL
INC EDI

; Add back power of 10 to make up for overshoot:
ADD EAX, DWORD PTR [EBX]
ADC EDX, DWORD PTR [EBX + SIZEOF DWORD]
ADD EBX, SIZEOF QWORD ;Next power of 10.
DEC CH
JNZ sublp
ADD AL, '0'
XOR AH, AH
STOSW ;Store last char. + terminator.

; Leading zero suppression:
MOV EDX, OFFSET ASCIIbuffer
MOV ECX, 19
zloop: CMP BYTE PTR [EDX], '0'
JNE done
INC EDX
LOOP zloop

done: MOV EAX, EDX
POP EDI
POP EBX
RET

Q2A ENDP
Assembly language programming should be fun. That's why I do it.