Writing some demo apps I needed numerously
decode bit fields of different size in ASCII Binary
representation and display them in different Dlg controls.
So I finaly came up to a proc that convert specified
number of bits (from 1 to 32) of specified value and display them
in given control. Upper then specified bits must be zeroed.

It's not about speed, it's about size and flexibility.
The thing is that it creates local strings.
Might be it could be of some use to someone.
Suggestions to make it shorter are wellcome
as long as conditions met:
1. It must create local strings (no pointers to
some buffers allowed)
2. It must display it itself, no just create strings.



StackBinAscii proc uses edi bits,bsize,hWnd,CtlID
;enter frame 4 bytes (push ebp\mov ebp,esp\push edi)
mov al,30h
mov ecx,bsize
sub esp,ecx
dec esp
mov edi,esp
rep stosb
mov byte ptr [edi],0
inc al
@@:
dec edi
shr bits,1
jnc @not1
mov [edi],al
@not1:
jne @B
invoke SetDlgItemText,hWnd,CtlID,esp
;exit frame 4 bytes (pop edi,leave,ret n)
ret
StackBinAscii endp

Posted on 2003-03-18 19:25:00 by The Svin
	OPTION PROLOGUE:NONE

OPTION EPILOGUE:NONE

StackBinAscii proc bits, bsize, hWnd, CtlID
mov ecx, [esp + 4] ; bits
push 0
stc
mov edx, esp
@@: dec esp
mov al, [esp]
rcr ecx, 1
sbb al, 30h
sub [esp], al
test ecx, -2
jne @B

sub edx, [esp + 36 + 8] ; bsize

; invoke SetDlgItemText, hWnd, CtlID, edx
invoke SetDlgItemText, DWORD PTR [esp][36][12][8], DWORD PTR [esp][36][16][4], edx

add esp, 32 + 4
ret 16
StackBinAscii endp

OPTION PROLOGUE:PROLOGUEDEF
OPTION EPILOGUE:EPILOGUEDEF
Works with all bit sizes and stack remains aligned.

Here, this one is a little better:
	OPTION PROLOGUE:NONE

OPTION EPILOGUE:NONE

StackBinAscii proc bits,bsize,hWnd,CtlID
mov ecx, [esp + 4] ; bits
push 0
stc
mov edx, esp
rcr ecx, 1
inc edx

@@: adc BYTE PTR [esp], 30h
dec esp
shr ecx, 1
mov BYTE PTR [esp], 0
jne @B

sub edx, [edx][4][8] ; bsize
; invoke SetDlgItemText, hWnd, CtlID, edx
invoke SetDlgItemText, DWORD PTR [esp][36][12][8], DWORD PTR [esp][36][16][4], edx

add esp, 32 + 4
ret 16
StackBinAscii endp

OPTION PROLOGUE:PROLOGUEDEF
OPTION EPILOGUE:EPILOGUEDEF
Anyone see something I'm missing?
Posted on 2003-03-18 22:49:44 by bitRAKE
Maybe something like this:
StackBinAscii proc bits, bsize, hWnd, CtlID

local String[36] :BYTE
mov esi, ebp
xor edx, edx
dec edx
mov ecx, bsize
mov eax, bits
shr edx, cl
and eax, edx
xor edx, edx
mov byte ptr [esi], dl
dec esi
mov ebx, 30h
mov ecx, 32
@@: shr eax, 1
adc edx, ebx
mov byte ptr [esi], dl
xor edx, edx
dec esi
dec ecx
jnz @B
inc esi
invoke SetDlgItemText,hWnd,CtlID, esi
ret
StackBinAscii endp


Let the compiler worry about stack :)
Posted on 2003-03-19 03:20:08 by masquer

Anyone see something I'm missing?

At least I see you specifyed args in a funny way


DWORD PTR [esp][36][12][8], DWORD PTR [esp][36][16][4]

:)
36+12+8=36+16+4

Yet Rickey, even if it could have worked it still takes the same 48 bytes
as my first proc so I didn't check your proc further, may be later.

masquer,
As I said it's about size.
Your proc is much bigger than original to discuss it
(note such code as mov ebx,30h is just unacceptable while optimizing
for size, not mentioned that such regs as ebx,esi needed to be preserved
and it would add some more size to the proc)
But you right about stack reservation, I noted it after the first post so
I've changed a couple of funny lines:


StackBinAscii proc uses edi bits,bsize,hWnd,CtlID

mov al,30h
sub esp,40
mov ecx,bsize
mov edi,esp
rep stosb
mov byte ptr [edi],0
inc eax
@@:
dec edi
shr bits,1
jnc @not1
mov [edi],al
@not1:
jne @B
invoke SetDlgItemText,hWnd,CtlID,esp
ret

StackBinAscii endp
Posted on 2003-03-19 14:11:10 by The Svin

Anyone see something I'm missing?


Note, that after loop value of esp may differ from case to
case, yet you address args and adjust esp at the end as
if you know it would be shifted to - 36.

Aside from other things your last proc doesn't work 'cause of
incorrect esp adjusment handling.
Posted on 2003-03-19 14:52:19 by The Svin
Stupid me :)
Wrote a several tuts, but didn't note obvious
inefficient 2 bytes "inc al" :)
Fixed, now it is 47 bytes.
Posted on 2003-03-19 16:14:32 by The Svin
i think this is shoter
however , i dont have the time to check if it is . and if it works .

; but it doesnt use bsize .


StackBinAscii proc uses edi bits,bsize,hWnd,CtlID
;enter frame 4 bytes (push ebp\mov ebp,esp)
push 0

@@:
dec ebp
shl bits,1
mov [ebp],30h
jnc @not1
inc byte ptr [ebp]
@not1:
jne @B
invoke SetDlgItemText,hWnd,CtlID,ebp
;exit frame 4 bytes (pop ebp,leave,ret n)
ret
StackBinAscii endp
Posted on 2003-03-19 16:46:24 by eko
Hmm. This is a few bytes smaller.


push edi
enter 33,0
mov edx,[ebp+4]
mov edi,esp
mov cl,[ebp+8]
ror edx,cl
blah: mov al,48
shl edx,1
adc al,0
stosb
loop blah
mov byte [edi],0
push esp
push dword [ebp+16]
push dword [ebp+12]
call SetDlgItemTextA
leave
pop edi
ret 16
Posted on 2003-03-19 17:07:14 by Sephiroth3

but it doesnt use bsize

That means that your proc doesn't meet conditions:
Ascii string must be of specified size, otherwize it's useless.
If I need to display 5 bits field it should look like:
00001 not like 1.
00000 not like 0.
00101 not like 101.
Posted on 2003-03-19 18:27:39 by The Svin
The Svin, does stack need to be aligned on Win9x?
I remember hearing something a time ago.
Posted on 2003-03-19 20:10:31 by bitRAKE
I tried the first version in 98, it worked OK.
I tried among other size with 5 and 6 bitsize - that means
as you understand unaligned stack result.
I'm talking of the first version, 'cause there was my stupid decision decrease esp exactly to needed string size.
In next version I just sub esp for 40 bytes buffer, so it's aligned.
As to your proc I doesn't work not because of unalignment. Just 'cause in a loop it's diviated esp to varaible = index of msb and at the end restored to constant,
if they not equal GPF will happen even before return - on
API call. And even if by some miracle it won't happen yet
wrong esp will point to wrong ret address and GPF will be unavoidable at the return pointing to accedent value as return address.
Posted on 2003-03-19 20:30:36 by The Svin
what about this one ......




StackBinAscii proc uses edi bits,bsize,hWnd,CtlID
;enter frame 4 bytes (push ebp\mov ebp,esp)
push 0

mov ecx,bsize
neg ecx
@@:
mov byte ptr [ebp+ecx],30h
shr bits,1
adc byte ptr [ebp+ecx],0
inc ecx
jnz @B
invoke SetDlgItemText,hWnd,CtlID,ebp
;exit frame 4 bytes (pop ebp,leave,ret n)
ret
StackBinAscii endp





EDIT: new version
but i havnt check it nor finish it .( i'm sure it can be better)
i 'm hury so i dont have the time right now



OPTION PROLOGUE:NONE
OPTION EPILOGUE:NONE

StackBinAscii proc uses edi bits,bsize

push 0
mov ecx,[esp+0ch]
neg ecx
lea eax,[esp+ecx]
@@:
mov byte ptr [esp+ecx],30h
shr dword ptr [esp+08h],1
adc byte ptr [esp+ecx],0
inc ecx
jnz @B

invoke SetDlgItemText,hWnd,CtlID,eax
add esp,4 ; can do pop eax or something else to save some bytes
ret
StackBinAscii endp
OPTION PROLOGUE:PROLOGUEDEF
OPTION EPILOGUE:EPILOGUEDEF
Posted on 2003-03-20 06:23:22 by eko
eko,

Very nice idea but what about 0-terminating the string?

edit: Also, that invoke overwrites the string.
Posted on 2003-03-20 06:56:14 by iblis
Sephiroth3,
1. Please note that you loading value into cl (not in ecx!)
and then using loop instruction.
What would happen if upper 24 bits in ecx has some garbage?
Change the line to mov ecx,...
2. Your addressing of agruments is incorrect.
Adjust them by + 8 to your current displacements.

Apart from that your code has some interesting ideas,
I'm going to steal :)
Thanx for your code.
Posted on 2003-03-20 13:57:01 by The Svin
eko, you have good ideas, but NUMEROUS
mistakes it every of your proc.
Mistakes could be seen at first carefull glance.
Please, check and test your code before sending.
What is in ebp in the first proc? Value of esp.
I.e - return address. Not a string address.
More to that, even if wasn't return address (that
you actually ovewriting by your proc) you yet
sending end of the string not a start.
I'm not talking about the last proc.
Giving you a chance to correct it by yourself.
Posted on 2003-03-20 17:52:31 by The Svin
you are right . in my first proc
there are alot of mistake . too many

it will not exit becuase of inc byte ptr
the push 0 needs to be before mov ebp,esp
and more "stupid" mistakes . this proc needs to be rewrite



the 3rd proc is a fix to the 2nd - I dont know why I left the 2nd proc

by the way the proc[3] can be write with the same number of bytes
like this




OPTION PROLOGUE:NONE
OPTION EPILOGUE:NONE

StackBinAscii proc uses edi bits,bsize

push 0
mov ecx,[esp+0ch]
neg ecx
lea eax,[esp+ecx]
@@:
; mov byte ptr [esp+ecx],30h
shr dword ptr [esp+08h],1
setc byte ptr [esp+ecx],0 ;adc byte ptr [esp+ecx],0
add byte ptr [esp+ecx],30h
inc ecx
jnz @B

invoke SetDlgItemText,hWnd,CtlID,eax
add esp,4 ; can do pop eax or something else to save some bytes
ret
StackBinAscii endp
OPTION PROLOGUE:PROLOGUEDEF
OPTION EPILOGUE:EPILOGUEDEF
Posted on 2003-03-21 08:48:09 by eko
I had an idea to change meaning of bsize value
to most significant bit index value a limit, that
allowed to create 41 bytes solution:


OPTION PROLOGUE:NONE
OPTION EPILOGUE:NONE

StackBinAscii proc bits,bsize,hWnd,CtlID

push edi
enter 40,0
mov ecx,[ebp+16]
mov edi,esp
@@:
mov al,18h
bt dword ptr [ebp+12],ecx
adc al,al
stosb
dec ecx
jns @B
mov byte ptr [edi],0
invoke SetDlgItemText,[ebp+20],[ebp+24],esp
leave
pop edi
ret 16

StackBinAscii endp
OPTION PROLOGUE:PROLOGUEDEF
OPTION EPILOGUE:EPILOGUEDEF


More important that the logic may be used in a task
to extract particular field of given value.
For example display bits from bit to bit
mlbits here is value of most and least significant bit set of
the field that need to be extracted and displayed:


OPTION PROLOGUE:NONE
OPTION EPILOGUE:NONE

StackBitFldAscii proc bits,mlbits,hWnd,CtlID
push edi
enter 40,0
bsr ecx,[ebp+16];mlbits most sign. bit
bsf edx,[ebp+16];least sign. bit
mov edi,esp
@@: mov al,24
bt dword ptr [ebp+12],ecx
adc al,al
stosb
dec ecx
cmp ecx,edx
jnl @B
mov byte ptr [edi],0
invoke SetDlgItemText,[ebp+20],[ebp+24],esp
leave
pop edi
ret 16

ret

StackBitFldAscii endp

OPTION PROLOGUE:PROLOGUEDEF
OPTION EPILOGUE:EPILOGUEDEF


Example of usage.
If we need to display "code or reg" field in modr/m byte:


;show bits 3..5 in given value
invoke StackBitFldAscii,valueofmodrm,mlb(5,3),hWnd,15
;.......
mlb macro msb,lsb
exitm % ((1 shl msb) or (1 shl lsb))

endm
;......
Posted on 2003-03-21 13:47:50 by The Svin



add esp,4 ; can do pop eax or something else to save some bytes



You know eko, it looks wierd, especially comments.
1. If you know how to write more effective code, why do
you write uneffective, mentioning about effective code in comments?
Strange style indeed.
2. Why use such slappy words as "some bytes" while talking of optimization
in wich fundamentals is ability to compare precise values?
Are you unable to calculate precise difference between add esp,4 and pop eax?
Accuracy is wellcome here.
Next time write "save two bytes"
3. Why you write "use edi" if your proc doesn't use edi?
4. What is
setc byte ptr ,0 ?
setc recives 1 argument - operand.
if you want to set it 0 if CF then write
setnc byte ptr ; no more arg needed.

eko, I'm asking you for a second time:
could you test your code before sending it, please?
Posted on 2003-03-21 14:49:18 by The Svin
Eeeh...
eko, I've read your proc to an end.
I think, you need study stack operations in regard of addressing.
Any push operation decrease address of stack pointer,
that means in your procs you put string to a place where
the string is overwritten by following API call after string formation. Cause you place it in esp and lower addresses
Thus local string need to be placed in addresses = and upper esp not lower.
But in upper addresses there are return and args placed
Thus
1. You must decrease esp by locals value
2. Placed locals in addresses esp and +
3. restore esp at the end to make successfull return.
Posted on 2003-03-21 16:08:05 by The Svin

You know eko, it looks wierd, especially comments.
1. If you know how to write more effective code, why do
you write uneffective, mentioning about effective code in comments?
Strange style indeed.
2. Why use such slappy words as "some bytes" while talking of optimization
in wich fundamentals is ability to compare precise values?
Are you unable to calculate precise difference between add esp,4 and pop eax?
Accuracy is wellcome here.
Next time write "save two bytes"


am.. yeah you are right . i should just write pop eax and comment the esp,4
i left the add esp,4 just to show my thoughts - next time i'll be accuracy as well


3. Why you write "use edi" if your proc doesn't use edi?
4. What is
setc byte ptr ,0 ?
setc recives 1 argument - operand.
if you want to set it 0 if CF then write
setnc byte ptr ; no more arg needed.

eko, I'm asking you for a second time:
could you test your code before sending it, please?

use edi left from your proc. i didnt notice it was there . ;[
the zero of setc [2nd parameter] , left from the old line adc ...,0

you are right I need to check my codes . i had few mistakes on the stack I forgot to change esp as well . I was in a hurry when i posted these procs ;[ .


here it is . fixed version of my proc - it based zero



OPTION PROLOGUE:NONE
OPTION EPILOGUE:NONE
StackBinAscii proc bits,bsize,hWnd,hCtl
mov ecx,[esp+8]
sub esp,33
and byte ptr [esp+ecx+1],0
@@:
shr dword ptr [esp+4+33],1
setc byte ptr [esp+ecx]
add byte ptr [esp+ecx],30h
dec ecx
jns @B

push esp
push [esp+20+33]
push [esp+20+33]
call SetDlgItemText


add esp,33
ret
StackBinAscii endp
OPTION PROLOGUE:PROLOGUEDEF
OPTION EPILOGUE:EPILOGUEDEF


bye

eko
Posted on 2003-03-21 21:07:54 by eko