tcc on windows support elf object file, here is an example of how to write in fasm and use its output in tcc.
assuming you have tcc with busybox setup, throw fasm.exe where sh.exe and make.exe reside.
hello_asm.asm
format elf
public say_hello as 'asm_say_hello'
extrn 'MessageBoxA' as MessageBox
section '.text' executable align 16
say_hello:
push 0
push _caption
push _text
push 0
call MessageBox
ret
section '.data' writeable align 16
_caption db 'fasm says..',0
_text db 'hello there',0
main.c
void asm_say_hello(void);
int main(int argc, char **argv)
{
asm_say_hello();
return 0;
}
makefile
# executable name
TARGET_EXE = tcc_fasm.exe
# executables will be placed here
BIN_DIR = ./bin
# root directory of c source files
SRC_DIR = ./src
# obj file will be compiled and placed here
OBJ_DIR = ./obj
# our lovely compiler
CC = tcc
# compiler flags
CFLAGS = -m32
# linker flags
LDFLAGS = -Wl,-image-base=10000 -Wl,-subsystem=windows -lmsvcrt -luser32
# find all c source files
SRCS = $(shell find $(SRC_DIR) -name "*.c" -or -name "*.asm")
# construct same root source tree inside object directory
OBJS = $(SRCS:%=$(OBJ_DIR)/%.o)
# for makefile dependency
DEPS = $(OBJS:.o=.d)
# every directory in root source will be passed to the compiler to find header include files
INC_DIR = $(shell find $(SRC_DIR) -type d)
# add the compiler prefix -I for every directory in source tree
INC_FLAGS = $(addprefix -I,$(INC_DIR))
# add makefile dependency directories
CFLAGS += $(INC_FLAGS) -MD
# build the target executable
$(BIN_DIR)/$(TARGET_EXE): $(OBJS)
mkdir -p $(dir $@)
$(CC) $(OBJS) -o $@ $(LDFLAGS)
# compile c source files
$(OBJ_DIR)/%.c.o: %.c
mkdir -p $(dir $@)
$(CC) $(CFLAGS) -c $< -o $@
# compile asm source files
$(OBJ_DIR)/%.asm.o: %.asm
mkdir -p $(dir $@)
fasm $< $@
run:
time ./$(BIN_DIR)/$(TARGET_EXE)
.PHONY: clean
clean:
rm -r $(OBJ_DIR)
# include makefile dependencies and suppress errors of missing ones with -
-include $(DEPS)
~/Desktop/programs/tcc_busybox/projects/tcc_fasm $ make
mkdir -p obj/./src/
fasm src/hello_asm.asm obj/./src/hello_asm.asm.o
flat assembler version 1.73.32 (1048576 kilobytes memory)
3 passes, 500 bytes.
mkdir -p obj/./src/
tcc -m32 -I./src -MD -c src/main.c -o obj/./src/main.c.o
mkdir -p bin/
tcc ./obj/./src/hello_asm.asm.o ./obj/./src/main.c.o -o bin/tcc_fasm.exe -Wl,-image-base=10000 -Wl,-subsystem=windows -lmsvcrt -luser32
~/Desktop/programs/tcc_busybox/projects/tcc_fasm $ ./bin/tcc_fasm.exe
important notes:
- nothing other than elf supported
- by default tcc create two sections, .text for code, .data for data, tcc will combine sections with same name, but it places whatever code or data from fasm on top of C, i.e. first byte in first executable page for code, or writeable page for data.