Okay, it's late Sunday and I have work early tomorrow morning. Very sleepy, sorry if this question sounds poorly thought out.

I want to zero out a LOGFONT structure. The C way is
memset(&logFont, 0, sizeof(LOGFONT));

And I'm wondering if there's a quick and clear way to do it in Masm32. Here's what I have so far (haven't tested it yet):

local logfont:LOGFONT

mov edi, addr logfont
mov [edi], byte ptr 0 ; zero out the current byte
inc edi
dec ecx
jnz @B

Will this work? What's the proper asm idiom? I know offhand it's glaringly inefficient; I could write out 7 DWORDS and then append the trailing byte instead. It seems that this is such a common thing that there should be a memset macro or somesuch.

Is there one?


Posted on 2002-04-21 23:11:40 by Chalain
just use the api:
invoke ZeroMemory,addr logFont,sizeof logFont
Posted on 2002-04-22 00:03:43 by grv575
fill_struct MACRO aStruct:REQ, tStruct:REQ

lea edi, aStruct
mov ecx, (SIZEOF tStruct)/4 ; must be multiple of four
rep stosd

xor eax,eax ; fill value
fill_struct logfont, LOGFONT
This is a repeat question:
$+0        $ 68 28FEFFFF    push -1D8

$+5 . 68 5D164000 push 0040165D
$+A . E8 B0000000 call <jmp.&KERNEL32.RtlZeroMemory>

$+0 . 33C0 xor eax,eax
$+2 . 8D3D 5D164000 lea edi,[40165D]
$+8 . B9 A3FFFFFF mov ecx,-5D
$+D . F3:AB rep stos dword ptr es:[edi]
You can see from the disassembly that it takes the same amount of bytes to clear the memory yourself as to call the API to do it! This doesn't include saving/restoring EDI/ECX/EAX, but that can usually be worked into the big picture. No point to using the API!
Posted on 2002-04-22 00:15:09 by bitRAKE
Is that method faster? :) If it is... then goodbye RtlZeroMemory :)

Posted on 2002-04-22 00:54:19 by Sliver

push eax
push edx
mov edx, ecx
xor eax, eax
and edx, 3
je CopyByDword
CopyByByte:add edi, edx
neg edx
@@:mov byte ptr ,al
inc edx
jne @B
CopyByDword:and ecx, 0FFFFFFFCh
je Done
add edi, ecx
shr ecx, 2
neg ecx
@@:mov dword ptr , eax
inc ecx
jne @B
Done:pop edx
pop eax

Posted on 2002-04-22 01:02:31 by bdjames
With the size of the structure, its "who cares".
You could do it with REP MOVSB and it would be smaller and plenty fast enough.



PS : Actually this is a mistake, I use the old string instructions so little I am getting rusty with them, it should be STOSB.

Something like,

mov ecx, count ; size of structure
mov al, 0 ; fill byte
mov edi, lpBuffer ; address of structure
rep stosb
Posted on 2002-04-22 03:11:34 by hutch--
Wrong place, Sorry...I hit the wrong button.

I think i got the smallest one

A Poster a while back said if it a text buffer ...

mov LOGFONT.WhatEver[0] , 0

It might work. It work with everything else.
Posted on 2002-04-22 06:25:18 by cmax

fill_struct MACRO aStruct:REQ, tStruct:REQ

mov ecx, (SIZEOF tStruct)/4 ; must be multiple of four

Ah, there's the rub: LOGFONT is 29 bytes long.

I assume this macro would leave the last byte uninitialized?

ZeroMemory is okay, I guess, but doesn't it incur a speed hit for the function call?


Posted on 2002-04-22 12:17:18 by Chalain
Hmm, I just had a thort... assuming that BitRake's macro would leave the last byte of LOGFONT uninitialized, would this code work? (I'm at work and don't have time to really test it out)

fill_struct MACRO aStruct:REQ, tStruct:REQ
lea edi, aStruct
mov ecx, (SIZEOF tStruct)/4 ; must be multiple of four
rep stosd

; handle straggling bytes
xor edx,edx
mov ebx, eax ; hang onto fill value
mov eax, SIZEOF tStruct
mov ecx, 4
div ecx
mov ecx, edx ; mov remainder to counter
mov eax, ebx ; restore fill value
rep stosb

xor eax,eax ; fill value
fill_struct logfont, LOGFONT

I'm sure it's gross and hideously inefficient... mostly it's just an exercise to see if I could get it to work. :)

So... does it? Is there a better way to go about it? Er, perhaps a better question would be, how many better ways are there...


Posted on 2002-04-22 12:29:47 by Chalain
ZeroMemory is okay, I guess, but doesn't it incur a speed hit for the function call?

With sizes like 29 byte, don't worry about this. Even on a slow machine it will probably take less than 100 cycles.
Only if you're clearing a memory area of several MBs, optimisation is an issue here.

Posted on 2002-04-22 12:34:26 by Thomas
Just change the macro to:
fill_struct MACRO aStruct:REQ, tStruct:REQ

lea edi, aStruct
mov ecx, SIZEOF tStruct
rep stosb
...and it works with non-dword multiple sizes.
Posted on 2002-04-22 12:50:10 by bitRAKE
I have been looking at the rep sto* instruction.
How can the overhead of that instruction be
only 3+n? One instruction per cycle, with only
three overhead?

Some kind of jump table?
Posted on 2002-04-22 14:20:47 by bdjames
Instead of using stosb for non dword aligned strings, the code included with masm32v7 is about 3 times as fast. It uses rep movsd and then movsb for the last couple bytes.

CopyMemD proc source:DWORD,dest:DWORD,len:DWORD

cmp len, 4 ; if < DWORD size
jl @@@1 ; copy as BYTE

mov esi, source
mov edi, dest
mov ecx, len

push ecx ; copy ecx
shr ecx, 2 ; integer divide by 4
shl ecx, 2 ; multiply by 4 for dividend
pop edx
sub edx, ecx ; remainder in edx
; shr ecx ; bug in original
shr ecx, 2 ; div by 4 for DWORD

rep movsd ; copy as DWORD
mov ecx, edx ; put remainder in counter
jmp @@@2

mov ecx, len
rep movsb ; copy as BYTE


CopyMemD endp

This is pretty easy to modify for stosb to zero structures. Looks like the stosd version is 6x faster on my system.
Posted on 2002-04-23 15:03:34 by grv575