Search the web
Sign In
New User? Sign Up
apj-announce · Announcement group
? Already a member? Sign in to Yahoo!

Yahoo! Groups Tips

Did you know...
Want your group to be featured on the Yahoo! Groups website? Add a group photo to Flickr.

Best of Y! Groups

   Check them out and nominate your group.
Having problems with message search? Fill out this form to ensure your group is one of the first to be migrated to the new message search system.

Messages

  Messages Help
Advanced
APJ Issue#4 Apr/Jun 99   Message List  
Reply | Forward Message #9 of 18 |
::/ \::::::.
:/___\:::::::.
/| \::::::::.
:| _/\:::::::::.
:| _|\ \::::::::::.
Apr-June 99
:::\_____\::::::::::.
Issue 4
::::::::::::::::::::::.................................................
........

A S S E M B L Y P R O G R A M M I N G J O U R N A L
http://asmjournal.freeservers.com
asmjournal@...




T A B L E O F C O N T E N T S
----------------------------------------------------------------------
Introduction...................................................mammon_

"Using COM in Assembly Language"..........................Lord.Lucifer

"Stack Frames and High-Level Calls"............................mammon_

"Define Your Memory".......................................Alan Baylis

"Writing a Boot Sector in A86"...........................Jan Verhoeven

"A Basic Virus Writing Primer"...................................Chili

Column: Win32 Assembly Programming
"Mouse Input....".........................................Iczelion
"Menus"...................................................Iczelion

Column: The C standard library in Assembly
"C string functions:_strtok"................................Xbios2

Column: The Unix World
"Using Menus in Xt"........................................mammon_

Column: Assembly Language Snippets
"Triple XOR".........................................Jan Verhoeven
"Trailing Calls".....................................Jan Verhoeven

Column: Issue Solution
"Fire Demo"....................................................iCE
----------------------------------------------------------------------
+++++++++++++++++++++Issue Challenge+++++++++++++++++++
Write a "Fire Demo"-style program in less than 100 bytes
----------------------------------------------------------------------


::/ \::::::.
:/___\:::::::.
/| \::::::::.
:| _/\:::::::::.
:| _|\ \::::::::::.
:::\_____\:::::::::::..............................................INTR
ODUCTION
by
mammon_


In the last few months I have come across a number of links to APJ, and
have
received the proverbial ton of email regarding it. Strangely enough, the
majority of these tend to agree that the one problem with the journal
is its
infrequent --if not irregular-- publication. If that is the only
complaint so
far, I think I can cope with it ;)

This issue is, naturally, very late due to what could be called "real
world"
[lit., "that which does not go away when a power outtage kills your PC"]
considerations; however the articles by weight alone should make up for
some
of this.

The largest of the bunch is undoubtedly the virus writing tutorial by
Chili,
who may have beat my previous record for article length: a very
thorough work,
worth reading just to help protect against virii, if not to write them.
This
is accompanied by Jan's discussion of boot sector programming...a
suitable
companion article, I believe.

High-level coders will undoubtedly be interested in Lord Lucifer's
article on
COM programming in assembly; it seems that high-level areas such as COM,
DirectDraw, and Winsock coding are starting to receive a fair degree of
attention from the assembly language world, judging from the tutorials
I have
been coming across.

Xbios2 has continued his excellent C stdlib work, and Icezlion has
contributed
two more of his now-legendary Win32 asm tutorials; I of course have
kept up
the Unix vanguard with yet another Xt article.

This month's challenge was contributed by iCE, and had a .text-size I
could
not readily beat.

A few brief notes concerning the web page: I have thrown together a
basic
collection of assembly language links at
http://asmjournal.freeservers.com/lynx.html
Submissions for this links page are welcome. I have also been getting a
few
emails to the APJ inbox asking or offering help with assembly language;
since
I check the inbox fortnightly at best, I have added a "classified ads"
page to
the APJ website at
http://www.guestbook4free.com/en/28806/entries/
which is essentially a guestbook where people can post contact info,
projects
they need help with, etc ... more or less a one-way bulletin board
like, well,
like classified ads are.

That should just about wrap things up. Enjoy the issue!

_m


::/ \::::::.
:/___\:::::::.
/| \::::::::.
:| _/\:::::::::.
:| _|\ \::::::::::.
:::\_____\:::::::::::...........................................FEATURE
.ARTICLE
Using COM in Assembly
Language
by Lord Lucifer


This article will discuss how to use COM interfaces in your assembly
language
programs. It will not discuss what COM is and how it is used, but
rather how
it can be used when programming in assembler. It will discuss only how
to
use existing interfaces, and not how to actually implement new ones;
this will
be shown in a future atricle.


About COM
-----------------------------------------------------------------------
-------

Here is a brief introduction to the basics behind COM.

A COM object is one in which access to an object's data is achieved
exclusively through one or more sets of related functions. These
function
sets are called interfaces, and the functions of an interface are called
methods. COM requires that the only way to gain access to the methods
of an
interface is through a pointer to the interface.

An interface is actually a contract that consists of a group of related
function prototypes whose usage is defined but whose implementation
is not. An interface definition specifies the interface's member
functions,
called methods, their return types, the number and types of their
parameters,
and what they must do. There is no implementation associated with an
interface. An interface implementation is the code a programmer
supplies to
carry out the actions specified in an interface definition.

An instance of an interface implementation is actually a pointer to an
array
of pointers to methods (a function table that refers to an
implementation of
all of the methods specified in the interface). Any code that has a
pointer
through which it can access the array can call the methods in that
interface.



Using a COM object assembly language
-----------------------------------------------------------------------
--------

Access to a COM object occurs through a pointer. This pointer points
to a
table of function pointers in memory, called a virtual function table,
or
vtable in short. This vtable contains the addresses of each of the
objects
methods. To call a method, you indirectly call it through this pointer
table.

Here is an example of a C++ interface, and how its methods are called:

interface IInterface
{
HRESULT QueryInterface( REFIID iid, void ** ppvObject );
ULONG AddRef();
ULONG Release();
Function1( INT param1, INT param2);
Function2( INT param1 );
}

// calling the Function1 method
pObject->Function1( 0, 0);

Now here is how the same functionality can be implemented using assembly
language:

; defining the interface
; each of these values are offsets in the vtable
QueryInterface equ 0h
AddRef equ 4h
Release equ 8h
Function1 equ 0Ch
Function2 equ 10h

; calling the Function1 method in asm
; the method is called by obtaining the address of the objects
; vtable and then calling the function addressed by the proper
; offset in the table
push param2
push param1
mov eax, pObject
push eax
mov eax, [eax]
call [eax + Function1]

You can see this is somewhat different than calling a function normally.
Here, pObject points to the Interface's vTable. At the Function1(0Ch)
offset
in this table is a pointer to the actual function we wish to call.



Using HRESULT's
-----------------------------------------------------------------------
--------

The return value of OLE APIs and methods is an HRESULT. This is not a
handle
to anything, but is merely a 32-bit value with several fields encoded
in the
value. The parts of an HRESULT are shown below.

HRESULTs are 32 bit values layed out as follows:

3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+-+-+-+-+-+---------------------+-------------------------------+
|S|R|C|N|r| Facility | Code |
+-+-+-+-+-+---------------------+-------------------------------+

S - Severity Bit
Used to indicate success or failure
0 - Success
1 - Fail

By noting that this bit is actually the sign bit of the 32-bit
value,
checking success/failure is simply performed by checking its sign:

call ComFunction ; call the function
test eax,eax ; now check its return value
js error ; jump if signed (meaning error
returned)
; success, so continue

R - reserved portion of the facility code, corresponds to NT's
second severity bit.

C - reserved portion of the facility code, corresponds to NT's
C field.

N - reserved portion of the facility code. Used to indicate a
mapped NT status value.

r - reserved portion of the facility code. Reserved for internal
use. Used to indicate HRESULT values that are not status
values, but are instead message ids for display strings.

Facility - is the facility code
FACILITY_WINDOWS = 8
FACILITY_STORAGE = 3
FACILITY_RPC = 1
FACILITY_WIN32 = 7
FACILITY_CONTROL = 10
FACILITY_NULL = 0
FACILITY_ITF = 4
FACILITY_DISPATCH = 2

To retreive the Facility,

call ComFunction ; call the function
shr eax, 16 ; shift the HRESULT to the right by 16
bits
and eax, 1FFFh ; mask the bits, so only the facility
remains
; eax now contains the HRESULT's Facility code

Code - is the facility's status code

To get the Facility's status code,
call ComFunction ; call the function
and eax, 0000FFFFh ; mask out the upper 16 bits
; eax now contains the HRESULT's Facility's status code



Using COM with MASM
-----------------------------------------------------------------------
-------
If you use MASM to assemble your programs, you can use some of its
capabilities to make calling COM functions very easy. Using invoke,
you can
make COM calls look almost as clean as regular calls, plus you can add
type
checking to each function.


Defining the interface:

IInterface_Function1Proto typedef proto :DWORD
IInterface_Function2Proto typedef proto :DWORD, :DWORD

IInterface_Function1 typedef ptr IInterface_Function1Proto
IInterface_Function2 typedef ptr IInterface_Function2Proto

IInterface struct DWORD
QueryInterface IUnknown_QueryInterface ?
AddRef IUnknown_AddRef ?
Release IUnknown_Release ?
Function1 IInterface_Function1 ?
Function2 Interface_Function2 ?
IInterface ends

Using the interface to call COM functions:

mov eax, pObject
mov eax, [eax]
invoke (IInterface [eax]).Function1, 0, 0

As you can see, the syntax may seem a bit strange, but it allows for a
simple
method using the function name itself instead of offsets, as well as
type
checking.



A Sample program written using COM
-----------------------------------------------------------------------
-------

Here is some sample source code which uses COM written in straight
assembly
language, so it should be compatable with any assembler you prefer with
only
minor changes necessary.

This program uses the Windows Shell Interfaces to show the contents of
the
Desktop folder in a window. The program is not complete, but shows how
the
COM library is initialized, de-initialized, and used. I also shows how
the
shell library is used to get folders and obcets, and how to perform
actions on them.


..386
..model flat, stdcall

include windows.inc ; include the standard windows header
include shlobj.inc ; this include file contains the shell
namespace
; definitions and constants

;----------------------------------------------------------
..data
wMsg MSG <?>
g_hInstance dd ?
g_pShellMalloc dd ?

pshf dd ? ; shell folder object
peidl dd ? ; enum id list object

lvi LV_ITEM <?>
iCount dd ?
strret STRRET <?>
shfi SHFILEINFO <?>
...

;----------------------------------------------------------
..code
; Entry Point
start:
push 0h
call GetModuleHandle
mov g_hInstance,eax

call InitCommonControls

; initialize the Component Object Model(COM) library
; this function must be called before any COM functions are called
push 0
call CoInitialize
test eax,eax ; error when the MSB = 1
; (MSB = the sign bit)
js exit ; js = jump if signed

; Get the Shells IMalloc object pointer, and save it to a global
variable
push offset g_pShellMalloc
call SHGetMalloc
cmp eax, E_FAIL
jz shutdown


; here we would set up the windows, list view, message loop, and so
on....
; we would also call the FillListView procedure...
; ....


; Cleanup
; Release IMalloc Object pointer
mov eax, g_pShellMalloc
push eax
mov eax, [eax]
call [eax + Release] ; g_pShellMalloc->Release();

shutdown:
; close the COM library
call CoUninitialize

exit:
push wMsg.wParam
call ExitProcess
; Program Terminates Here


;----------------------------------------------------------
FillListView proc

; get the desktop shell folder, saved to pshf
push offset pshf
call SHGetDesktopFolder

; get the objects of the desktop folder using the EnumObjects method of
; the desktop's shell folder object
push offset peidl
push SHCONTF_NONFOLDERS
push 0
mov eax, pshf
push eax
mov eax, [eax]
call [eax + EnumObjects]

; now loop through the enum id list
idlist_loop:
; Get next id list item
push 0
push offset pidl
push 1
mov eax, peidl
push eax
mov eax, [eax]
call [eax + Next]
test eax,eax
jnz idlist_endloop

mov lvi.imask, LVIF_TEXT or LVIF_IMAGE
mov lvi.iItem,

; Get the item's name by using the GetDisplayNameOf method
push offset strret
push SHGDN_NORMAL
push offset pidl
mov eax, pshf
push eax
mov eax, [eax]
call [eax + GetDisplayNameOf]
; GetDisplayNameOf returns the name in 1 of 3 forms, so get the correct
; form and act accordingly
cmp strret.uType, STRRET_CSTR
je strret_cstr
cmp strret.uType, STRRET_OFFSET
je strret_offset

strret_olestr:
; here you could use WideCharToMultiByte to get the string,
; I have left it out because I am lazy
jmp strret_end

strret_cstr:
lea eax, strret.cStr
jmp strret_end

strret_offset:
mov eax, pidl
add eax, strret.uOffset

strret_end:
mov lvi.pszText, eax

; Get the items icon
push SHGFI_PIDL or SHGFI_SYSICONINDEX or SHGFI_SMALLICON or
SHGFI_ICON
push sizeof SHFILEINFO
push offset shfi
push 0
push pidl
call SHGetFileInfo
mov eax, shfi.iIcon
mov lvi.iImage, eax

; now add item to the list
push offset lvi
push 0
push LVM_INSERTITEM
push hWndListView
call SendMessage

; repeat the loop
idlist_endloop:

; now free the enum id list
; Remember all allocated objects must be released...
mov eax, peidl
push eax
mov eax,[eax]
call [eax + Release]

; free the desktop shell folder object
mov eax, pshf
push eax
mov eax,[eax]
call [eax + Release]

ret
FillListView endp


END start


Conclusion
-----------------------------------------------------------------------
--------

Well, that is about it for using COM with assembly language.
Hopefully, my
next article will go into how to define your own interfaces. As you can
see, using COM is not difficult at all, and with it you can add a very
powerful capability to your assembly language programs.



::/ \::::::.
:/___\:::::::.
/| \::::::::.
:| _/\:::::::::.
:| _|\ \::::::::::.
:::\_____\:::::::::::...........................................FEATURE
.ARTICLE
Stack Frames and
High-Level Calls
by mammon_


Last month I covered how to implement high-level calls in Nasm. Since
then it
has come to my attention that many beginning programmers are unfamiliar
with
calling conventions and the stack frame; to remedy this I have prepared
a brief
discussion of these topics.

The CALL Instruction
--------------------
At its most basic, an assembly language call takes this for:
push [parameters]
call [address]
Some assemblers will require that the CALL statement take as an rgument
only
addresses leading to external functions or addresses created with a
macro or
directive such as PROC. However, as a quick glance through a debugger
or a
passing familiarity with Nasm will demonstrate, the CALL instruction
simply
jumps to an address [often a label in the source code] while pushing the
contents of EIP [containing the address of the instruction following
the call]
onto the stack. The CALL instruction is therefore equivalent to the
following
code:
push EIP
jmp [address]

The address that has been called will thefore have the stack set up as
follows:
[Last Parameter Pushed]: DWORD
[Address of Caller] : DWORD
--- "Top" of Stack [esp] ---
At this point, anything pushed onto the stack will be on top of [that
is, with a
lower memory address, since the stack "grows" downwards] the return
address.

The Stack Frame
---------------
Note that the parameters to the call therefore cannot be POPed from the
stack,
as this will destroy the saved return address and thus cause the
application to
crash upon returning from the call [unless, of course, a chosen return
address
is PUSHed onto the stack before returning from the call]. The logical
way to
reference these parameters, then, would be as offsets from the stack
pointer:
[parameter 2] : DWORD esp + 8
[parameter 1] : DWORD esp + 4
[Address of Caller]: DWORD esp
----- "Top" of Stack [esp] -----
In this example, "parameter 1" is the parameter pushed onto the stack
last, and
"parameter 2" is the parameter pushed onto the stack before parameter
1, as
follows:
push [parameter 2]
push [parameter 1]
call [procedure]
The problem with referring to parameter as offsets from esp is that esp
will
change whenever a value is PUSHed onto the stack during the routine.
For this
reason, it is standard for routines which take parameters to set up a
"stack
frame".

In a stack frame, the base pointer [ebp] is set equal to the stack
pointer [esp]
at the start of the call; this provides a "base" address from which
parameters
can be addressed as offsets. It is assumed that the caller had a stack
frame
also; thus the value of ebp must be preserved in order to prevent
causing damage
to the caller. The stack frame usually takes the following form:
push ebp
mov ebp, esp
... [actual code for the routine] ...
mov esp, ebp
pop ebp
This means that once the stack frame has been entered, the stack has the
following structure:
[parameter 2] : DWORD ebp + 12
[parameter 1] : DWORD ebp + 8
[Address of Caller]: DWORD ebp + 4
[Old Base Pointer] : DWORD ebp
----- Base Pointer [ebp] -----
----- "Top" of Stack [esp] -----
The use of the base pointer also allows space to be allocated on the
stack for
local variables. This is done by simply subtracting bytes from esp;
since esp is
restored when the stack frame is exitted, this space will automatically
be
deallocated. The local variables are then referred to as *negative*
offsets from
ebp; these may be EQUed to meaningful symbol names in the source code.
A routine
that has 3 local DWORD variables would take the following form:
Var1 EQU [ebp-4]
Var2 EQU [ebp-8]
Var3 EQU [ebp-12] ;provide meaningful names for the
variables
push ebp
mov ebp, esp
sub esp, 3*4 ;3 DWORDs at 4 BYTEs apiece
... [actual code for the routine] ...
mov esp, ebp
pop ebp
This routine would then have the following stack structure after the
allocation
of the local variables:
[parameter 2] : DWORD ebp + 12
[parameter 1] : DWORD ebp + 8
[Address of Caller]: DWORD ebp + 4
[Old Base Pointer] : DWORD ebp
----- Base Pointer [ebp] -----
[Var1] : DWORD ebp - 4
[Var2] : DWORD ebp - 8
[Var3] : DWORD ebp - 12
----- "Top" of Stack [esp] -----

The stack frame has can also be used to provide a call trace, as it
stores the
base pointer of [and thus a pointer to the caller of] the caller.
Assume that a
program has the following flow of execution:
proc_1: push dword call1_p2
push dword call1_p1
call proc_2
________proc_2: push call2_p1
call proc_3
________________proc_3: push call3_p1
call proc_4
Upon creation of the stack frame in proc_4, the stack has the following
structure:
[call1_p2] : DWORD ebp + 36
[call1_p1] : DWORD ebp + 32
[Return Addr of Call1] : DWORD ebp + 28
[Old Base Pointer] : DWORD ebp + 24
---- Base Pointer of Call 1 ----
[call2_p1] : DWORD ebp + 20
[Return Addr of Call2] : DWORD ebp + 16
[Base Pointer of Call1]: DWORD ebp + 12
---- Base Pointer of Call 2 ----
[call3_p1] : DWORD ebp + 8
[Return Addr of Call3] : DWORD ebp + 4
[Base Pointer of Call2]: DWORD ebp
----- Base Pointer [ebp] -----
----- "Top" of Stack [esp] -----
As you can see, for each previous call the return address is [ebp+4],
where ebp
is the address of the saved base pointer for the call previous to that
one.
Thus, if one could traverse the history of stack frames as follows:
mov eax, ebp ; eax = address of previous ebp
mov ecx, 10 ; trace the last 10 calls
loop_start:
mov ebx, [eax+4] ; ebx = return address for call
call print_stack_trace
mov eax, [eax] ; step back one stack frame
loop loop_start
This is exceptionally useful for exception handling; the handling
function will
be able to print out a stack history to aid debugging. This principle
can also
be applied in conjunction with debugging code [for example, the Win32
debug API]
to create a utility which will trace the calls [in reality, the stack
frames of
the calls] made by a target. Essentially, this would boil down to the
following
logic:
1) Breakpoint on changes to EBP
2) On Break, get return address [ebp+4]
3) Get instruction prior to return address
4) Print or log the instruction
Note that this can be enhanced to resolves symbol names in the logged
CALL
instruction, such that local or API address labels [e.g.
GetWindowTextA] can be
logged rather than just the address itself.

The ENTER Instruction
---------------------
The ENTER instruction is used to create a stack frame with a single
instruction;
it is equivalent to the code
push ebp
mov ebp, esp
The ENTER instruction takes a first parameter that specifes the number
of bytes
to reserve for local variables; an optional second parameter gives the
nesting
level [0-31] of the current stack frame in the overall program
structure. This
is often used by high-level languages to save call trace information
for error
handlers, as it specifies the number of additional [previous] stack
frame pointers
to save on the stack.

The RET Instruction
-------------------
Any routine which is accessed by a CALL instruction must be terminated
with a
return [RET] instruction. As one can see from the operation of the CALL
instruction, if you were to attempt to circumvent the RET instruction
by JMPing
to the retrun address, the stack would still be corrupted. The RET
statement is
roughly equivalent to the following code:
pop EIP

Note that the RET must take place after exiting the stack frame in
order to
avoid corruption of the stack.

The LEAVE Instruction
---------------------
The LEAVE instruction is used to exit a stack frame created with the
ENTER
instruction; it is equivalent to the code
mov esp, ebp
pop ebp
The LEAVE instruction takes no parameters and still requires a RET
statement to
follow it.

High-level Language Calling Conventions
---------------------------------------
At this point one may wonder what has happened to the parameters pushed
onto the
stack prior to the call. Are they still on the stack after the RET, or
have they
been cleared? Since the parameters cannot be POPed from the stack while
within
the call, they still are on the stack at the RET instruction.

At this point the programmer has two options. They can have the caller
clean up
the stack by adding the number of bytes pushed to esp immediately after
the
call:
push dword param2
push dword param1
call procedure
add esp, 2 * 4 ;2 DWORDs at 4 BYTEs apiece
Or they can clear the stack by passing to the RET instruction the
number of
bytes that need to be cleared:
push dword param2
push dword param1
call procedure
...
procedure:
push ebp
mov ebp, esp
...
mov esp, ebp
pop ebp
ret 8 ;2 DWORDs at 4 BYTEs apiece
Which method is chosen is left up to the programmer; however, when
writing a
library or API, one must make clear who is responsible for cleaning up
the
stack. In addition, when interfacing with high-leve languages, one also
has to
make clear which order the parameters are to be pushed in. For this
reason there
are calling conventions for the high-level languages.

The C calling convention is used to interface with the C and C++
programming
languages; it is used in the standard C library and in Unix APIs. It
pushes the
parameters from right to left, and does not clean up the stack upon
return from
the call. A call to a C-style routine would look as follows:
;corresponds to the C code
;procedure(param1, param2)
push dword param2
push dword param1
call procedure
add esp, 8
A C-style routine would have the following structure:
push ebp
mov ebp, esp
...
mov esp, ebp
pop ebp
ret

The Pascal calling convention is used interface with the Pascal, BASIC,
and
Fortran programming languages; it is used in the Win16 API. It pushes
the parameters
from left to right, and cleans up the stack upon return from the call;
as such
it is the opposite of the C convention. A call to a Pascal routine
would look as
follows:
;corresponds to the C code
;procedure(param1, param2)
push dword param1
push dword param2
call procedure
A Pascal-style routine would have the following structure:
push ebp
mov ebp, esp
...
mov esp, ebp
pop ebp
ret 8 ;clear the 2 dword parameters

The Stdcall ["standard call" or __stdcall] calling convention is a
combination
of the C and Pascal conventions; it is used in the Win32 API. It pushes
the
parameters from right to left, and cleans the stack upon return from
the call. A
call to a Stdcall routine would look as follows:
;corresponds to the C code
;procedure(param1, param2)
push dword param2
push dword param1
call procedure
A Stdcall-style routine would have the following structure:
push ebp
mov ebp, esp
...
mov esp, ebp
pop ebp
re




Wed Sep 15, 1999 12:53 pm

hiroshimator@...
Send Email Send Email

Forward
Message #9 of 18 |
Expand Messages Author Sort by Date

... /| \::::::::. ... Apr-June 99 ... Issue 4 ... ........ A S S E M B L Y P R O G R A M M I N G J O U R N A L http://asmjournal.freeservers.com ...
hiroshimator@...
Send Email
Sep 15, 1999
12:50 pm
Advanced

Copyright © 2009 Yahoo! Inc. All rights reserved.
Privacy Policy - Terms of Service - Guidelines - Help