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
# executable will be placed here
BIN_DIR = ./bin
# root directory of source files
SRC_DIR = ./src
# obj file will be compiled and placed here
OBJ_DIR = ./obj
# our lovely compiler
CC = tcc
# our lovely assembler
AS = fasm
# compiler flags
CFLAGS = -m32
# linker flags
LDFLAGS = -Wl,-image-base=0x10000 -Wl,-subsystem=windows -lmsvcrt -luser32
# find all source files
SRCS = $(shell find $(SRC_DIR) -name "*.c" -or -name "*.asm")
# construct source tree inside obj dir
OBJS = $(patsubst $(SRC_DIR)/%,$(OBJ_DIR)/%,$(SRCS:%=%.o))
# for makefile dependency
DEPS = $(OBJS:.o=.d)
# every dir in source tree will be passed to the compiler to find include files
INC_DIR = $(shell find $(SRC_DIR) -type d)
# add the compiler prefix -I for every dir 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: $(SRC_DIR)/%.c
mkdir -p $(dir $@)
$(CC) $(CFLAGS) -c $< -o $@
# compile asm source files
$(OBJ_DIR)/%.asm.o: $(SRC_DIR)/%.asm
mkdir -p $(dir $@)
$(AS) $< $@
.PHONY: run
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.