NASM - The Netwide Assembler
NASM Forum => Using NASM => Topic started by: nobody on December 23, 2008, 04:42:43 AM
-
Hi all
Here is my scall macro, I have been working on lately. It is intended to be used with Golink, no Imports.
It's the macro from Nagoa package that I have slightly modified.
Two problems: -no matter how I rotate, I cannot get the right position for the argument passed with ADDR
I will get ERROR t1.asm:53: error: comma or end of line expected
or I will get the address of the Argument to the left. Or it will create a string in data “ADDR” and return a pointer to it
-%elifid and %elifnum branches never execute. I think If I scall Function,1 it should go trough the
%elifnum branch
%define ADDR "ADDR_",
%macro scall 1-*.nolist ;Windows StdCall: push last value first, no cleanup
%ifndef %1_defined ;define external functions
extern %1
%endif
%define _proc %1
%rep %0-1
%rotate -1
%ifidni %1,"ADDR_"
;%error "ADDR is used"
;%rotate -1
lea eax, [%1]
push eax
%rotate 1
%elifstr %1
;;;;;%ifstr %-1
;%error "We have a string argument"
mac_pushstring %1
%elifid
push dword %1
%error "We have a label"
%elifnum
push dword %1
%error "We have a number"
%else
;%error "unspecified Argument"
push dword %1
%endif
%endrep
call _proc
%endmacro
PROC proc1,string
LOCAL val,4
LOCAL buf,4
mov D[@val],1
mov D[@buf],2
scall HexPrint,ADDR [@string] ;ebp+8
scall HexPrint, ADDR [@val] ;ebp-4
scall HexPrint,ADDR [@buf] ;ebp-8
ENDP
Start:
lcall proc1,textout
scall ExitProcess, 0
Any suggestions would be most appriciated,
Klod
-
Hi Klod,
Jeez, that's a tricky one!!! At first, I didn't see how this was going to work at all. "ADDR foo" is *one* parameter, we're going to have to "parse" it, right? Wrong! My tired old eyes were missing the comma in the %define. We're making *two* parameters out of it!
So what Pedro's doing is to rotate an extra time, check the "previous" (or "next") parameter for "ADDR_". If so, rotate to the "real" parameter, lea and push it, and "rotate back" to skip the "ADDR_" (fake) parameter. If it *isn't* ADDR_, undo the "extra" rotate and proceed...
Pedro introduces an "assemble-time variable", "i", which mirrors the parameter count, "%0", initially. This gets decremented an "extra" time if ADDR_, and causes an "early exit" from the %rep loop. There may be a way to get around this, but it may be necessary - my best attempt so far does the lea/push correctly(?), but since we've handled two parameters per loop (if ADDR), this pushes one too many (push Hexprint, e.g.) before "call Hexprint". Re-introducing that (I called it "repcount") seems to fix it
One thing I noticed that's going to cause you trouble is the brackets "[]". You've got "[%1]" in the macro, and call it as "ADDR_ [@string]". This results in "lea [[@string]]" - "expression syntax error"! Programmer's choice which place you do it, but not both.
I think your "%elifnum" will work if you make it "$elifnum %1". Arguably, Nasm ought to complain about just "%elifnum" without a parameter... but it doesn't.
This is what I've got... so far...
%define ADDR "ADDR_",
%macro scall 1-*.nolist ;Windows StdCall: push last value first, no cleanup
%ifndef %1_defined ;define external functions
extern %1
%endif
%define _proc %1
%assign repcount %0
%rep %0 - 1
%rotate -1
%rotate -1 ; "extra" rotate
%ifidni %1,"ADDR_"
%error "ADDR is used"
%rotate 1
lea eax, [%1]
push eax
%rotate -1
%assign repcount repcount - 1
%else
%rotate 1 ; undo the "extra"
%endif
%ifstr %1
;;;;;%ifstr %-1
%error "We have a string argument"
mac_pushstring %1
%elifid %1
push dword %1
%error "We have a label"
%elifnum %1
push dword %1
%error "We have a number"
%else
;%error "unspecified Argument"
push dword %1
%endif
%assign repcount repcount - 1
%if repcount >= 1
%exitrep
%endif
%endrep
call _proc
%endmacro
This "seems to work" - not well-tested, 'cause I had to comment out a lot of stuff, lacking the full macro-set (and Windows), to get it to assemble at all. See if it helps... I think you're closing in on it!
Best,
Frank
-
Thanks Frank for your help.
I had to play around a bit with the code. I thought I didn't need the repcount mechanism, since I shifted right then left. I did not consider, that the argument to the right of ADDR would pushed as a regular parameter in the previous loop. I decided to take it one step further and make an invoke macro out of it. Local and global procs can be invoked with the same macro
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; Invk Macro Based on sources like Nguga,PedroC,Bryant Keller nuMitor and others, adapted to GoLink
; Written by : Klod
; Assembler : Netwide Assembler v2.00
; Linker :GoLink
; Date : 26-Dec-2008
; To Do :Fix size bug will push dword byte/word if size other than dword specified
:[global] will not be pushed at all, has to be dword[global] or dword[@local]
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
%define ADDR "ADDR_",
%MACRO invk 1-*
%define _proc %1
%ifndef PROC_defined_%1
;%error extern %1
extern %1
%endif
%assign repcount %0-1
%rep %0-1
%rotate -1
%ifidni %1,"ADDR_"
;%error "ADDR is used"
%rotate 1 ;extra rotate
%assign repcount repcount -1
lea eax, %1
push eax
%rotate -1 ;undo extra rotate
%elifstr %1
;%error "We have a string argument"
mac_pushstring %1
;%assign repcount repcount -1
%elifid %1
;%error "We have a label"
push dword %1
%elifnum %1
;%error "We have a number"
push dword %1
%assign repcount repcount -1
%else
;%error "an unspecified argument has been supplied"
%endif
%if repcount <= 1
%exitrep
%endif
%endrep
call _proc
%ENDMACRO
You were right, the brackets are a problem. I have to use push dword %1 because of it. If I use ADDR @param Nasm will not compile I will get error: invalid operand type.
You mentioned string parsing in your reply. I have not tried it yet, but think it would be well worth to explore. My macro could be greatly simplified if ADDR_[@parm]could be treated as one argument. My initial idea was to use something like:
%substr %%arg %1 5,-1 ;to %define %%arg '[@parm]'???
lea eax,%%arg
push dword eax
Any thoughts on that notion?
Working with the macros I have encountered problems with definitions and scope. As an example:
%define addr(x) (lea eax,( x)\ push eax)
invk MsgBox,addr(dword[@lpName]),'test'
invk MsgBox,addr([@lpName]),'test'
This would be my prefered method, but cannot make it work at this time.
As always, your help and suggestions are very much appreciated.
Klod
-
Hi Klod,
Haven't taken time to test this, but the logic looks wrong to me...
%rep %0-1
%rotate -1
%ifidni %1,"ADDR_"
;%error "ADDR is used"
%rotate 1 ;extra rotate
%assign repcount repcount -1
lea eax, %1
push eax
%rotate -1 ;undo extra rotate
%elifstr %1
I think we need to do an "extra rotate -1" *before* checking for "ADDR". Then, if we've got "ADDR", "unrotate", that is, rotate 1, lea/push the "real" parameter, then undo the "extra" rotate -1 before doing "non-ADDR parameters". That's why I put it in a separate if/else/endif in the code I posted - couldn't figure out how to do it as a single if/elif/elif... without putting the "unrotate" in *each* clause.
If this is working properly, "never mind...". :)
I'll try to get back to this. Both your "%define addr(x)" and "%substr" ideas sound interesting...
Best,
Frank