NASM - The Netwide Assembler
NASM Forum => Using NASM => Topic started by: Klod on October 19, 2010, 04:28:33 AM
-
This may be pushing the envelope to far and is purely experimental. Even though I have not seen any examples in this forum or on the net, I tried to create a macro from within a macro. I believe the following example should work.
%warning __NASM_VER__ 2.10rc1-20101008
%macro definem 2+
;%warning %? %1 %2 %0 'parameters'
mac %1,%2
%endmacro
%macro mac 2-*
%push mac
%warning 'Parameters' %{1} %2
%push mac
%define %$name %{1}
%warning 'Parameters' %{1} %2 %$name
%macro %{1} 1-*
%warning %? %1 %2 %0 %[%{$name}] %$name %{$name}
push %2
EXTERN %{1}
;call %1
%endmacro
%pop
%endm
[Section .Text]
Start:
definem ExitProcess,0
definem strcpy,ptr
; push 0
; EXTERN ExitProcess
strcpy,Start
ExitProcess ,0
;Windows XP service pack 2
;\nasm\bin\NASM -f win32
;\nasm\bin\golink @\nasm\bin\GFL.txt /console /entry Start
NAsm reports:
\nasm\bin\NASM -f win32 "C:\NasmEd\Project\WorkInProgress\Stringparsing\invkDefine.asm"
C:\NasmEd\Project\WorkInProgress\Stringparsing\invkDefine.asm:1: warning: "2.10rc1-20101008" 2.10rc1-20101008
C:\NasmEd\Project\WorkInProgress\Stringparsing\invkDefine.asm:25: warning: (mac:2) 'Parameters' ExitProcess 0
C:\NasmEd\Project\WorkInProgress\Stringparsing\invkDefine.asm:25: warning: (mac:5) 'Parameters' ExitProcess 0 ExitProcess
C:\NasmEd\Project\WorkInProgress\Stringparsing\invkDefine.asm:26: warning: (mac:2) 'Parameters' strcpy ptr
C:\NasmEd\Project\WorkInProgress\Stringparsing\invkDefine.asm:26: warning: (mac:5) 'Parameters' strcpy ptr strcpy
C:\NasmEd\Project\WorkInProgress\Stringparsing\invkDefine.asm:29: warning: (strcpy:1) mac Start 2 %$name %$name %$name
C:\NasmEd\Project\WorkInProgress\Stringparsing\invkDefine.asm:30: warning: (ExitProcess:1) mac 0 2 %$name %$name %$name
This all works as I expected, both macros strcpy and Exitprocess are created. However, when I call the macros, the macro name "disappears". %? should show macroname as Exitprocess and strcpy and not as mac (macro name of previous macro). %2 still gives the correct parameter but %1 "disappears". I thought first that %1 might have been shifted into macro name but not so. Also by creating a context and then attempting to use the local %$name suffers the same fate.
As I said earlier, purely experimental. Maybe I'm reading more in the docs than there is ???
Regards Klod
-
This must be an unsupported use? ???
-
%warning __NASM_VER__ 2.10rc1-20101008
%macro definem 2+
;%warning %? %1 %2 %0 'parameters'
mac %1,%2
%endmacro
%macro mac 2-*
%push mac
%warning 'Parameters' %{1} %2
%push mac
%define %$name %{1}
%warning 'Parameters' %{1} %2 %$name
%macro %{1} 1-*
%warning %? %1 %2 %0 %[%{$name}] %$name %{$name}
push %2
EXTERN %{1}
;call %1
%endmacro
%pop
%endm
[Section .Text]
Start:
definem ExitProcess,0
definem strcpy,ptr
; push 0
; EXTERN ExitProcess
strcpy,Start
ExitProcess ,0
;Windows XP service pack 2
;\nasm\bin\NASM -f win32
;\nasm\bin\golink @\nasm\bin\GFL.txt /console /entry Start
NAsm reports:
\nasm\bin\NASM -f win32 "C:\NasmEd\Project\WorkInProgress\Stringparsing\invkDefine.asm"
C:\NasmEd\Project\WorkInProgress\Stringparsing\invkDefine.asm:1: warning: "2.10rc1-20101008" 2.10rc1-20101008
C:\NasmEd\Project\WorkInProgress\Stringparsing\invkDefine.asm:25: warning: (mac:2) 'Parameters' ExitProcess 0
C:\NasmEd\Project\WorkInProgress\Stringparsing\invkDefine.asm:25: warning: (mac:5) 'Parameters' ExitProcess 0 ExitProcess
C:\NasmEd\Project\WorkInProgress\Stringparsing\invkDefine.asm:26: warning: (mac:2) 'Parameters' strcpy ptr
C:\NasmEd\Project\WorkInProgress\Stringparsing\invkDefine.asm:26: warning: (mac:5) 'Parameters' strcpy ptr strcpy
C:\NasmEd\Project\WorkInProgress\Stringparsing\invkDefine.asm:29: warning: (strcpy:1) mac Start 2 %$name %$name %$name
C:\NasmEd\Project\WorkInProgress\Stringparsing\invkDefine.asm:30: warning: (ExitProcess:1) mac 0 2 %$name %$name %$name
Before I start on the problem at hand, you might need to double check your definem macro, as you seem to have unbalanced the number of %push/%pop directives (you have two %push mac and only one %pop). I'm not sure if that was intentional but if you end up using your code a lot, it might really slow your code down.
This all works as I expected, both macros strcpy and Exitprocess are created. However, when I call the macros, the macro name "disappears". %? should show macroname as Exitprocess and strcpy and not as mac (macro name of previous macro).
I'm pretty sure this behaviour is supposed to be expected. %? is getting expanded when your new macro is being created so I don't really know of any way around this. I'm honestly surprised your code worked. :)
%2 still gives the correct parameter but %1 "disappears". I thought first that %1 might have been shifted into macro name but not so. Also by creating a context and then attempting to use the local %$name suffers the same fate.
Arguments are fine, it's a usage problem. When you use your ExitProcess macro, you are passing a NULL parameter. See below:
Start:
definem ExitProcess,0
definem strcpy,ptr
; push 0
; EXTERN ExitProcess
; strcpy,Start << This is strcpy( "", Start )
strcpy Start ;<< This is strcpy( Start )
; ExitProcess ,0 << This is ExitProcess( "", 0 )
ExitProcess 0 ;<< This is ExitProcess( 0 )
As you can see, the coma preceding your arguments creates a blank argument in %1. And as for loosing %$name, it's expected as well, when you create a new context, %$name becomes %$$name and a fresh context is provided for you (this allows you to redefine %$name locally to your macro while retaining the old one).
-
Hi Bryant,
......check your definem macro, as you seem to have unbalanced the number of %push/%pop directives (you have two %push mac and only one %pop). I'm not sure if that was intentional but if you end up using your code a lot, it might really slow your code down.
You are correct. This was accidental, as I have been trying different things. In the heat of the moment I got sloppy.
I'm pretty sure this behaviour is supposed to be expected. %? is getting expanded when your new macro is being created so I don't really know of any way around this. I'm honestly surprised your code worked.
I have attached a working program with source. The "context local " approach does not work and of course none of the "macro locals" work. I have found a workaround but its not satisfactory....
strcpy Start ;<< This is strcpy( Start )
; ExitProcess ,0 << This is ExitProcess( "", 0 )
You are right here again but I think the problem lies here...
%macro %[%1] 0-*
%warning %?? %0 ,%1,%2 %3 %0-1 ,%[%1]
The macro with name %[%1] gets created. Here however the preprocessor gets confused. Instead of using %[%1] as the new macro name, it reuses the previous macro name (mac), drops %[%1] and shifts the supplied parameters to the right and thus creates an empty parameter. I assume macro name mac is used as current macro name until it sees a matching %endm.
As you can see, the coma preceding your arguments creates a blank argument in %1.
printf missing1starg,Newline
This compiles and runs fine
printf string3 <--- correct invocation
This produces ERROR: Line 34: error: invalid combination of opcode and operands
The workaround works by defining %[%1] before the macro is created and then ignoring %1 and using %2 as first argument. There is a serious drawback in my implementation because %define name %1 creates persistence.
definem printf,ptr
definem scanf,ptr
printf, string
-
I was fooling around with formatting and somehow my incomplete response got posted ;D
...continued from previous post.
this gives Error:
31: error: invalid combination of opcode and operands
Error symbol `call' redefined for multiple invocations of the same macro
This is not what I was shooting for.
I do not know how Nasm implements macros but think if its similar in approach to context mechanism, it could be relatively easy to implement a "previous macro name" "context" mechanism which would also allow macros to be recursive??
Thanks for your input,
Klod
-
Forgot to attach my proggie ;)
Klod
-
You did it again in the posted version. Check out this source:
;Windows XP service pack 2
;\nasm\bin\NASM -f win32
;\nasm\bin\golink @\nasm\bin\GFL.txt /console /entry Start
%warning __NASM_VER__ 2.10rc1-20101028
%macro definem 2+
mac %1,%2
%endmacro
%macro mac 2-*
%define name %1
%warning %?? %0 'Parameters' %{1} %2 %3 name
%macro %[%1] 0-*
%warning %?? %0 ,%1,%2 %3 %0-1 ,%[%{1}]
push %1
EXTERN name
call name
%endmacro
%endmacro
[Section .data]
string db 'hello',13,10,0
string2 db 'Hello again',0
string3 db 'and again Hello',0
Newline db 13,10,0
key db '%x'
[Section .text]
Start:
definem printf,ptr
printf string
printf string2
printf Newline
printf string3
printf Newline ;correct calling
definem scanf,ptr
scanf key
definem ExitProcess, 0
ExitProcess 0
I assembled it and got:
nestedMacrocall.asm:4: warning: "2.09.03" 2.10rc1-20101028
nestedMacrocall.asm:29: warning: (mac:2) mac 2 'Parameters' printf ptr printf
nestedMacrocall.asm:31: warning: (printf:1) mac 1 ,string, 1-1 ,string
nestedMacrocall.asm:32: warning: (printf:1) mac 1 ,string2, 1-1 ,string2
nestedMacrocall.asm:33: warning: (printf:1) mac 1 ,Newline, 1-1 ,Newline
nestedMacrocall.asm:34: warning: (printf:1) mac 1 ,string3, 1-1 ,string3
nestedMacrocall.asm:35: warning: (printf:1) mac 1 ,Newline, 1-1 ,Newline
nestedMacrocall.asm:37: warning: (mac:2) mac 2 'Parameters' scanf ptr scanf
nestedMacrocall.asm:38: warning: (scanf:1) mac 1 ,key, 1-1 ,key
nestedMacrocall.asm:39: warning: (mac:2) mac 2 'Parameters' ExitProcess 0 ExitProcess
nestedMacrocall.asm:41: warning: (ExitProcess:1) mac 1 ,0, 1-1 ,0
Since I'm on Linux, I can't actually link and test the code, but I'm assuming this is the output you were wanting. Re-read my post, what you are doing wrong is passing the empty param which is generating a call instruction without an argument (which is the reason for the "invalid combination of opcode and operand" error you're getting). Review this code, I'm sure you'll see what I'm saying. :)
-
Hi Bryant, I have come to see the light :)
I originally used %macro %{1} %0 to work out the possibility of making it work. This is incorrect in as far as the macroname is counted as a parameter. %0 would be 2 instead of one. %{0}-1 does not work, neither does %$count for parameter count. I was unaware of an extra parameter being added. once I could compile , the proggie would crash. I then found that I needed to push %2 to make it work. and this explains the printf,string syntax. And I thought Confucius was Chineese ;D ;D
Here is the correct working version:
%macro mac 2
%define name %1
%warning %?? %0 'Parameters' %{1} %2
%macro %{1} 1
%warning %?? %0 'args' %1
push %1
EXTERN name
call name
%endmacro
%endm
[Section .data]
string db 'first string',0
key db '%c'
[Section .text]
Start:
mac printf, ptr
printf string
mac scanf,ptr
scanf key
mac ExitProcess,0
ExitProcess 0
In order to test for %ifmacro MyMacro 3
%macro MyMacro 3 would have to be defined. Nasm will neither accept %{0}-1 nor %$count count
Do you have any ideas if this could be done??
Regards Klod