Hi friends,
Here a simple example using functions from Pelle's C run-time static library crt.lib :
.386
.model flat,stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\user32.inc
include \masm32\include\masm32.inc
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\user32.lib
includelib \masm32\lib\masm32.lib
includelib \pellesc\lib\crt.lib ; Pelle's CRT static library
strcat PROTO C :DWORD,:DWORD
strstr PROTO C :DWORD,:DWORD
strchr PROTO C :DWORD,:DWORD
.data
dest db 'strcat example : ',0
db 20 dup(0)
source db 'Hello my friend',13,10,0
string2 db 'friend',0
crlf db 13,10,0
.data?
buffer db 20 dup(?)
.code
start:
invoke strcat,ADDR dest,ADDR source
invoke StdOut,ADDR dest
invoke strstr,ADDR dest,ADDR string2
call print
invoke strchr,ADDR dest,114 ; look for 'r'
call print
invoke ExitProcess,0
print PROC
invoke dw2hex,eax,ADDR buffer
invoke StdOut,ADDR buffer
invoke StdOut,ADDR crlf
ret
print ENDP
END start
[attachment deleted by admin]
Vortex,
Nice example. It works fine for me as it is.
If I try to use printf instead of the MASM32 functions, it doesn't work correctly when linking with the static crt.lib. If I change the includelib to use the dynamic pocrt.lib, printf works fine. Any idea why?
I ran into this before and at that time I just decided to use the dynamic lib because it worked. I don't understand why it doesn't work with the static lib.
Here's the code:
.386
.model flat, stdcall
option casemap:none
include c:\masm32\include\windows.inc
include c:\masm32\include\kernel32.inc
includelib c:\masm32\lib\kernel32.lib
includelib c:\progra~1\pellesc\lib\crt.lib ; Pelle's CRT static library
strcat PROTO C :DWORD,:DWORD
strstr PROTO C :DWORD,:DWORD
strchr PROTO C :DWORD,:DWORD
printf PROTO C :PTR BYTE,:VARARG
CR EQU 13
LF EQU 10
.data
pStr DWORD 0
szDest BYTE 'strcat example : ', 0, 20 dup(0)
szSource BYTE 'Hello my friend', CR, LF, 0
szString2 BYTE 'friend', 0
szFormat BYTE "%u", LF, 0
szCrLf BYTE CR, LF, 0
.code
start:
invoke strcat, ADDR szDest, ADDR szSource
invoke printf, ADDR szDest
invoke strstr, ADDR szDest, ADDR szString2
mov pStr, eax
invoke printf, ADDR szFormat, pStr
invoke strchr, ADDR szDest, 'r'
mov pStr, eax
invoke printf, ADDR szFormat, pStr
invoke ExitProcess, 0
END start
Note: I am using polink for the linker.
Hi Greg,
Probably, the reason is that printf from crt.lib refers to the start-up code of the static library. I faced the same problem. As you said, you can use the DLL version pocrt.dll Another solution is to use msvcrt.dll or crtdll.dll to bind dinamically all those functions.
Here is a tiny C run-time startup module demo using pocrt.dll
[attachment deleted by admin]
It might work with the static library if you add the following calls (not officially documented, and may change in the future - but I see no reason for it at the moment).
C prototypes:
int __bheapinit(void)
void __ioinit(void)
Something like this...
invoke __bheapinit ; will return a non-zero value on success, otherwise zero -- for malloc() etc.
test eax,eax
jz byebye
invoke __ioinit ; will not return anything -- for I/O handles etc.
Pelle
Hi Pelle,
Thanks for the info :U
Pelle,
Thanks for that information, it does work. Since it is subject to change, I won't use it in anything important. It's fun to play around with though. :toothy
Thanks. I see no reason for it to change any time soon, probably never, but I don't want to "officially" support it...
Pelle
Here is an example of using the dynamic version of Pelle's C run-time library (pocrt.dll) in a MASM program. I wrote this program a while back to test the concept. I created the pocrt.inc and pocrt.lib with Hutch's makecimp program. I attached all the files in pocrt.zip.
.586
.MODEL FLAT, stdcall
option casemap:none
include windows.inc
include c:\masm32\include\kernel32.inc
include c:\masm32\include\user32.inc
include c:\masm32\include\masm32.inc
include c:\masm32\pocrt\pocrt.inc
include c:\masm32\macros\macros.asm
includelib c:\masm32\lib\kernel32.lib
includelib c:\masm32\lib\user32.lib
includelib c:\masm32\lib\masm32.lib
includelib c:\masm32\pocrt\pocrt.lib
Sine PROTO degrees:PTR REAL8, sin:PTR REAL8
Cosine PROTO degrees:PTR REAL8, cos:PTR REAL8
Tangent PROTO degrees:PTR REAL8, tan:PTR REAL8
Arcsine PROTO sin :PTR REAL8, degrees:PTR REAL8
Arccosine PROTO cos :PTR REAL8, degrees:PTR REAL8
Arctangent PROTO tan :PTR REAL8, degrees:PTR REAL8
inputR4 PROTO pR4 :PTR REAL4
inputR8 PROTO pR8 :PTR REAL8
inputR10 PROTO pR10 :PTR REAL10
;---------------------------------------
; macros
;---------------------------------------
printf MACRO pszFmt, args:VARARG
IFB <args>
IFB <pszFmt>
invoke pocrt_printf, chr$(13,10)
ELSE
invoke pocrt_printf, pszFmt
ENDIF
ELSE
invoke pocrt_printf, pszFmt, args
ENDIF
ENDM
;---------------------------------------
WaitKey MACRO
printf chr$(13,10,"Press any key to continue...")
call wait_key
printf
ENDM
;---------------------------------------
.DATA
align 8
dblDegrees REAL8 0.0
dblSine REAL8 0.0
dblCosine REAL8 0.0
dblTangent REAL8 0.0
.CODE
start:
printf chr$("Enter angle in degrees: ")
invoke inputR8, ADDR dblDegrees
printf
printf chr$("Angle = %9.6lf degrees",13, 10), dblDegrees
invoke Sine, ADDR dblDegrees, ADDR dblSine
invoke Cosine, ADDR dblDegrees, ADDR dblCosine
invoke Tangent, ADDR dblDegrees, ADDR dblTangent
printf
printf chr$("Sine(%.1lf) = %8.6lf", 13, 10), dblDegrees, dblSine
printf chr$("Cosine(%.1lf) = %8.6lf", 13, 10), dblDegrees, dblCosine
printf chr$("Tangent(%.1lf) = %8.6lf", 13, 10), dblDegrees, dblTangent
printf
invoke Arcsine, ADDR dblSine, ADDR dblDegrees
printf chr$("Arcsine(%8.6lf) = %9.6lf degrees", 13, 10), dblSine, dblDegrees
invoke Arccosine, ADDR dblCosine, ADDR dblDegrees
printf chr$("Arccosine(%8.6lf) = %9.6lf degrees", 13, 10), dblCosine, dblDegrees
invoke Arctangent, ADDR dblTangent, ADDR dblDegrees
printf chr$("Arctangent(%8.6lf) = %9.6lf degrees", 13, 10), dblTangent, dblDegrees
WaitKey
invoke ExitProcess, 0
;======================================================
; procedures
;======================================================
Sine PROC degrees:PTR REAL8, sin:PTR REAL8
LOCAL radians:REAL8
IFNDEF DtoR
.CONST
DtoR REAL10 0.017453292519943295769 ;(Pi / 180.0)
ENDIF
.CODE
mov eax, degrees
finit
fld REAL8 PTR [eax]
fld DtoR
fmul
fstp radians
fwait
invoke pocrt_sin, radians ;result in ST(0)
mov eax, sin
fstp REAL8 PTR [eax]
fwait
ret
Sine ENDP
;======================================================
Cosine PROC degrees:PTR REAL8, cos:PTR REAL8
LOCAL radians:REAL8
IFNDEF DtoR
.CONST
DtoR REAL10 0.017453292519943295769 ;(Pi / 180.0)
ENDIF
.CODE
mov eax, degrees
finit
fld REAL8 PTR [eax]
fld DtoR
fmul
fstp radians
fwait
invoke pocrt_cos, radians ;result in ST(0)
mov eax, cos
fstp REAL8 PTR [eax]
fwait
ret
Cosine ENDP
;======================================================
Tangent PROC degrees:PTR REAL8, tan:PTR REAL8
LOCAL radians:REAL8
IFNDEF DtoR
.CONST
DtoR REAL10 0.017453292519943295769 ;(Pi / 180.0)
ENDIF
.CODE
mov eax, degrees
finit
fld REAL8 PTR [eax]
fld DtoR
fmul
fstp radians
fwait
invoke pocrt_tan, radians ;result in ST(0)
mov eax, tan
fstp REAL8 PTR [eax]
fwait
ret
Tangent ENDP
;======================================================
Arcsine PROC sin:PTR REAL8, degrees:PTR REAL8
IFNDEF RtoD
.CONST
RtoD REAL10 57.295779513082320876798 ;(180.0 / Pi)
ENDIF
.CODE
mov eax, sin
invoke pocrt_asin, REAL8 PTR [eax] ;result in ST(0)
mov eax, degrees
fld RtoD
fmul
fstp REAL8 PTR [eax]
fwait
ret
Arcsine ENDP
;======================================================
Arccosine PROC cos:PTR REAL8, degrees:PTR REAL8
IFNDEF RtoD
.CONST
RtoD REAL10 57.295779513082320876798 ;(180.0 / Pi)
ENDIF
.CODE
mov eax, cos
invoke pocrt_acos, REAL8 PTR [eax] ;result in ST(0)
mov eax, degrees
fld RtoD
fmul
fstp REAL8 PTR [eax]
fwait
ret
Arccosine ENDP
;======================================================
Arctangent PROC tan:PTR REAL8, degrees:PTR REAL8
IFNDEF RtoD
.CONST
RtoD REAL10 57.295779513082320876798 ;(180.0 / Pi)
ENDIF
.CODE
mov eax, tan
invoke pocrt_atan, REAL8 PTR [eax] ;result in ST(0)
mov eax, degrees
fld RtoD
fmul
fstp REAL8 PTR [eax]
fwait
ret
Arctangent ENDP
;======================================================
inputR4 PROC pR4:PTR REAL4
invoke pocrt_scanf, chr$("%f"), pR4
ret
inputR4 ENDP
;======================================================
inputR8 PROC pR8:PTR REAL8
invoke pocrt_scanf, chr$("%lf"), pR8
ret
inputR8 ENDP
;======================================================
inputR10 PROC pR10:PTR REAL10
LOCAL r8:REAL8
invoke pocrt_scanf, chr$("%lf"), ADDR r8
mov eax, pR10
finit
fld r8
fstp REAL10 PTR [eax]
ret
inputR10 ENDP
;======================================================
end start
[attachment deleted by admin]
Using lib2inc, I created all the function prototypes from crt.lib :
lib2inc \pellesc\lib\crt.lib
After replacing all the StdOut functions with printf, here is the new listing :
.386
.model flat,stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\user32.inc
include \masm32\include\masm32.inc
include crt.inc
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\user32.lib
includelib \masm32\lib\masm32.lib
includelib \pellesc\lib\crt.lib ; Pelle's CRT static library
.data
dest db 'strcat example : ',0
db 20 dup(0)
source db 'Hello my friend',13,10,0
string2 db 'friend',0
template1 db '%s',13,10,0
template2 db '%X',13,10,0
.data?
buffer db 20 dup(?)
.code
start:
invoke __bheapinit
test eax,eax
jz finish
invoke __ioinit
invoke strcat,ADDR dest,ADDR source
invoke printf,ADDR template1,ADDR dest
invoke strstr,ADDR dest,ADDR string2
invoke printf,ADDR template2,eax
invoke strchr,ADDR dest,114 ; look for 'r'
invoke printf,ADDR template2,eax
finish:
invoke ExitProcess,0
END start
[attachment deleted by admin]
Same example assembled with POASM
[attachment deleted by admin]