G'day All,
I am trying to use the Expat XML parser from within my ASM Win32
application.
I have built a library "lib" file as per Iczelion's "How toCreate your
own MASM Import Libraries" instructions. I can load the library and call
some expat functions without error:
However when I call "XML_Parse", the program crashes:
So I tried to load the "libexpat.dll" dynamically, with much the
same result:
Does anyone know what I have done wrong, and why the XMLParse function
crashes my application. I have also tried the LibXML XML C parser with
no luck :(
Links:
Expat XML Parser http://www.libexpat.org
LibXML XML C parser http://www.xmlsoft.org/
Also:
I am fairly new to ASM amd Win32 programming
Thanks
Dorf
I am trying to use the Expat XML parser from within my ASM Win32
application.
I have built a library "lib" file as per Iczelion's "How toCreate your
own MASM Import Libraries" instructions. I can load the library and call
some expat functions without error:
invoke XML_ParserCreate, 0
...
invoke XML_SetElementHandler, hXMLParser, funStart, funEnd
...
However when I call "XML_Parse", the program crashes:
invoke XML_Parse, hXMLParser, buff, 21, 0 ; BANG
So I tried to load the "libexpat.dll" dynamically, with much the
same result:
.data
...
; Dynamically load the DLL
; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
MyDLLName db "libexpat.dll",0
XMLParse db "XML_Parse",0
XMLParserCreate db "XML_ParserCreate",0
XMLSetElementHandler db "XML_SetElementHandler",0
...
hMyDLL dd ?
addrParse dd ?
addrParserCreate dd ?
addrSetElementHandler dd ?
...
; Expat XML processing callback functions
fStart db 'funStart',0
fEnd db 'funEnd',0
buff db '<action> id </action>',0
.code
start:
...
; Dynamically load the DLL
; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
invoke LoadLibrary, OFFSET MyDLLName
mov [hMyDLL], eax
; XML_ParserCreate
invoke GetProcAddress, [hMyDLL], offset XMLParserCreate
.if(eax == NULL)
invoke Beep, 1000, 100
.endif
mov [addrParserCreate], eax
; p = XML_ParserCreate(NULL);
push NULL ; dword1
call [addrParserCreate]
mov hXMLParser, eax
; XML_SetElementHandler
invoke GetProcAddress, [hMyDLL], offset XMLSetElementHandler
.if(eax == NULL)
invoke Beep, 1000, 100
.endif
mov [addrSetElementHandler], eax
; XML_SetElementHandler(p, start, end);
push offset fEnd ; dword3
push offset fStart ; dword2
push [hXMLParser] ; dword1
call [addrSetElementHandler]
; XML_Parse [CRASH]
invoke GetProcAddress, [hMyDLL], offset XMLParse
.if(eax == NULL)
invoke Beep, 1000, 100
.endif
mov [addrParse], eax
; XML_Parse(XML_Parser p, const char *s, int len, int isFinal)
push 0 ; dword4
push 21 ; dword3
push offset buff ; dword2
push [hXMLParser] ; dword1
call [addrParse] ; BANG
Does anyone know what I have done wrong, and why the XMLParse function
crashes my application. I have also tried the LibXML XML C parser with
no luck :(
Links:
Expat XML Parser http://www.libexpat.org
LibXML XML C parser http://www.xmlsoft.org/
Also:
I am fairly new to ASM amd Win32 programming
Thanks
Dorf
Try:
invoke XML_Parse, hXMLParser, addr buff, sizeof buff, 0
- if you don't use addr/sizeof, masm will pass the first element (byte) of buff, expat will treat that as a pointer, and *boom*. Also, it's bad to use hardcoded magic values (ie: 21), especially when masm has 'sizeof' :-)
invoke XML_Parse, hXMLParser, addr buff, sizeof buff, 0
- if you don't use addr/sizeof, masm will pass the first element (byte) of buff, expat will treat that as a pointer, and *boom*. Also, it's bad to use hardcoded magic values (ie: 21), especially when masm has 'sizeof' :-)
G'day f0dder,
Thanks for the quick response
That helped. The app still crashes however.
The parser now calls my start function and pops a message box
with the opening tag "<action>". :)
But it crashes before calling the end function :(
Thanks for your help
Dorf
Thanks for the quick response
That helped. The app still crashes however.
The parser now calls my start function and pops a message box
with the opening tag "<action>". :)
But it crashes before calling the end function :(
; start(void *data, const char *el, const char **attr)
funStart proc data:DWORD, el:DWORD, attr:DWORD
;invoke Beep, 1000, 100 ; Bell
invoke MessageBox, NULL, el, NULL, MB_OK
ret
funStart endp
; end(void *data, const char *el) {
funEnd proc data:DWORD, el:DWORD
invoke Beep, 100, 100 ; Bell
ret
funEnd endp
Thanks for your help
Dorf
If you're doing a typical masm file, you have ".model flat,stdcall" somewhere - this sets the default calling convention for all further PROCs to stdcall. I assume EXPAT is written in C, and that it doesn't have "__stdcall" or similar qualifiers for it's callbacks.
So, try adding a 'C' to your callback procs - like
So, try adding a 'C' to your callback procs - like
funStart proc C data:DWORD, el:DWORD, attr:DWORD
;invoke Beep, 1000, 100 ; Bell
invoke MessageBox, NULL, el, NULL, MB_OK
ret
funStart endp
; end(void *data, const char *el) {
funEnd proc C data:DWORD, el:DWORD
invoke Beep, 100, 100 ; Bell
ret
funEnd endp
G'day f0dder,
Yep ... that seems to have done the trick :)
Just for the record, I had to now define the start/end function
prototypes as:
Now I can start testing the expat parser :-D
Thank you very much
I think Win32Asm is very cool
Thanks again
Dorf
Yep ... that seems to have done the trick :)
Just for the record, I had to now define the start/end function
prototypes as:
funStart proto C :DWORD, :DWORD, :DWORD
funEnd proto C :DWORD, :DWORD
Now I can start testing the expat parser :-D
Thank you very much
I think Win32Asm is very cool
Thanks again
Dorf
G'day All,
Next problem ...
Does anyone know how to access a pointer-to-a-pointer (const char **attr") in MASM.
The Expat XML parser - in C
To the Expat XML parser - in RadASM/MASM
Thanks
Dorf
Next problem ...
Does anyone know how to access a pointer-to-a-pointer (const char **attr") in MASM.
The Expat XML parser - in C
/* Read an XML document from standard input and print an element */
/* outline on standard output. */
void start(void *data, const char *el, const char **attr) {
int i;
...
printf("%s", el);
for (i = 0; attr[i]; i += 2) {
printf(" %s='%s'", attr[i], attr[i + 1]);
}
...
}
To the Expat XML parser - in RadASM/MASM
funStart proc C data:DWORD, el:DWORD, attr:DWORD
invoke SaveIndent
invoke lstrcat, addr strBuff, el
invoke lstrcat, addr strBuff, addr szNewLine
inc level
invoke SaveIndent
; Handle the element attributes
; *** HOW TO DEREFERENCE A POINTER TO A POINTER ("const char **attr")***
invoke lstrcat, addr strBuff, attr
invoke lstrcat, addr strBuff, addr szNewLine
;inc level
ret
funStart endp
Thanks
Dorf
Looking at the C code attr seems to be a pointer to an array of pointers to strings so you could try for example this code which should mimic the "for" loop given. I haven't tested this though :)
Basically if a memory variable is a pointer to a point then the following will get you to the "thing"
For strings though you wont need the last mov cause you'll be dealing with their pointers anyway.
;Loop through attrs
mov ecx,attr ; ecx point to attr array
cmp [ecx],0 ; test ecx for NULL
jz endLoop
startLoop:
mov eax,[ecx] ; eax points to string
; ... do something here ...
; move ecx onto next string and recheck for NULL
add ecx,4
cmp [ecx],0
jnz startLoop
endLooop:
Basically if a memory variable is a pointer to a point then the following will get you to the "thing"
mov eax,attr ; eax is pointer to pointer
mov eax,[eax] ; eax is pointer
mov eax,[eax] ; eax is the "thing"
For strings though you wont need the last mov cause you'll be dealing with their pointers anyway.
G'day E?in,
That helped a lot :)
I'm having some trouble with the loop ... detecting null
attributes, but it basically works.
I'll post my little demo of parsing an XML file into
a Treeview control in a day or so.
Thanks
Dorf
That helped a lot :)
I'm having some trouble with the loop ... detecting null
attributes, but it basically works.
I'll post my little demo of parsing an XML file into
a Treeview control in a day or so.
Thanks
Dorf
Just thinking it might be important to also check ecx for NULL ie
;Loop through attrs
mov ecx,attr ; ecx point to attr array
cmp ecx,0 ; <-- check if attr is null
jz endLoop
cmp [ecx],0 ; test ecx for NULL
jz endLoop
startLoop:
You can make use of jecxz if the displacement is less than 127 bytes.
G'day All,
Here is my little demo of using the Expat XML parser in an
RadASM/MASM project.
This application parses an XML file into a Treeview control.
See the included "Readme.txt" for a more detailed description.
I've also included a project to create the import library
for the Expat XML parser C library.
Issues:
After reading the XML file into a string buffer, I cannot get
the actual length of the XML contents (with sizeof buff).
If I pass this buffer to Expat, it complains about malformed
document, or something.
As a workaround I get the size of the XML file:
invoke GetFileSizeFile, fileName
and pass this return value (eax) to Expat.
invoke XML_Parse, hXMLParser, addr buff, eax, 0
and Expat seems happy with this.
Someone that knows what they're doing may be able to figure this
out ... perhaps!
Use this at your own risk - I am fairly new to ASM/Win32 :)
Thanks for the help
ASM/Win32 rocks.
dorf
Here is my little demo of using the Expat XML parser in an
RadASM/MASM project.
This application parses an XML file into a Treeview control.
See the included "Readme.txt" for a more detailed description.
I've also included a project to create the import library
for the Expat XML parser C library.
Issues:
After reading the XML file into a string buffer, I cannot get
the actual length of the XML contents (with sizeof buff).
If I pass this buffer to Expat, it complains about malformed
document, or something.
As a workaround I get the size of the XML file:
invoke GetFileSizeFile, fileName
and pass this return value (eax) to Expat.
invoke XML_Parse, hXMLParser, addr buff, eax, 0
and Expat seems happy with this.
Someone that knows what they're doing may be able to figure this
out ... perhaps!
Use this at your own risk - I am fairly new to ASM/Win32 :)
Thanks for the help
ASM/Win32 rocks.
dorf
After reading the XML file into a string buffer, I cannot get
the actual length of the XML contents (with sizeof buff).
Sizeof works at assemble-time - it returns the size the assembler has reserved for the data object. The assembler has no notion of "the size of the contents", you'll need some runtime code for that. In case of an ASCII text file, you could use a strlen routine, or - as you're doing right now - simply the filesize.
dorf:
Hello, I could not find the demo you mentioned. Will you please check the link?
Thank you.
Hello, I could not find the demo you mentioned. Will you please check the link?
Thank you.
The link got zapped when the board got hacked some time back, I think.
The Expat XML parser demo is here, also a couple of other Masm32 examples:
http://www.phpmvc.net/asm/
Download - 83,888 Bytes
http://www.phpmvc.net/asm/expat-xml-parser-test.zip
Regards
dorf
The Expat XML parser demo is here, also a couple of other Masm32 examples:
http://www.phpmvc.net/asm/
Download - 83,888 Bytes
http://www.phpmvc.net/asm/expat-xml-parser-test.zip
Regards
dorf