Hi , I have assembled two files Example.asm and io.asm.
Io.asm defines some functions as public:
PUBLIC itoaproc, atoiproc
Example.asm tries to consume these functions by declaring them as EXTERN
However, while linking, there is an error
Cannot resolve reference _itoaproc, _atoiproc
Why is it expecting underscore prefixed symbols ? What is the solution ?
This can be only an error of syntax.He can be solve easily if you post your code here.
With Microsoft's ml.exe, when you declare a symbol as PUBLIC an underscore (_) is prefixed to the symbol in the OBJ file. Perhaps when you declare it as EXTERN you have to also add the underscore.
Quote from: donkey on December 03, 2010, 08:01:48 AM
With Microsoft's ml.exe, when you declare a symbol as PUBLIC an underscore (_) is prefixed to the symbol in the OBJ file. Perhaps when you declare it as EXTERN you have to also add the underscore.
Thanks for the confirmation. I believe this behaviour was not in MASM 5.1. Is there any workaround to it ?
Have you tried defining the symbol using the underscore in the EXTERN directive ? Beyond that I am not a MASM user so I cannot really help but the majority of members here are MASM guys, someone might have a better solution.
you might try using EXTERNDEF instead of PUBLIC/EXTERN
http://www.masm32.com/board/index.php?topic=15480
what i learned in that thread was that EXTERNDEF replaces both/either
madhur_ahuja,
Instead of members having to guess what you are doing and what masm version you are using, post some code instead of wasting their time.
Now that was rude. I think I provided enough info. OK. Attached are files. I have corrected the funtion names to include _ as suggested above.
I am using same version of ml.exe and link.exe as provided by latest build of masm32.
Hutch can be as nice or as rude as he likes - it is his forum
PUBLIC _itoaproc, _atoiproc, _dtoaproc, _atodproc, _outproc, _inproc, _szlenproc
PROC's are already PUBLIC - remove that line
_itoaproc PROC NEAR32
in FLAT model, you will rarely use FAR procs, and i am not sure NEAR32 is valid
just use PROC
_itoaproc PROC
also - good idea to specify root-relative paths in include/includelib
when you include a file, it is as though you pasted the text in where the include is
so - you do not need EXTERN, PUBLIC, EXTERNDEF
if you were creating a lib file (IO.LIB), then you need them
> Now that was rude.
No, just efficient, (well almost, no PROTOTYPES).
Stripped out the leading underscores, added STDCALL and removed the NEAR32 and "io.asm" builds into an object module correctly.
HELLO.ASM is missing the prototypes for the procedures in IO.ASM and apparently some macros.
Now I know that many nof our members are magicians who walk on water and are modest about it but with missing prototytpes and macros even they cannot make what is not there. Post that code and the rest looks reasonably simple to fix.
Just as an aside, the code looks like it was written back in the middle 90s for masm 6.11 by the notation and code style. Once you get it up and going you can do a lot better and a lot faster if it matters.
as Hutch mentioned, your problems are largely syntax
however, i also noticed that the procs use BASIC calling convention
easy to fix - the parms are reverse order
some parms are words - we always pass dwords to maintain stack alignment
not as easy to fix if other parts of this library are written to pass words - lol
but, it can and should be done
another big issue is that they are written as procs, but you are trying to call them as macros
in this case, they really should be procs
push/pop:
for win32, procs should preserve EBX, ESI, EDI, EBP, and the DF should remain cleared
EAX, ECX, and EDX can be trashed, and are often used to return results
you may assume the DF will be cleared
however, if the rest of this library is written to preserve a set DF, you may want to keep that until you fix all the procs
i see a lot of them pushf and popf - again - these are words
use pushfd and popfd to maintain stack alignment
pushing and poping can be done an easier way (see example below)
PROTO's:
we usually place protos near the beginning of the program
they do not need to declare stdcall or the names of parms (see example below)
once a proc has been PROTO'ed, you may use invoke to call it
here is a simple example of using PROTO
;proto's are placed near the beginning of the program
MyProc PROTO :DWORD,:DWORD
; .
; .
; .
.CODE
MyProc PROC uses ebx esi edi dwSource:DWORD,lpBuffer:DWORD
LOCAL dwSign:DWORD
mov eax,dwSource
cdq
or edx,1
mov dwSign,edx ;+1 of pos, -1 if neg
mov edi,lpBuffer
; .
; .
; .
ret
MyProc ENDP
notice that the "uses ebx esi edi" takes care of pushing/poping those registers
the masm prologue/epilogue takes care of the stack frame (ebp), assigning space for locals, and adjusting the stack after RET
now, to use the proc...
INVOKE MyProc,value,offset buffer
the PROTO must preceed the INVOKE in the source file
we pass the address of buffer - not it's contents
oh - i forgot to mention one thing....
all the procs you have in io.asm are replaced with modern better faster code in the masm32 libraries :bg
for the most part, thanks to Mr. Rude :U
What a mess. The file io.asm looks like some code I have by Richard Detmer, that has the same right to left parameter order. The Detmer examples specify:
.model flat, stdcall
And work out the difference with a set of interface macros.
You are right. its the code from that book.
My Bad! I forgot to include header file, which converts those procs to macros and takes care of other concerns you mentioned. I am pasting it below:
;IO.H - header file for I/O macros
; 32-bit version for flat memory model
; R. Detmer last revised 8/2000
.NOLIST ; turn off listing
.386
EXTERN itoaproc:near32, atoiproc:near32
EXTERN dtoaproc:near32, atodproc:near32
EXTERN inproc:near32, outproc:near32
itoa MACRO dest,source,xtra ;; convert integer to ASCII string
IFB <source>
.ERR <missing operand(s) in ITOA>
EXITM
ENDIF
IFNB <xtra>
.ERR <extra operand(s) in ITOA>
EXITM
ENDIF
push ebx ;; save EBX
mov bx, source
push bx ;; source parameter
lea ebx,dest ;; destination address
push ebx ;; destination parameter
call itoaproc ;; call itoaproc(source,dest)
pop ebx ;; restore EBX
ENDM
atoi MACRO source,xtra ;; convert ASCII string to integer in AX
;; offset of terminating character in ESI
IFB <source>
.ERR <missing operand in ATOI>
EXITM
ENDIF
IFNB <xtra>
.ERR <extra operand(s) in ATOI>
EXITM
ENDIF
push ebx ;; save EBX
lea ebx,source ;; source address to EBX
push ebx ;; source parameter on stack
call atoiproc ;; call atoiproc(source)
pop ebx ;; parameter removed by ret
ENDM
dtoa MACRO dest,source,xtra ;; convert double to ASCII string
IFB <source>
.ERR <missing operand(s) in DTOA>
EXITM
ENDIF
IFNB <xtra>
.ERR <extra operand(s) in DTOA>
EXITM
ENDIF
push ebx ;; save EBX
mov ebx, source
push ebx ;; source parameter
lea ebx,dest ;; destination address
push ebx ;; destination parameter
call dtoaproc ;; call dtoaproc(source,dest)
pop ebx ;; restore EBX
ENDM
atod MACRO source,xtra ;; convert ASCII string to integer in EAX
;; offset of terminating character in ESI
IFB <source>
.ERR <missing operand in ATOD>
EXITM
ENDIF
IFNB <xtra>
.ERR <extra operand(s) in ATOD>
EXITM
ENDIF
lea eax,source ;; source address to EAX
push eax ;; source parameter on stack
call atodproc ;; call atodproc(source)
;; parameter removed by ret
ENDM
output MACRO string,xtra ;; display string
IFB <string>
.ERR <missing operand in OUTPUT>
EXITM
ENDIF
IFNB <xtra>
.ERR <extra operand(s) in OUTPUT>
EXITM
ENDIF
push eax ;; save EAX
lea eax,string ;; string address
push eax ;; string parameter on stack
call outproc ;; call outproc(string)
pop eax ;; restore EAX
ENDM
input MACRO dest,length,xtra ;; read string from keyboard
IFB <length>
.ERR <missing operand(s) in INPUT>
EXITM
ENDIF
IFNB <xtra>
.ERR <extra operand(s) in INPUT>
EXITM
ENDIF
push ebx ;; save EBX
lea ebx,dest ;; destination address
push ebx ;; dest parameter on stack
mov ebx,length ;; length of buffer
push ebx ;; length parameter on stack
call inproc ;; call inproc(dest,length)
pop ebx ;; restore EBX
ENDM
.NOLISTMACRO ; suppress macro expansion listings
.LIST ; begin listing
Quote from: MichaelW on December 04, 2010, 06:12:39 AM
What a mess. The file io.asm looks like some code I have by Richard Detmer, that has the same right to left parameter order. The Detmer examples specify:
.model flat, stdcall
And work out the difference with a set of interface macros.
I only see .MODEL FLAT in my version.
Quote from: madhur_ahuja on December 04, 2010, 06:14:54 AM
I only see .MODEL FLAT in my version.
Yes, now that I check I had added the stdcall (in 2004).
The thread is a mess.
I don't think that it's a good idea to modify the sources. As you said, they are from a book, so it almost certainly once DID work. The sample uses the ".model flat" directive ( which tells me that they are intended for Masm v6.xx ), so everything should work without changes if you use Masm v6.14 included in Masm32.
The problem mentioned in the first post is a "name decoration" problem. Most likely it occurs because an option (-Gd) was missing in the command line when Masm was launched.
Btw, the io.inc which you posted still lacks the "output" macro, which is used in hello.asm, so it is of little help.
The "output" macro is there - it's just hard to see because the name is tabbed over to the position of the code. After I sorted out the paths in hello.asm:
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include io.inc
.LISTALL
includelib \masm32\lib\kernel32.lib
I assembled, linked, and tested with this batch file:
@echo off
set file1="io"
set file2="hello"
set lib=c:\masm32\lib
set path=c:\masm32\bin;%path%
if exist %file1%.obj del %file1%.obj
if exist %file2%.obj del %file2%.obj
if exist %file2%.exe del %file2%.exe
ml /c /coff %file1%.asm
pause
ml /c /coff %file2%.asm
pause
Link /SUBSYSTEM:CONSOLE %file2%.obj %file1%.obj
pause
%file2%.exe
echo.
echo.
pause
And there were no problems.
Quote from: MichaelW on December 04, 2010, 07:12:37 AM
The "output" macro is there - it's just hard to see because the name is tabbed over to the position of the code.
...
And there were no problems.
Thanks! Yes, no problems. And I additionally tried to remove the "_"-prefixes in io.asm and assembled it with the -Gd option: this also works.
Thanks guys. Either specifying -Gd or using .model flat, stdcall solves the problem.
However, I believe -Gd means C style function calling and naming conventions as per
http://msdn.microsoft.com/en-us/library/s0ksfwcf.aspx
But I don't see stack being cleaned up by caller as specified in:
http://en.wikipedia.org/wiki/X86_calling_conventions
Am I missing something ?
For a procedure that uses the C calling convention ML would encode the return instruction to not remove the parameters from the stack, and invoke would add code to remove the parameters from the stack after the call returned. In my tests with ML6.15, and a STDCALL procedure, -Gd did affect the naming convention, but did not affect the encoding of the return instruction or the calling convention that invoke assumed.
Quote from: madhur_ahuja on December 04, 2010, 07:52:34 AM
But I don't see stack being cleaned up by caller as specified in:
http://en.wikipedia.org/wiki/X86_calling_conventions
Am I missing something ?
He has explicitly made the procedures into STDCALL by using RET with a value, this will adjust the stack by the number of bytes specified, for example in the _dtoaproc his return is
ret 8 which will add 8 to ESP before returning.
BASIC uses this calling convention - reverse parm order, but corrects the stack as in STDCALL
anyways, this is some old stuff - lol
if this is for school, you may not have any choice but to work with it
but, if you are trying to learn masm from a book (on your own), i suggest you get some new stuff
this library can create some bad habits for you
all registers are preserved and the math procs set the flags to indicate the results
very few modern procs work that way
the worst thing is, some procs use word-sized parms
for modern code that uses word parms, dwords are passed to maintain stack alignment
if you modify the procs to be up to date, then much of the example code in the book will not work
Yes, this is for self learning and not a school. Can you suggest some other reference ?
truthfully, you do not need to buy a book
install the masm32 package
the package contains macros, libraries, example code, help files, tutorials
the link is in the upper right hand corner of the forum
also in those links, you will find Iczelion's Tutorials - a great way to get started for win32
EDIT
have a look around in those links - a lot of material
another thing you will find in there is a link to Intel Programmer's Reference Manuals
that will cover the instruction set
also - Randy Hyde has a nice online reference....
http://www.arl.wustl.edu/~lockwood/class/cs306/books/artofasm/toc.html
Thanks a lot :U