2

I am following the tutorial from https://github.com/chipsetx/Simple-Kernel-in-C-and-Assembly. I am building it on macOS 12.4 using virtualised Ubuntu. I cannot get the kernel to compile and receive the unrecognised emulation mode: elf_i386 error. GCC command does not work with -m32 option, but runs after I remove it. The commands that I used are at the bottom of this post. Thanks for help.

kernel.asm

;;kernel.asm
bits 32     ;nasm directive
section .text
    ;multiboot spec
    align 4
    dd 0x1BADB002           ;magic
    dd 0x00             ;flags
    dd - (0x1BADB002 + 0x00)    ;checksum. m+f+c should be zero

global start
extern kmain    ;kmain is defined in the c file

start:
    cli ;block interrupts
    call kmain
    hlt ;halt the CPU

kernel.c

#define WHITE_TXT 0x07 /* light gray on black text */

void k_clear_screen();
unsigned int k_printf(char *message, unsigned int line);

/* simple kernel written in C */
void k_main() 
{
    k_clear_screen();
    k_printf("Hello, world! Welcome to my kernel.", 0);
};

/* k_clear_screen : to clear the entire text screen */
void k_clear_screen()
{
    char *vidmem = (char *) 0xb8000;
    unsigned int i=0;
    while(i < (80*25*2))
    {
        vidmem[i]=' ';
        i++;
        vidmem[i]=WHITE_TXT;
        i++;
    };
};

/* k_printf : the message and the line # */
unsigned int k_printf(char *message, unsigned int line)
{
    char *vidmem = (char *) 0xb8000;
    unsigned int i=0;

    i=(line*80*2);

    while(*message!=0)
    {
        if(*message=='\n') // check for a new line
        {
            line++;
            i=(line*80*2);
            *message++;
        } else {
            vidmem[i]=*message;
            *message++;
            i++;
            vidmem[i]=WHITE_TXT;
            i++;
        };
    };

    return(1);
}

linker.ld

OUTPUT_FORMAT(elf32-i386)
ENTRY(start)
SECTIONS
{
    . = 0x100000;
    .text : {*(.text)}
    .data : {*(.data)}
    .bss  : {*(.bss)}
}

The commands I have used to build the project.

nasm -f elf32 kernel.asm -o kasm.o => WORKS
gcc -m32 -c kernel.c -o kc.o
=> unrecognized command line option -m32 (works when I remove it)

ld -m elf_i386 -T link.ld -o kernel kasm.o kc.o 
=> ERROR HERE: ld: unrecognised emulation mode: elf_i386

qemu-system-i386 -kernel kernel
user7289922
  • 181
  • 1
  • 11
  • 3
    You may need to install some i386 development packages under Ubuntu although gcc should handle `-m32`. Mine does but I can't recall what I had to do to get it to work – Craig Estey Jun 15 '22 at 18:31
  • 2
    Just checked my ubuntu system. An installed package is `lib32gcc-5-dev` where `5` is a rev number to get the 32 `libgcc` (e.g.) But, a better package is `gcc-multilib` See: https://askubuntu.com/questions/453681/gcc-wont-link-with-m32 and https://stackoverflow.com/questions/22355436/how-to-compile-32-bit-apps-on-64-bit-ubuntu These came from a web search on: `gcc "-m32" ubuntu install package` – Craig Estey Jun 15 '22 at 20:07
  • 1
    Are you sure you're running this on an x86-64 Ubuntu system, not AArch64 or something, or native MacOS? Any x86 build of GNU Binutils `ld` should support `ld -m elf_i386`. Checking `objdump -d kc.o` output (after a build without `-m32` should show you what ISA your native GCC is targeting. (@CraigEstey: You don't need any library packages for this, since they're not *linking* with `gcc -m32`, only bare `ld`, with no libc or libgcc. Any source that happened to use libgcc helper functions, like for `uint64_t` division would have a link error.) – Peter Cordes Jun 16 '22 at 00:00
  • 2
    You might want `-ffreestanding` to make sure GCC doesn't invent calls to `memset` / `memcpy`, unless you define those symbols. Although unfortunately that will stop GCC from inlining small `memcpy` / `memset` that you use explicitly, so that sucks, and might be better to use some explicit `-fno-builtin-foo` options. – Peter Cordes Jun 16 '22 at 00:04
  • 1
    @PeterCordes see: https://stackoverflow.com/questions/21103826/m32-option-doesnt-work-with-gcc-but-works-with-g A comment there should be familiar ;-) It recommends `gcc-multilib` – Craig Estey Jun 16 '22 at 00:41
  • 1
    @CraigEstey: Exactly, totally different situation. In that Q&A, they use `gcc -m32 hello.c` *without* `-c`, so it compiles successfully, and then fails trying to link an executable with libgcc_s and libc. Here we're just using `gcc -m32 -c` to build a `.o`, and linking it manually with `ld` with no libraries. I suspect this is either an AArch64 Ubuntu on a Mac with an M1, or it's the native MacOS `gcc`/`ld` that are clang-based and want to build MachO object files, not ELF. Missing library packages wouldn't explain the symptoms; `gcc-multilib` doesn't replace `/usr/bin/ld`. – Peter Cordes Jun 16 '22 at 00:47
  • 2
    From Ubuntu, post the output of `uname -a` in a code block here to settle whether it is x86 based vs arm – Craig Estey Jun 16 '22 at 00:56
  • 2
    Try adding support for 32 bit architecture on your system. Follow this tutorial - https://askubuntu.com/a/454254 – L_R Jun 16 '22 at 07:41

0 Answers0