News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Code sizing macros

Started by jj2007, June 26, 2008, 10:01:27 AM

Previous topic - Next topic

jj2007

Here is a macro showing the size of your code. Question: Is there any clean way to determine the size of the code that has been added by the Masm32 libraries? I assume searching for the byte sequence 004015F4 in the code would be an option, but that might be OS-specific...

CPU Disasm (from OllyDbg)
Address   Hex dump          Command                                  Comments
004015F4   $- FF25 D0224000 JMP DWORD PTR DS:[<&kernel32.ExitProcess
004015FA   $- FF25 D4224000 JMP DWORD PTR DS:[<&kernel32.GetStdHandl

Thanx, jj

ShowCodeSize MACRO
call ChkEnd
sub eax, offset start
push eax
print chr$(13, 10, "Your own code section has ")
pop eax
print ustr$(eax)
print chr$(" bytes", 13, 10, 10)
ENDM

... code ...

OPTION PROLOGUE:NONE
OPTION EPILOGUE:NONE

ChkEnd2 proc
int 3 ; for testing in OllyDbg
mov eax, [esp]
ret
ChkEnd2 endp
ChkEnd proc
call ChkEnd2
ret
ChkEnd endp

OPTION PROLOGUE:PrologueDef
OPTION EPILOGUE:EpilogueDef

japheth

Quote from: jj2007 on June 26, 2008, 10:01:27 AM
Question: Is there any clean way to determine the size of the code that has been added by the Masm32 libraries? I assume searching for the byte sequence 004015F4 in the code would be an option, but that might be OS-specific...

you can define a text$z segment:


     .code

     [your code]

     .code _text$z

ENDCODE equ $



And ENDCODE will be behind any code the linker has added.


OPTION PROLOGUE:NONE
OPTION EPILOGUE:NONE

    [snip]

OPTION PROLOGUE:PrologueDef
OPTION EPILOGUE:EpilogueDef


There's no need for these directives if the procs between them don't contain params or locals.

jj2007

Thanxalot! But wouldn't the segment be page-aligned...? I had embarked on a more complicated way, see below.

BeforeChkEnd:
ShowCodeSize proc uses esi

print chr$(13, 10, "Your code section has", 9)
mov eax, offset BeforeChkEnd - offset start
print str$(eax)
print chr$(" bytes ", 40, "excluding the ShowCodeSize routine", 41, 13, 10)

print chr$("The libraries added", 9)
mov esi, offset AfterChkEnd

xor ecx, ecx ; counter

@@: inc esi
mov eax, [esi]
inc ecx
cmp ecx, 4000
ja @F
cmp ax, 25FFh ; a long JMP
jne @B
mov eax, [esi+6]
cmp ax, 25FFh ; another long JMP exactly 6 bytes later
jne @B

@@: print ustr$(ecx)
print chr$(" bytes", 13, 10, 10)
ret
ShowCodeSize endp        ; just before end start
AfterChkEnd:

end start

japheth

> Thanxalot! But wouldn't the segment be page-aligned...? I had embarked on a more complicated way, see below.

Not page-aligned, but possibly dword (.386) or para (16-bytes, .486 and above) aligned. The COFF linker will combine  all sections beginning with _text until the '$', sort them by name and put them into a "physical" section. IIRC that's part of the COFF specification.

jj2007

I tried your suggestion and got this:

Your code section has   1014 bytes (excluding the ShowCodeSize routine)
The libraries added     427 bytes (my cmp ax, 25FFh routine)
The linker added        4202496 - 4199422 = 3074 bytes

BeforeChkEnd:
ShowCodeSize proc uses esi

print chr$(13, 10, "Your code section has", 9)
mov eax, offset BeforeChkEnd - offset start
print str$(eax)
print chr$(" bytes ", 40, "excluding the ShowCodeSize routine", 41, 13, 10)

print chr$("The libraries added", 9)
mov esi, offset AfterChkEnd

xor ecx, ecx ; counter

@@: inc esi
mov eax, [esi]
inc ecx
cmp ecx, 4000
ja @F
cmp ax, 25FFh ; a long JMP
jne @B
mov eax, [esi+6]
cmp ax, 25FFh ; another long JMP exactly 6 bytes later
jne @B

@@: print ustr$(ecx)
print chr$(" bytes", 13, 10)

mov esi, offset ENDCODE
print chr$("The linker added", 9)
print str$(esi)
print " - "
mov eax, offset BeforeChkEnd
print str$(eax)
print " = "
sub esi, offset BeforeChkEnd
print str$(esi)
print chr$(" bytes", 13, 10, 10)

ret
ShowCodeSize endp
AfterChkEnd:

.code _text$
ENDCODE equ $
end start

jj2007

Practical example:

UseOldCat = 1
Your code section has   1162 bytes (excluding the ShowCodeSize routine)
The libraries added     430 bytes

UseOldCat = 1
Your code section has   653 bytes (excluding the ShowCodeSize routine)
The libraries added     331 bytes

Look for the UseOldCat switch in the attachment.

EDIT:
In contrast to the old cat$ macro, CAT$ does not require buffer initialisation:

old cat$:
mov byte ptr [mcDefBuffer], 0   ; clear the target buffer for cat$
mov eax, cat$(addr mcDefBuffer, CrLf$, "Ciao bello")

new CAT$:
mov eax, CAT$(0, CrLf$, "Ciao bello")

is the same as

mov eax, CAT$(addr mcDefBuffer, CrLf$, "Ciao bello")

i.e. passing a zero pointer means use the mcDefBuffer default buffer. In any case, CAT$ will write to the pointer "as is", i.e. will not check for a terminating zero byte. If you need the "append to myBuffer" functionality, use:

mov eax, CAT$(addr myBuffer, CrLf$, "Ciao bello")
mov eax, CAT$(1, CrLf$, "This line was appended")

The mcDefBuffer hangs around in the .data? section and has 1024 bytes, i.e. a very big MessageBox.
When used with CAT$(0, ...), the copy is safe, i.e. will never write beyond the buffer.
When using other buffers, the copy is not safe.

[attachment deleted by admin]