News:

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

Helpful functions

Started by boogara, October 01, 2007, 01:22:14 AM

Previous topic - Next topic

boogara

Sorry if this is the wrong area...please move if it is, but I couldn't find a suitable place to put this...

Kind of think it'd be a good thing to have helpful functions/procedures/code listed here for others...especially code that isn't easily found.

I'll start with a registry-dumping example.


.586
.model flat, stdcall
option casemap :none

include user32.inc     ; Used for wsprintf
includelib user32.lib  ; incs need the libs...atleast user32 does

.data
; szReg displays the current values of the registers (and flags)
szReg db "EFlags: 0x%08X", 10, 13, "EDI: 0x%08X", 10, 13, "ESI: 0x%08X", 10, 13, "EBP: 0x%08X", 10, 13, "ESP: 0x%08X", 10,13,"EBX: 0x%08X", 10, 13,
              "EDX: 0x%08X", 10, 13, "ECX: 0x%08X", 10, 13, "EAX: 0x%08X", 10, 13, 0

; Message box title
szTitle db "Registry Dump",0

.data?
; Where to store the result (explained more in StoreRegs proc)
szOutput db 256 dup (?)

; Lets begin coding
.code

; -----------------------------------------------------------------
; StoreRegs
; No params
; Return: None
; Formats a string to display the current values of the registers
; Credit:
; Code is from somewhere, but I forgot where (from a CPUID example)
; ------------------------------------------------------------------
StoreRegs proc
; Before continuing, explaining this little bit
; If using call, then you must first push all the values in reverse order
; (pretty much like a little endian style programming...spiffeh!)

pushad  ; Pretty much, load all the 32-bit registers
pushfd   ; Load the flags now

push offset szReg      ; The format of the string we want to use (0x%08X will output in format of: 0xABCD123F)
push offset szOutput  ; Where do we want to store the resulting string

call wsprintf  ; Lets do the dirty work

add esp, 8  ; I'll be honest...I'm not exactly sure what the purpose of adding 8 to ESP does...but if it's not here, then your program will crash

popfd    ; Restore the flags (so we can change them again)
popad   ; Restore the 32-bit registers now so we can change them again as well
ret        ; Exit out of the procedure and continue on

StoreRegs endp

; -----------------------------------------------------------------
; MBRegs
; No params
; Return: None
; Calls StoreRegs, then displays the results (szOutput) in a message box
; (Note: Escaping MASM-coding to make it more compatible with other assemblers)
; ------------------------------------------------------------------
MBRegs proc

; Call the above procedure, so we can get the values
call StoreRegs

push MB_OK               ; We only want an "Ok" button for the message box
push offset szTitle       ; Set the title of the message box
push offset szOutput    ; The fruit-of-the-loom...our content
push NULL                  ; No HWND defined (to simply procedure)

call MessageBox   ; Display message box
ret                      ; Exit out of the procedure and continue on

MBRegs endp

Tedd

Looks okay :wink Could be cleaned up by using 'invoke' though.
The add esp,8 is to clean up the stack after calling wsprintf -- it's a 'c-style' function, so it doesn't clean its parameters off the stack itself. So you have to clean up the 2 dword parameters (2 * 4 bytes = 8 bytes) to re-balance the stack. Actually, you give it 11 parameters (those two plus the nine registers) so you could put "add esp,(4*11)" and remove the 'popfd' and 'popad' (which are quite slow, so unless you 'need' the values replacing, you should do that.)
[Note: using invoke with wsprintf WILL place the stack cleanup after your call automatically, so in this case it's not a good idea to use it for that function; but for the MessageBox it's fine.]
No snowflake in an avalanche feels responsible.

boogara

Quote from: Tedd on October 01, 2007, 07:08:41 PM
Looks okay :wink Could be cleaned up by using 'invoke' though.
The add esp,8 is to clean up the stack after calling wsprintf -- it's a 'c-style' function, so it doesn't clean its parameters off the stack itself. So you have to clean up the 2 dword parameters (2 * 4 bytes = 8 bytes) to re-balance the stack. Actually, you give it 11 parameters (those two plus the nine registers) so you could put "add esp,(4*11)" and remove the 'popfd' and 'popad' (which are quite slow, so unless you 'need' the values replacing, you should do that.)
[Note: using invoke with wsprintf WILL place the stack cleanup after your call automatically, so in this case it's not a good idea to use it for that function; but for the MessageBox it's fine.]
Hehe, thanks.

As for the registry thing...I had another idea of just making a local variable (or multiple local variables if it's not possible the first way), and just continuously do a "mov val, [register]  push offset val  mov val, 0" kind of thing...which I also found somehwere else.

I don't quite understand why people would need to know the flags anyways, so...hey.

On the pop*d functions...if I did a push, but not a pop, would the registers be able to be edited?  (part of me says yes..but, whenever I read how pop/push work, it gets confusing at times.)

Tedd

Call it the 'register set' - the registry is something used by windows to store settings (could cause confusion :wink; technically it's 'register file' but causes even more confusion ::))

Not sure about that 'idea' :bdg You could push store them one-by-one, but you don't really gain anything by doing it - plus your value for the stack pointer is messed up.
The flags indicate the status of the last operation, so it's useful for debugging (what's the purpose of dumping the registers anyway?) In a binary form, you still need to decode the actual flags but it's better than nothing. {Possible extension if you get bored :bg}
Push just stores a copy of the value of the register on the stack, the register itself is unmodified and usable just as it was before. So you could push the same register 50 times if you want - makes no difference (though you might want to fix the stack again at some point = add esp,(4*50))
No snowflake in an avalanche feels responsible.

boogara

Quote from: Tedd on October 02, 2007, 11:49:04 AM
Call it the 'register set' - the registry is something used by windows to store settings (could cause confusion :wink; technically it's 'register file' but causes even more confusion ::))

Not sure about that 'idea' :bdg You could push store them one-by-one, but you don't really gain anything by doing it - plus your value for the stack pointer is messed up.
The flags indicate the status of the last operation, so it's useful for debugging (what's the purpose of dumping the registers anyway?) In a binary form, you still need to decode the actual flags but it's better than nothing. {Possible extension if you get bored :bg}
Push just stores a copy of the value of the register on the stack, the register itself is unmodified and usable just as it was before. So you could push the same register 50 times if you want - makes no difference (though you might want to fix the stack again at some point = add esp,(4*50))

Ahhh...alrighty.  Well, I'll do some research on Google and see what else I can find out about that then :)

That...and chances are it wouldn't improve speed (much), and might just add more overhead.  In the general view of things, dumping the registers doesn't serve any purpose...but, I know when I was tinkering with the FPU functions, it helped to catch where the problem(s) were.

Ahhhh, okay.  Makes sense.  It'd confuse me, because I'd read the comments on push/pop, and it'd be like, pushing would save the value, then pop would let you edit the register again.