hi, how do i import symbol only if it's used in NASM?

Something like following in FASM:
if used SomeProcedure
extrn SomeProcedure
end if


i need it for building headers for library, but i don't want every object compiled with this header to import hundreds of procedures it doesn't use.
Posted on 2007-05-24 09:15:55 by vid

hi, how do i import symbol only if it's used in NASM?

Something like following in FASM:
if used SomeProcedure
extrn SomeProcedure
end if


i need it for building headers for library, but i don't want every object compiled with this header to import hundreds of procedures it doesn't use.


Take a look at the IMPORT and INVOKE macros that NASM32.INC provides within the NASM32 Project. This is one way of achieving what you want.
Posted on 2007-05-25 08:21:29 by SpooK
but then i have to use "invoke" with procedure to get it imported, right?

isn't there something that would work with pure assembly?
Posted on 2007-05-26 07:11:33 by vid

but then i have to use "invoke" with procedure to get it imported, right?

isn't there something that would work with pure assembly?


Probably not. FASM does it within the source code, NASM requires MACRO intervention. Both ways don't involve "pure assembly" in any sense of the term.

I'm sure that you can overload EXTERN with an %imacro that does similar to what the IMPORT/INVOKE combination does... but I would imagine that it is more trouble than it is worth.
Posted on 2007-05-26 13:14:33 by SpooK
vid,

Actually the best way is to overload "CALL" as described in a previous thread (can't remember the URL so I'll just post a similar macro here).

%imacro call 1
%push invoke

  %ifdef __stdcall_defined_%{1}
  %define %{1} __stdcall_defined_%{1}
  extern __stdcall_defined_%{1}
  %endif

  %ifdef __cdecl_defined_%{1}
  %define %{1} __cdecl_defined_%{1}
  extern __cdecl_defined_%{1}
  %endif

  %ifdef _UNDERSCORE_
  %define _proc _%{1}
  %else
  %define _proc %{1}
  %endif

  call _proc

%pop
%endmacro


This is the 'CALL' macro from my BKMACROS.INC file (currently not available). It overloads CALL so that it can work with the NASM32 library procedural include files (like kernel32.inc, user32.inc, etc). It's basically a stripped down version of the 'INVOKE' macro. This is probably the best, and easiest, way to go about it. I don't suggest trying to overload 'EXTERN' as it's a directive and I've gone that route before, you tend to run into order of processing issues where the directive is processed before the macro, or parts there of, are ready to be handled. With certain directives it can be done, but it's just a pain and not worth the effort.

Regards,
Bryant Keller
Posted on 2007-05-27 01:34:42 by Synfire
Both ways don't involve "pure assembly" in any sense of the term.

i meant pure assembly for those who use header, not nescassarily in header.

I would probably have to stick to instruction overloading, like Synfire insisted. Unfortunatelly, that means i would have to limit usage of those symbols to just CALL and maybe JMP.

Synfire: thanks for macros. If I would want to allow same for JMP, i would probably have to support more forms (jmp XXX, jump near XXX, jump short XXX, ...). Could you please hint me how to write such macro in NASM?
Posted on 2007-05-27 18:55:31 by vid
vid,

Probably the easiest way would be to add an extra argument (now keep in mind none of these macros have been tested and it's 5:40 AM) like so:

%imacro jmp 1-2
%push jump

  %if %0 = 2
  %define _distance %1
  %rotate 1
  %endif

  %ifdef __stdcall_defined_%{1}
  %define %{1} __stdcall_defined_%{1}
  extern __stdcall_defined_%{1}
  %endif

  %ifdef __cdecl_defined_%{1}
  %define %{1} __cdecl_defined_%{1}
  extern __cdecl_defined_%{1}
  %endif

  %ifdef _UNDERSCORE_
  %define _proc _%{1}
  %else
  %define _proc %{1}
  %endif

  %ifdef _distance
  jmp _distance _proc
  %else
  jmp _proc
  %endif

%pop
%endmacro


Then do your jumps using jmp XXX or jmp near, XXX it merely adds a comma to the works. If you don't want the comma, that's where things are going to get a bit hairy. I can't really think of anything right off the top of my head, it's pretty late and I've not had much sleep recently.. but if you hash/compared the first part, then figured out a way to strip out the latter you could pass everything as a string, parsing could probably be done using %substr and %strlen with predetermined values.. although this makes the; near, far, short, long tokens case sensitive. Sorta like (I use %error to display messages to the screen in this example):

%imacro jmp 1
%push jmp

  %assign index 1
  %assign hash  0

  %rep 4
  %substr character %{1} index
  %assign hash (hash<<0x13)+(hash>>0x0d)+character
  %assign index index+1
  %endrep

  %if hash = -553117262
  %error Near Jump Handler
  %endif

  %assign index 1
  %assign hash  0

  %rep 3
  %substr character %{1} index
  %assign hash (hash<<0x13)+(hash>>0x0d)+character
  %assign index index+1
  %endrep

  %if hash = 50862578
  %error Far Jump Handler
  %endif

  %assign index 1
  %assign hash  0

  %rep 5
  %substr character %{1} index
  %assign hash (hash<<0x13)+(hash>>0x0d)+character
  %assign index index+1
  %endrep

  %if hash = -745059276
  %error Short Jump Handler
  %endif

  %assign index 1
  %assign hash  0

  %rep 4
  %substr character %{1} index
  %assign hash (hash<<0x13)+(hash>>0x0d)+character
  %assign index index+1
  %endrep

  %if hash = -613409753
  %error Long Jump Handler
  %endif

%pop
%endmacro

jmp "near XXX"


There are many different approaches to this one, but I would go with the first.. or possibly the old style of creating jmpn, jmpf, jmps, jmpl macros. Those are pretty common in most macros.inc files you find around. That's the best hints I can give you this late at night.

Regards,
Bryant Keller
Posted on 2007-05-28 04:51:43 by Synfire
thanks. I will think about it.

I want to enforce as few macros as possible on users of my header... Looks like a hard job
Posted on 2007-05-28 06:00:12 by vid
does NASM support inline macros? maybe i could define symbol as inline macro that would declare it on first use?
Posted on 2007-05-28 07:32:01 by vid
It supports single line macros which can be expanded as arguments/operands if that's what you're talking about:

%define
%idefine
%xdefine

If you are talking about something like 'EXITM' then no, NASM doesn't have support returning values or expressions from a macro like that.

%idefine sizeof(a) a %+ _size
...
mov eax, SIZEOF ( WNDCLASSEX )


VAR() and ARGV() from NASM32.INC use this convention. Attached to this is post is my BKMACROS.INC file. Think of it as an overly simplified variant of NASM32. You might find it useful in trying to figure out some of your macro issues. Below is a test source to show source code works when using the BKMACROS.INC file (it's not really impressive when compared to NASM32.INC but it's useful as an extension.

;---------------------------------------------------------------;
; test.asm - application to test BKMACROS.INC                  ;
;                                                              ;
; Written by : Bryant Keller                                    ;
; Email      : bkeller@codegurus.org                            ;
; Page      : http://asm.codegurus.org/                        ;
; Compiler  : Netwide Assembler v0.98.39                      ;
; Date      ; 23-Feb-2007                                      ;
; Purpose    : Assembly program used as a test bed during the  ;
;              development of the MACROS.INC include file.      ;
;              Designed for use with Netwide Assembler.        ;
;                                                              ;
;---------------------------------------------------------------;

%include "bkmacros.inc"
%include "\nasm32\inc\win32\windows.inc"
%include "\nasm32\inc\win32\kernel32.inc"
%include "\nasm32\inc\win32\user32.inc"

%define NASM32_COMPATIBLE
;%define MEM_MOVE_REG EAX ; switch to using a register
                          ; to move memory operands (m2m)

STRUC DOUBLEWORD
.HighWord RESW 1
.LowWord RESW 1
ENDSTRUC

.data
szMessage: DB "Would you like to quit now?", 0

highlow:
istruc DOUBLEWORD
AT DOUBLEWORD.HighWord, dw 0
AT DOUBLEWORD.LowWord, dw 0
iend

dwBackup: DD 0

.code

global main
main: xor EAX, EAX
xor EBX, EBX
xor ECX, ECX
xor EDX, EDX
@@
push ECX
push D MB_YESNO, "Hello World!", szMessage, D NULL
call MessageBoxA
pop ECX
inc ECX
cmp EAX, IDNO
jz @B

cmp ECX, 5
jz @F

ASSUME highlow, DOUBLEWORD
mov W highlow.(HighWord), AX
mov W highlow.(LowWord), sizeof(DOUBLEWORD)

ASSUME highlow, NOTHING
mov EAX, D
m2m D , D

push "Thank you for trying macros.inc", "Exiting..."
call MyProc
@@
push D NULL
call ExitProcess
ret

MyProc:
BEGIN 256 ; 256 bytes on the stack

mov ESI, arg(1)
mov EDI, arg(2)
push D MB_OK, ESI, EDI, D NULL
call MessageBoxA

mov EDI, ESP
push "So far everything seems fine :)"
push EDI
call lstrcpyA

push D MB_OK, ESI, EDI, D NULL
call MessageBoxA

END


Regards,
Bryant Keller
Attachments:
Posted on 2007-05-28 13:37:59 by Synfire
wrong vocabulary

i meant kind of inline macro that can expand to multiple lines. Like then EXITM macros in MASM.

:(

now i understand why GAS developers decided to stop using "extern" and declare every unknown symbol as extern ;)
Posted on 2007-05-28 14:01:35 by vid
Heh, you posted while I was updating. Read the extra information in my previous post.
Posted on 2007-05-28 14:05:25 by Synfire
thanks, unfortunately that doesn't help me :(
Posted on 2007-05-28 16:00:25 by vid