flat assembler
Message board for the users of flat assembler.

Index > Compiler Internals > Conditional compilation

Author
Thread Post new topic Reply to topic
Endre



Joined: 29 Dec 2003
Posts: 215
Location: Budapest, Hungary
Endre 09 Nov 2008, 19:09
I was just getting tired of copying constants from (linux) system headers into my assembly programs, so I tried to put this work on cpp (the c-preprocessor). First I tried with gnu "as". Everything worked just as I expected, but the same method did not behave the same way with fasm.

Here the gnu "as" code (little bit changed hello world example from the fasm package):
Code:
/**
 * Compile with
 * gcc -g -nostdlib hello_gcc.S -o hello_gcc
 * or
 * gcc -s -nostdlib hello_gcc.S -o hello_gcc
 * sstrip ./hello_gcc  (see elfkickers)
 */

        .if 0
#include <asm/unistd.h>
#include <unistd.h>
        .endif

        .line __LINE__
        .intel_syntax noprefix
        .text
        .globl _start
_start:
        nop
        mov     rax, __NR_write
        mov     rdi, STDOUT_FILENO
        mov     rsi, offset msg
        mov     rdx, offset msg_size
        syscall
        xor     rdi, rdi
        mov     rax, __NR_exit
        syscall

msg:
        .string "Hello 64-bit world!\n"
msg_size = . - msg
    
As mentioned above this works perfectly. The C-preprocessor submits my symbols with correct values and the conditional compilation protects the assembler from the uninterpretable c-code. Excellent I thought, and tried the same thing with fasm:
Code:
; Compile with
; cpp -P hello_fasm.asm -o hello_fasm_pp.asm
; fasm hello_fasm_pp.asm

format ELF64 executable

match =a, b {
#include <asm/unistd.h>
#include <unistd.h>
}

segment readable executable

entry $
        nop
        mov     rax, __NR_write
        mov     rdi, STDOUT_FILENO
        mov     rsi,  msg
        mov     rdx,  msg_size
        syscall
        xor     rdi, rdi
        mov     rax, __NR_exit
        syscall

msg db 'Hello 64-bit world!',0xA
msg_size = $-msg    

But it always signalizes syntax error in code from any of the header files that it might not even see. Since it seems that most of the c-codes are correctly ignored by the assembler I do not understand why it feels after a while that it has to restart assembling, despite the fact that "match" brace isn't closed yet.
Post 09 Nov 2008, 19:09
View user's profile Send private message Reply with quote
baldr



Joined: 19 Mar 2008
Posts: 1651
baldr 09 Nov 2008, 20:42
Endre,

Definitely there is } somewhere in the cpp's output. That surely will do harm. Wink
Post 09 Nov 2008, 20:42
View user's profile Send private message Reply with quote
Endre



Joined: 29 Dec 2003
Posts: 215
Location: Budapest, Hungary
Endre 10 Nov 2008, 10:24
Of course, it's evident that in c-code there are characters that may disturb fasm, but it signalizes error where around no such characters are there. Check it out. On the other hand there should be some better mechanism to exclude code parts more safely. Just see "as". It uses .if, .endif. Such tokens are quite rare in programming languages or comments.
Post 10 Nov 2008, 10:24
View user's profile Send private message Reply with quote
baldr



Joined: 19 Mar 2008
Posts: 1651
baldr 10 Nov 2008, 11:41
Endre,

How do I supposed to check your cpp output? Wink

Try to enclose #includes in if 0 … end if.
Post 10 Nov 2008, 11:41
View user's profile Send private message Reply with quote
Endre



Joined: 29 Dec 2003
Posts: 215
Location: Budapest, Hungary
Endre 14 Nov 2008, 09:44
gcc:
Code:
gcc -E hello_gcc.S -o hello_gcc_pp.s    

fasm:
Code:
cpp -P hello_fasm.asm -o hello_fasm_pp.asm    


Of course gcc uses cpp as well. On windows you will need Cygwin or MinGW for gcc and cpp, additionally my example won't compile because it uses linux system calls and linux headers you won't have on neither of the above mentioned environments. If you want then I can write some example that you can compile also on windows.

I tried if/endif. They are even worse.
Post 14 Nov 2008, 09:44
View user's profile Send private message Reply with quote
baldr



Joined: 19 Mar 2008
Posts: 1651
baldr 14 Nov 2008, 10:48
Endre,

hello_fasm_pp.asm will be enough. Attach it so I could see it.
Post 14 Nov 2008, 10:48
View user's profile Send private message Reply with quote
Endre



Joined: 29 Dec 2003
Posts: 215
Location: Budapest, Hungary
Endre 15 Nov 2008, 14:16
When compiling I get this message:

Code:
flat assembler  version 1.67.28  (16384 kilobytes memory)
hello_fasm_pp.asm [1016]:
extern long int sysconf (int __name) __attribute__ ((__nothrow__));
error: invalid expression.    


Description: cpp output
Download
Filename: hello_fasm_pp.asm.zip
Filesize: 3.44 KB
Downloaded: 869 Time(s)

Post 15 Nov 2008, 14:16
View user's profile Send private message Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8351
Location: Kraków, Poland
Tomasz Grysztar 15 Nov 2008, 14:43
There are closing braces inside your "match" block, so it ends prematurely (in fasm braces cannot nest). To make it behave correctly you have to replace all "}" occurences in C source with "\}".

Oh, and I think it would be nicer to use "rept 0" instead of that "match".
Post 15 Nov 2008, 14:43
View user's profile Send private message Visit poster's website Reply with quote
baldr



Joined: 19 Mar 2008
Posts: 1651
baldr 16 Nov 2008, 14:30
Endre,

The only way I came up with so far is to post-process the source after cpp to remove all the #includes' leftovers (e.g. enclose them between distinguishable lines and use some tool, such as awk, to drop them from the source).

My first thought was about pre-preprocessing Wink files to be #included, replacing '}' with '\}', but it involves parsing C syntax, at least to avoid replacement in character/string literals.

if 0 … end if trick doesn't work because ifs can be nested, thus fasm should interpret the "" anyway. My fault. Wink
Post 16 Nov 2008, 14:30
View user's profile Send private message Reply with quote
Endre



Joined: 29 Dec 2003
Posts: 215
Location: Budapest, Hungary
Endre 16 Nov 2008, 19:01
Guys, I've just wanted to point out some weakness of fasm preprocessor directives (unfortunate C-like syntax, lack of nestabality etc.).
I exactly know that you can work-around the problem but I guess, it's not the way it should be.
Post 16 Nov 2008, 19:01
View user's profile Send private message Reply with quote
vid
Verbosity in development


Joined: 05 Sep 2003
Posts: 7105
Location: Slovakia
vid 16 Nov 2008, 19:13
Lack of C-like #if, lack of inline macros, and lack of string parsing, really are weaknesses of FASM macro system. But otherwise, combined with some assembly-time features (defined/used, virtual, forward referencing) still makes it about as powerful macro system as MASM's, but based on much smaller set of features.
Post 16 Nov 2008, 19:13
View user's profile Send private message Visit poster's website AIM Address MSN Messenger ICQ Number Reply with quote
baldr



Joined: 19 Mar 2008
Posts: 1651
baldr 26 Nov 2008, 10:34
Endre,

I don't think that Tomasz designed fasm with ability to include foreign sources in mind.

By the way, of what use they are (#includes of C headers)? Just to replace several object-like macros with constants? Even in that case you can easily stumble upon something like #define NULL ((void *)0)

There is a Perl script to convert C source to fasm syntax include file, but don't expect too much from it: at a first glance, it doesn't handle nested #includes (surely there are more restrictions).
Post 26 Nov 2008, 10:34
View user's profile Send private message Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4022
Location: vpcmpistri
bitRAKE 26 Nov 2008, 16:01
Nesting in the FASM preprocessor is stack based - it isn't a work-around, but by design I believe.
Code:
macro bracket {
       display "0"
}
macro bracket {
     display "1"
       bracket
}
macro bracket {
   bracket
     purge bracket
       display "2"
       bracket
}
macro bracket {
   display "3"
       bracket
}
bracket    
Post 26 Nov 2008, 16:01
View user's profile Send private message Visit poster's website Reply with quote
Endre



Joined: 29 Dec 2003
Posts: 215
Location: Budapest, Hungary
Endre 29 Nov 2008, 17:46
baldr wrote:
Endre,

I don't think that Tomasz designed fasm with ability to include foreign sources in mind.

Fasm should not include anything. It's done by the preprocessor. The only thing fasm needs to do is to have a "better" preprocessor syntax to protect itself from other languages (let's say open: C). C is used by all the OSs fasm runs on. So it would be just enough to use such syntax for its preprocessor directives that is not C-like. That's why the most assemblers, I know, use preprocessor syntax like for instance .if, .else, .endif. Due the dot prefix these tokens are acceptably rare in C-programs/headers (don't forget comments are automatically discarded by the C-preprocessor, so you don't have to fear them).

Quote:
Just to replace several object-like macros with constants?
Yes, my intention is something like this, however I don't exactly understand your "object-like" term.

Quote:
Even in that case you can easily stumble upon something like #define NULL ((void *)0)

This is the nature of the C-preprocessor you should be aware of. I don't see any problem with it.

Quote:
There is a Perl script to convert C source to fasm syntax include file, but don't expect too much from it: at a first glance, it doesn't handle nested #includes (surely there are more restrictions).

I guess it does not correctly handle other preprocessor directives either (e.g. #if 0/#endif) I simply don't understand why somebody wants to use an incorrect preprocessor when he/she could use a correct one. Is it faster? Needs less RAM, processor, anything?
Post 29 Nov 2008, 17:46
View user's profile Send private message Reply with quote
baldr



Joined: 19 Mar 2008
Posts: 1651
baldr 02 Dec 2008, 00:47
Endre,

By "include foreign sources" I meant any piece of source not in fasm syntax; it has nothing to do with method by which that piece occurs in source file given to fasm for compilation (even copy+paste Wink). If those C include files are pure preprocessor's (i.e. only preprocessor's directives and comments, no declarations), they'll leave no extras in preprocessor's output after replacements are done, so no need of .if/.endif ever arise.
Endre wrote:
Yes, my intention is something like this,…
This is the only reason?
Endre wrote:
…however I don't exactly understand your "object-like" term.
When in doubt, RTFM Wink. ISO/IEC 9899:TC2 "Programming Languages — C", clause 6 "Language", subclause 6.10.3 "Macro replacement", paragraphs 9 and 10 give definitions of object- and function-like macros, respectively.
Endre wrote:
This is the nature of the C-preprocessor you should be aware of. I don't see any problem with it.
I don't either. It's fasm that will complain about expression syntax (<< vs. shl and such – there are too much differences in syntax to simply replace some identifiers with respective C constant expressions).
Endre wrote:
I guess it does not correctly handle other preprocessor directives either (e.g. #if 0/#endif) I simply don't understand why somebody wants to use an incorrect preprocessor when he/she could use a correct one.
Definitely neither it is a full-blown C syntax parser nor it is supposed to be. It is the tool to convert C include files to fasm syntax. Anyway, it's output is supposed to be hand-tuned (e.g. alignment of fields in struct).

By the way, I'd managed to compile your preprocessed source with the following changes:
Code:
;; Compile with
;; cpp hello_fasm.asm -o hello_fasm_pp.asm
;; fasm hello_fasm_pp.asm

format ELF64 executable

macro typedef [arg] {}
macro enum [arg] {
common
        purge   xx
        macro   xx
}
macro extern [arg] {}
macro __attribute__ [arg] {}
macro char [arg] {}
macro size_t [arg] {}

#include <asm/unistd.h>
#include <unistd.h>

purge typedef, extern, __attribute__, char, size_t, xx

segment readable executable

entry $
        nop
        mov     rax, __NR_write
        mov     rdi, STDOUT_FILENO
        mov     rsi,  msg
        mov     rdx,  msg_size
        syscall
        xor     rdi, rdi
        mov     rax, __NR_exit
        syscall

msg db 'Hello 64-bit world!',0xA
msg_size = $-msg    
Cumbersome? Yes. But works. Wink
Post 02 Dec 2008, 00:47
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-2024, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.