What's up ?

This may be a dumb question, but it's coming from a newbie.

Is it possible to link procadures with VC++ without using the PROC directive ?

I successfully linked the following proceadure with C++ using VC++ 6:

// C++ PART:

extern "C"
{
int __stdcall Sum(unsigned int a, unsigned int b);
}

int main() {

int a = Sum(3, 4);
cout << "Sum: " << a << endl;

return 0;
}

; ASM PART:

Sum proc a: DWORD, b: DWORD

mov eax, a
add eax, b

ret
Sum endp

The above code works as expected. But for learning purposes I'd like NOT to
use MASM's PROC facility.
I'd like to declare the proceadure using only labels, and manipulating the stack
by hand. Something like this:

_Sum:

push ebp
mov epb, esp
; sub esp, 0

mov eax,
add eax, ; Does this work ?

mov esp, ebp
pop ebp
ret


Is it possible ?

Thx in advance
Posted on 2003-08-20 01:05:29 by Waka
Hi, Waka

really, PROC is a macro, that does (in your case):
push ebp
mov epb, esp

so you can use with your current ASM (to disable this macro:


option prologue:none
option epilogue:none


or

; ASM PART:
Sum LABEL DWORD

or (should be the same, but shorter)


mov eax, [esp + 12 - DWORD]
add eax, [esp + 8 - DWORD]
ret
Posted on 2003-08-20 02:35:28 by S.T.A.S.
Thanks, S.T.A.S.




Sum LABEL DWORD

mov eax, [esp + 12 - DWORD]
add eax, [esp + 8 - DWORD]


What does 'DWORD' mean in this case ?
I changed my previous code to that above, but now I can't link it to the C++ code,
it does assemble though

Thank you.
Posted on 2003-08-20 03:30:51 by Waka
DWORD = 4.

Who ever said a stack frame is needed?


_Sum:
pop edx
pop ecx
pop eax
add eax, ecx
push edx
retn

Though the above code I cleared the stack

For some less destructive code:


_Sum:
mov eax, [esp+4]
add eax, [esp+8]
retn

Hmm my code looks so much like S.T.A.S's.
Posted on 2003-08-20 08:44:23 by roticv

now I can't link it to the C++ code


well, i'm not good at linking with C code ;)
I just supposed if you can link to"Sum proc a: DWORD, b: DWORD", then you could link to that label.

may be this can help:

Syntax: PUBLIC name [, name]...

Description:

Makes one or more variables available to other modules in the
program. PUBLIC names can be forward referenced.



I still suggest to use:
option prologue:none

option epilogue:none

since this does enforce assembler don't generate stuff like:
push ebp
mov epb, esp
; sub esp, 0
and all labels that are inside proc are LOCAL by default, so you can avoid some bugs.


Syntax: OPTION PROLOGUE:macroname

OPTION EPILOGUE:macroname

Description:

PROLOGUE registers <macroname> as the macro function to be called
when a prologue needs to be generated. EPILOGUE registers
<macroname> as the macro procedure to be called when a RET or IRET
instruction is encountered.

You can revert to the default prologue or epilogue by specifying
PrologueDef or EpilogueDef as <macroname>. EPILOGUE code is

generated only if the RET or IRET instruction terminating the PROC
block has no operand. The RETN, RETF, and IRETF instructions do not
cause the assembler to generate epilogue code.

To suppress generation of the prologue or epilogue code, give NONE
as the <macroname>.

The assembler expects a macro definition of this form:

macroname MACRO procname, flags, argbytes, localbytes, <reglist>,
userparms:VARARG


Parameter Description

procname Macro name for the procedure or NONE.

flags Word-size bit flag: (1=On, 0=Off)
Bits Description
0-2 Language type:
000 Not specified
001 C
010 SYSCALL
011 STDCALL
100 Pascal
101 Fortran

110 Basic
111 Reserved
3 Reserved
4 Caller restores stack
5 FAR procedure
6 PRIVATE procedure
7 EXPORT procedure
8 Epilogue caused by IRET instruction

All other bits are reserved for future use.

argbytes The total number of bytes used by PROC arguments.


localbytes The total number of bytes used by variables defined
with the LOCAL directive inside the PROC block.

reglist Comma-delimited list of registers from the PROC
directive USE option. This list is reversed in
in the EPILOGUE directive. Angle brackets are
passed.

userparms Passed the optional macroarglist from the PROC
directive.


her is example of macros i'm using (I don't like use EBP for stack frame, because it can be another free register for use in asm):


sPrologue MACRO procname, flags, argbytes, localbytes, reglist,userparms:VARARG
ifnb reglist ;if there are registers to be saved, store them
for r,reglist
push r ;dont forget optimize: mov [esp...], : sub esp,vars
endm
endif
if localbytes NE 0
sub esp, localbytes ; make space on the stack for locals
; LocBytes equ localbytes ;these bytes are reserved for local vars on the stack
endif
exitm <localbytes>
endm

sEpilogue MACRO procname, flags, argbytes, localbytes, reglist,userparms:VARARG
if localbytes NE 0
add esp,localbytes ;; free space on the stack for locals
endif
ifnb reglist ;; Pop off the registers -- they are in
for r,reglist ;; inverse order from the prologue call
pop r
endm
endif
ret argbytes
endm


What does 'DWORD' mean in this case ?

DWORD = 4
"push ebp" does this:
1. moves value of EBP to address
2. subtracts from ESP SizeOf(DWORD)
3. adds to EIP SizeOf("push ebp" opcode)

so if we use ESP instead of EBP wee need to balance the stack "by hands" but it saves some bytes for us ;)


Hmm my code looks so much like S.T.A.S's.

so does mine:
_Sum:

pop edx
pop ecx
pop eax
add eax, ecx
jmp edx

;)
Posted on 2003-08-20 09:35:23 by S.T.A.S.
some quicker one


mov eax, [esp+8]
add eax, [esp+4]
mov ecx, [esp]
;mov ebx, [esp] :(
add esp, 3*DWORD
jmp eCx
Posted on 2003-08-20 09:44:27 by S.T.A.S.
Bad for linking to VC++ because the compiler requires EBX (plus ESI, EDI, and EBP) to be preserved.
Use ECX or EDX instead of EBX.
Posted on 2003-08-20 22:06:20 by tenkey
Thanks, tenkey!
Posted on 2003-08-20 22:30:11 by S.T.A.S.
Hey, guys !

Thanks for answering.

But, my initial problem was to make VC++ 'see' the
proceadure label. How can I make MASM labels and variables
available to be used on VC++ ?

BTW, I didn't understand your macros, S.T.A.S. Thanks for
your comprehensive post anyway. Do you know a good reference
for me to learn to use macros ? A tutorial perhaps ? (besides
MASM manual).

My intention now is to replace some parts of a program
I made in C with ASM, to see if I can make it faster and
to learn how it's done.

Thanks.
Posted on 2003-08-20 22:42:05 by Waka
In C++ mode, extern "C" __stdcall in VC will generate a link name which is "_" + function-name + "@" + number-of-argument-bytes. The number of argument bytes is in decimal.

In your example, the linker will see that VC wants to link to _Sum@8.

If you use PUBLIC or EXTERNDEF, the name you use will probably be Sum@8 or _Sum@8.

Since you specify stdcall in the C code, you will eat up stack space if your function is called from a loop. Use ret 8 to delete the 8 bytes of argument from the stack.
Posted on 2003-08-20 23:35:01 by tenkey

I successfully linked the ... procedure with C++ using VC++ 6

Doesn't this works?
option prologue:none

option epilogue:none

I'm not good at the theory.
I just know that EXTERN/EXTERNDEF make asm "see" C labels :)
and I hope that PUBLIC will make your label "visible" for link.exe

Problem may be with exporting/importing of labels, since ms link uses
_imp__SomeFunc@N or _SomeFunc@N instead of SomeFuncI (N = bytes of parameters on the stack)
take a look inside .obj files, sure you'll find the answer

I've experiensed problems with linking my asm files a while ago, but found the solution and forgot it :(
Posted on 2003-08-20 23:37:25 by S.T.A.S.
I did this:



PUBLIC _Test
_Test: ; do nothing

ret


or this:


PUBLIC _Test
_Test LABEL DWORD ; do nothing

ret


But looking inside the obj file, I don't see the label.
How can even another asm file "see" the label if it's not inside
the obj file ?


Doesn't this works?



Doesn't this works?
option prologue:none
option epilogue:none



This does work, but I would like to it using only labels.
And I would like to have access to the global variables of the ASM file also.

Thanks once more !
Posted on 2003-08-21 00:23:13 by Waka

But looking inside the obj file, I don't see the label.
How can even another asm file "see" the label if it's not inside
the obj file ?


IMHO compiler did some optimization ;)

does PUBLIC label works or not? this should...

really in asm there are some ways to define label:
1. dummy label dword
2. dummy equ $
3. proc dummy (this will generate stuff like mov ebp, esp until you spacify option prologue:none
Posted on 2003-08-21 01:35:28 by S.T.A.S.