flat assembler
Message board for the users of flat assembler.

Index > Macroinstructions > Determining number of arguments

Author
Thread Post new topic Reply to topic
hafai



Joined: 12 Jun 2011
Posts: 8
hafai 26 Aug 2011, 14:05
If I declare the following:
Code:
MACRO FUNC [args] {;Do stuff}    
Is there a way to know if there are 0 args, 1 args, or more? Some sort of IF statement where if there are 0 then it does one thing, if there is only 1 then it does something else, and if there are more than one then it takes a third course of action?

I know I can do the following to tell the difference between 1 and 0:
Code:
{IF args EQ
     ;0 arg action
ELSE
     ;1 arg action
END IF}    
But that can't tell the difference between only 1 arg and 2 or more.
Post 26 Aug 2011, 14:05
View user's profile Send private message Reply with quote
vid
Verbosity in development


Joined: 05 Sep 2003
Posts: 7105
Location: Slovakia
vid 26 Aug 2011, 14:31
One rather generic way is to count arguments at assembly time by using forward at preprocess time:
Code:
macro func [args] {
common
  argno = 0
  if ~ args eq
forward
    argno = argno + 1
common
  end if
  ;here test "argno"
}    


after preprocessing this for "func 1, eax, 3" this becomes:
Code:
  argno = 0
  if ~ 1, eax, 3 eq    ;true
    argno = argno + 1
    argno = argno + 1
    argno = argno + 1
  end if
  ;here test argno
    


Depending on what exactly you need this for, there might be a better solution.
Post 26 Aug 2011, 14:31
View user's profile Send private message Visit poster's website AIM Address MSN Messenger ICQ Number Reply with quote
hafai



Joined: 12 Jun 2011
Posts: 8
hafai 26 Aug 2011, 15:42
Thank you. The solution actually works well. I tweaked the idea to count using registers so I can push the number of args onto the stack.

Now I'm having a different issue. FASM is calling my invocation of the macro an illegal instruction. All my other macros are working fine but for some reason when I try to invoke this on it fails. It is invoked as "CALL_PROCEDURE proc_name, [args]"

My macro pushes args to the stack and then pushes the number of values pushed onto the stack. It then calls proc_name. I've tried taking out the stack code. I've tried taking out the call instruction. I've tried with args, without args, both fail. I've even taken out all the macro's code so it is empty. I've also tried renaming the macro to make sure I wasn't treading on something that was secretly a hidden reserved word. I also know that my use of two macro files isn't causing the issue. Still illegal instruction.

I'm at a loss. All my code does at the moment is invoke this macro which then calls a procedure.
Post 26 Aug 2011, 15:42
View user's profile Send private message Reply with quote
vid
Verbosity in development


Joined: 05 Sep 2003
Posts: 7105
Location: Slovakia
vid 26 Aug 2011, 16:06
You should post your code for us to help. It's rather hard from your description to help you.
Post 26 Aug 2011, 16:06
View user's profile Send private message Visit poster's website AIM Address MSN Messenger ICQ Number Reply with quote
hafai



Joined: 12 Jun 2011
Posts: 8
hafai 26 Aug 2011, 16:19
Okay. Here is the invoke code.
Code:
start:
     CALL_PROCEDURE Clear_Screen
halt:
    JMP halt    
The following is the CALL_PROCEDURE macro.
Code:
;MACRO: CALL_PROCEDURE proc_name, [args]
;DESCRPITION: Used by calling code to call a procedure with the correct calling convention
MACRO CALL_PROCEDURE proc_name, [args]
{     PUSH RAX ;We use this for a moment and need to preserve it
  PUSH R15 ;We store RSP from before the parameters were pushed onto the stack in R15. As we will need the current contents again we need to save it
  MOV R15, RSP ;Now store the current RSP in R15 so we can unwind the stack after returning from this call
    IF ~ args EQ
REVERSE PUSH args ;Pushes the args onto the stack in reverse order
  END IF
COMMON MOV RAX, RSP ;Retrieve the current RSP address
     SUB RAX, R15 ;Determine how many bytes the stack has grown by
       ;DIV 8 ;Divide by 8 to determine how many arguments were pushed (In 64-bit all pushes (32-bit isn't available (16-bit pushes are but we don't use them here so we can assume (know) that all pushes were 64-bit)))
        PUSH RAX ;Push the number of arguments onto the stack
       CALL proc_name ;Call the procedure
  MOV RSP, R15 ;Unwind the stack (Remember, the called function should have preserved R15
 POP R15} ;Now we get the Caller's R15 back so it can preserve it for it's eventual return. If R15 is 0 then there is nothing to return to.    
The "Clear_Screen" function which gets invoked by the macro is the following.
Code:
START_PROCEDURE Clear_Screen
 PUSH RAX ;Save RAX
  MOV RAX, 0xB8000 ;Set to the beginning of video ram
 START_LOOP Clear_Screen_Loop, 1000 ;Loop 1000 times since we have to copy over 4000 bytes and we do 4 at a ime
              MOV DWORD [RAX], 0x0F200F20 ;Copy over 4 bytes
              ADD RAX, 4 ;Increment the address by 4
      END_LOOP Clear_Screen_Loop
  POP RAX ;Restore RAX
END_PROCEDURE Clear_Screen    
I didn't include the START_LOOP and END_LOOP as they just create a label at the start and then uses the loop instruction to countdown using RCX which the 1000 is put into.
Furthermore I know the Clear_Screen function works because I have used it number times before. I am just using it here to see some output to verify that the procedure is called correctly. The args on the stack don't affect it. I'll be using a CMP though to make sure args are being passed properly when this gets assembling correctly.
Post 26 Aug 2011, 16:19
View user's profile Send private message Reply with quote
hafai



Joined: 12 Jun 2011
Posts: 8
hafai 26 Aug 2011, 17:30
This is embarrassing. Earlier nothing was working because I put my includes at the beginning of the main source file. I just moved the include statement for the file with the "illegal instruction" back to the beginning and lo and behold, it's working. Sorry about that.
Post 26 Aug 2011, 17:30
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.