The MASM Forum

General => The Campus => Topic started by: NoCforMe on July 12, 2022, 09:16:26 AM

Title: QWORD conversion function in MASM32 libraries?
Post by: NoCforMe on July 12, 2022, 09:16:26 AM
Any chance there's a QWORD (to ASCII) converter somewhere in the MASM32 stuff? I looked in the help file but only found info on DWORD routines. Suppose I could write one myself, but why reinvent that particular wheel?
Title: Re: QWORD conversion function in MASM32 libraries?
Post by: jj2007 on July 12, 2022, 09:20:18 AM
http://masm32.com/board/index.php?topic=221.0

If speed is not an issue:
include \masm32\include\masm32rt.inc

.data
MyQ QWORD 12345678901234567890

.code
start:
  printf("The value of MyQ is %llu\n", MyQ)
  inkey "hit any key"
  exit

end start


If speed is important, try MasmBasic Str$(MyQ), it's a factor 3.6 faster than CRT printf().
Title: Re: QWORD conversion function in MASM32 libraries?
Post by: NoCforMe on July 12, 2022, 09:35:53 AM
Quote from: jj2007 on July 12, 2022, 09:20:18 AM
http://masm32.com/board/index.php?topic=221.0

Regarding just that thread, I took a look at it, but I won't look any further. Why? Because the people who wrote that stuff do something that I really really really really HATE. Which is to use totally cryptic, un-understandable references to local variables like [esp+0*4] instead of just creating a goddamn readable LOCAL VARIABLE like everyone else does. ("Dedndave" is particularly guilty of this crime.) Why do this? It buys you absolutely nothing in terms of execution speed. All it does is make your code unintelligible. Sheesh.
Title: Re: QWORD conversion function in MASM32 libraries?
Post by: NoCforMe on July 12, 2022, 09:38:11 AM
Quote from: jj2007 on July 12, 2022, 09:20:18 AM
If speed is not an issue:
include \masm32\include\masm32rt.inc

.data
MyQ QWORD 12345678901234567890

.code
start:
  printf("The value of MyQ is %llu\n", MyQ)
  inkey "hit any key"
  exit

end start


If speed is important, try MasmBasic Str$(MyQ), it's a factor 3.6 faster than CRT printf().

But I don't want printf(); I want something like wsprintf(), that formats to memory. Got anything like that? (Not MasmBasic, since I'm still not yet a user.)
Title: Re: QWORD conversion function in MASM32 libraries?
Post by: jj2007 on July 12, 2022, 09:40:47 AM
Quote from: NoCforMe on July 12, 2022, 09:35:53 AMtotally cryptic, un-understandable references to local variables like [esp+0*4]

I use this syntax over 250 times in my library, and don't feel guilty. Just get used to it :cool:

Simple example, coded tonight:
destx equ [esp-16]
desty equ [esp-12]
destw equ [esp-8]
desth equ [esp-4]
srcx equ [esp]
srcy equ [esp+4]
srcw equ [esp+8]
srch equ [esp+12]
xor ebx, ebx
push ebx ; callback data
push ebx ; callback
push ebx ; attributes
push UnitPixel ; unit=2
push edx ; src height
; fild stack
push eax ; src width
; fild stack
push ebx ; src y slot
push ebx ; src x slot
.DATA
align 16
cropdata dw 20, 20, -20, -20 ; x, y, w, h
.CODE
pmovsxwd xmm0, qword ptr cropdata
movups xmm1, oword ptr [esp]
PADDD xmm0, xmm1
movups oword ptr [esp], xmm0
fild stack[3*4] ; h
fild stack[2*4] ; w
deb 4, "A", ST(0), ST(1)
fld st ; copy of width
fmul [edi.GuiImageZOOM].gizX ; width*percentX
fiadd stack
deb 4, "srcX", ST(0)
nops 2
fistp stack ; new src X
fmul [edi.GuiImageZOOM].gizW ; width*percentW
fisubr stack[8] ; subtract from old width
fisub stack ; subtract left offset
fistp stack[8] ; new src width
fld st ; copy of height
fmul [edi.GuiImageZOOM].gizY ; height*percentY
fiadd stack[4]
fistp stack[4] ; new src Y
fmul [edi.GuiImageZOOM].gizH ; width*percentH
fisubr stack[12] ; subtract from old height
fisub stack[4] ; subtract top offset
fistp stack[12] ; new src height
Title: Re: QWORD conversion function in MASM32 libraries?
Post by: NoCforMe on July 12, 2022, 10:04:57 AM
But why? Why on earth would you want to code something cryptically like that instead of using symbolic names like [insert name of deity here] intended? is it that much trouble to come up with names? How in the world do you look at that and know just what the hell [esp-8] refers to?

Like they say, smh ...
Title: Re: QWORD conversion function in MASM32 libraries?
Post by: jj2007 on July 12, 2022, 10:06:46 AM
Short answer: nobody forces me to use (for example) fild stack[3*4]...
Title: Re: QWORD conversion function in MASM32 libraries?
Post by: NoCforMe on July 12, 2022, 10:51:10 AM
I did find what looks like a usable (and simple) routine in that thread you linked to, and it's from "dedndave". I've reformatted it to my liking here:


        .data

Q2Abuffer DB "01234567890123456789",0 ;20 ASCII digits

        .code

;====================================================================
; Convert 64-bit unsigned integer (QWORD) to ASCII decimal string
;
; On entry,
; EDX:EAX = QWORD value to convert
;
; Returns:
; EAX--> buffer containing numeric string
;====================================================================
Q2A PROC

PUSH EBX
PUSH EDI

STD ;No, not a venereal disease:
;set direction flag to go backwards.
MOV EDI, OFFSET Q2Abuffer + 18
MOV ECX, EDX
XCHG EAX, ESI
MOV EBX, 100 ;Load with divisor.

qloop: XOR EDX, EDX
XCHG EAX, ECX
DIV EBX
XCHG EAX, ECX
XCHG EAX, ESI
DIV EBX
XCHG EAX, ESI
XCHG EAX, EDX
AAM
XCHG AL, AH ;Swap bytes.
OR AX, 3030h ;Convert to ASCII.
STOSW ;Store 2 digits.
MOV EAX, ECX
OR EAX, ESI
JNZ qloop

ADD EDI, 2
CLD ;Be sure to clear direction flag!
CMP BYTE PTR [EDI], '0' ;Leading zero?
JNE exit99 ;  No, done.

INC EDI ;  Yep, increment past it.
exit99: MOV EAX, EDI ;Return with pointer to buffer.
POP EDI
POP EBX
RET

Q2A ENDP


Haven't tested it out yet, but I'm sure it'll do nicely.
Title: Re: QWORD conversion function in MASM32 libraries?
Post by: hutch-- on July 12, 2022, 12:15:33 PM
 :biggrin:

Everybody has a theory, I get to see code that is regularly unintelligible, its the name of the game. I am an addict of clarity but you don't get to see it all that much.
Title: Re: QWORD conversion function in MASM32 libraries?
Post by: jj2007 on July 12, 2022, 05:11:57 PM
Quote from: NoCforMe on July 12, 2022, 10:51:10 AMHaven't tested it out yet, but I'm sure it'll do nicely.

Not bad indeed, but you have two very slow DIV instructions in your code...

MyQ=12345678901234567890
2547 ms for Q2A
1264 ms for Str$()


MOV EDI, OFFSET Q2Abuffer + 18

If that line was my code, it would be
mov edi, offset Q2aBuffer+18

- ALL CAPS would drive me crazy
- a tab between mov and edi? No thanks, my eyes don't like jumping around
- Q2Abuffer looks like an inconsistent half camel case; Q2aBuffer is much more readible
- I don't need spaces around + and minus signs, they distract

As you can see, it's all a question of taste - as Hutch writes, "Everybody has a theory" ;-)
Title: Re: QWORD conversion function in MASM32 libraries?
Post by: NoCforMe on July 12, 2022, 06:11:30 PM
Quote from: jj2007 on July 12, 2022, 05:11:57 PM
Quote from: NoCforMe on July 12, 2022, 10:51:10 AMHaven't tested it out yet, but I'm sure it'll do nicely.

Not bad indeed, but you have two very slow DIV instructions in your code...

Don't care. Speed matters not here. It's just used for some end-of-run reporting. Rather have small, simple code here.

BTW, regarding program formatting, I realize this is a religious issue ...
Title: Re: QWORD conversion function in MASM32 libraries?
Post by: jj2007 on July 12, 2022, 06:25:19 PM
Quote from: NoCforMe on July 12, 2022, 06:11:30 PMBTW, regarding program formatting, I realize this is a religious issue ...

Amen :tongue:
Title: Re: QWORD conversion function in MASM32 libraries?
Post by: Vortex on July 12, 2022, 06:34:42 PM
Hello,

Anyone who tried crt_sprintf with %I64u ? That function does not seem to support 64-bit integers.
Title: Re: QWORD conversion function in MASM32 libraries?
Post by: jj2007 on July 12, 2022, 06:45:56 PM
Same as %llu in reply #1, Erol:

include \masm32\include\masm32rt.inc

.data
MyQ QWORD 12345678901234567890
buffer db 80 dup(?)

.code
start:
  cls
  invoke crt_sprintf, addr buffer, chr$("A: The value of MyQ is %I64u", 13, 10), MyQ
  printf("B: The value of MyQ is %I64u\n", MyQ)
  inkey addr buffer
  exit

end start
Title: Re: QWORD conversion function in MASM32 libraries?
Post by: Vortex on July 12, 2022, 06:56:01 PM
Hi Jochen,

Thanks, the code below works fine. The specifier %I64u works with wsprintf too.

include \masm32\include\masm32rt.inc

.data

x       dq 12345678901234567890
f1      db '%I64u',0

.data?

buffer  db 128 dup(?)

.code

start:

    invoke  crt_sprintf,\
            ADDR buffer,ADDR f1,x
           
    invoke  StdOut,ADDR buffer

    invoke  ExitProcess,0

END start

Title: Re: QWORD conversion function in MASM32 libraries?
Post by: hutch-- on July 12, 2022, 06:57:20 PM
 :biggrin:

> know just what the hell [esp-8] refers to?

Just what it says, the memory address in esp with a minus offset of 8 bytes.

This is the normal Intel "complex addressing mode".

When you have a reason to work in QWORD size data in 32 bit, you do it the old fashioned hard way, the low DWORD is read like normal, the high DWORD is read separately and added to the first with a multiplier. The other option is to write it in 64 bit.  :biggrin:
Title: Re: QWORD conversion function in MASM32 libraries?
Post by: NoCforMe on July 12, 2022, 07:08:34 PM
You're missing the point.

Yes, I know what [esp-n] means. But I don't know what it means when I'm looking at code, meaning that I have no idea what variable it refers to. So why use it instead of a recognizable name? That's why we use a macro assembler, isn't it? Otherwise we'd still be flipping front-panel switches and coding in binary (or even worse, octal). Why use [esp-8] when you can use "pintsDrank" or whatever?

Someone pointed out to me that that notation is useful when using a debugger like Olly which displays stuff that way, but even there it would be a lot nicer to use a meaningful symbolic name rather than some offset from a register, which tells me nothing about what that data is, unless you're some kind of idiot savant who can memorize all that crap.
Title: Re: QWORD conversion function in MASM32 libraries?
Post by: hutch-- on July 12, 2022, 07:19:12 PM
Writing no stack frame code comes with practice, you should know what you are passing to a procedure and using direct stack addressing is part of that type of code. The solution of course is to actually comment your code and you will always know what it is. Thank God 64 bit is clearer but under the hood is a joy to behold. It has to be aligned correctly ALA M$ ABI and its written in reverse order below the current stack location.

Now if you want to write no stack frame code with the lowest overhead, if you need temporary locations for what would be LOCAL values in a stackframe procedure, you write it below the stack and this is in 32 bit.
Title: Re: QWORD conversion function in MASM32 libraries?
Post by: Vortex on July 12, 2022, 07:33:19 PM
Hi NoCforMe,

Hutch's latest post is a nice explanation. If you wish to code an optimized procedure, you need to turn off stack framing and use the complex addressing mode.
Title: Re: QWORD conversion function in MASM32 libraries?
Post by: Vortex on July 15, 2022, 06:46:26 AM
Hi NoCforMe,

Here is a quick example for you :

include     \masm32\include\masm32rt.inc

subs        PROTO :DWORD,:DWORD

.data

msg         db '120 - 40 = %u',0

.data?

buffer      db 32 dup(?)

.code

start:

    invoke  subs,120,40
   
    invoke  wsprintf,ADDR buffer,\
            ADDR msg,eax

    invoke  StdOut,ADDR buffer

    invoke  ExitProcess,0


OPTION PROLOGUE:NONE
OPTION EPILOGUE:NONE

align 4

subs PROC x:DWORD,y:DWORD

    mov     eax,DWORD PTR [esp+4]
    sub     eax,DWORD PTR [esp+8]

    ret     2*4 ; balance the stack manually

subs ENDP


OPTION PROLOGUE:PrologueDef
OPTION EPILOGUE:EpilogueDef


END start
Title: Re: QWORD conversion function in MASM32 libraries?
Post by: NoCforMe on July 15, 2022, 07:36:16 AM
OK, so compare to the way I would do it:

;*****  Subroutine using easy-to-understand arguments instead of [esp+4], etc.:  *****

Subtract PROC minuend:DWORD, subtrahend:DWORD

MOV EAX, minuend
SUB EAX, subtrahend
RET

Subtract ENDP


I fail to see the advantage of your way. What have you gained? Sure, the tiny overhead of the prologue/epilogue code. Is that all? Seems like a small price to pay for readability. Or is there something else I'm missing here?

See, this way I, the human, don't have to keep track of [esp+n] offsets; that's what computers are for ...
Title: Re: QWORD conversion function in MASM32 libraries?
Post by: jj2007 on July 15, 2022, 09:25:34 AM
Quote from: NoCforMe on July 15, 2022, 07:36:16 AMWhat have you gained? Sure, the tiny overhead of the prologue/epilogue code.

That's correct. It's tiny, but if the proc itself is tiny, omitting the overhead may be an advantage.

Here is a more readable alternative: equates.

include \masm32\include\masm32rt.inc

.code
OPTION PROLOGUE:NONE
OPTION EPILOGUE:NONE

subxy proc x0, y0
  x equ [esp+4] ; define your argument
  y equ [esp+8] ; names with equates
  mov eax, x
  sub eax, y
  retn 8
subxy endp

OPTION PROLOGUE:PrologueDef
OPTION EPILOGUE:EpilogueDef

start:
  invoke subxy, 456, 123
  MsgBox 0, cat$(str$(eax), " is the result"), "Hello:", MB_OK
  exit

end start


Same code but different syntax:

include \masm32\include\masm32rt.inc

.code
subxy:
  x equ [esp+4] ; define your argument
  y equ [esp+8] ; names with equates
  mov eax, x
  sub eax, y
  retn 8

start:
  push 123
  push 456
  call subxy
  MsgBox 0, cat$(str$(eax), " is the result"), "Hello:", MB_OK
  exit

end start