Search code examples
cassemblywatcom

E2028: _small_code_ is an undefined reference


I am working on my own bootloader. I want it to print "Hello world". For some reason, I get an error: Error! E2028: small_code is an undefined reference

Hello! I am working on my own bootloader. I want it to print "Hello world". I have the following code:

main.c:

#define HELLO_STR               "\"Hello, world…\""

#define BLACK           0x0
#define WHITE           0xF

typedef unsigned char byte;

#define bool char
#define true 1
#define false 0

int STRLEN_(const char *str) {
    int len = 0;
    while ((*str) != '\0') {
        len++;
    }

    return len;
}

void printText(
        const char *str,
        byte inX,
        byte inY,
        byte inBackgroundColor,
        byte inTextColor,
        bool inUpdateCursor
    )
{
    byte textAttribute = ((inTextColor) | (inBackgroundColor << 4));
    byte lengthOfString = STRLEN_(str);

    __asm {
        push    bp
        mov     al, inUpdateCursor
        xor     bh, bh
        mov     bl, textAttribute
        xor     cx, cx
        mov     cl, lengthOfString
        mov     dh, inY
        mov     dl, inX
        mov     es, word ptr[str + 2]
        mov     bp, word ptr[str]
        mov     ah, 13h
        int     10h
        pop     bp
    }
}

void clearScreen(void) {
    __asm {
        mov  al, 02h
        mov  ah, 00h
        int     10h
    }
}

void showCursor(bool inMode) {
    byte flag = inMode ? 0 : 0x32;

    __asm {
        mov     ch, flag
        mov     cl, 0Ah
        mov     ah, 01h
        int     10h
    }
}

void BootMain()
{
    clearScreen();
    showCursor(false);

    printText(
        HELLO_STR,
        0,
        0,
        BLACK,
        WHITE,
        false
        );

    return;
}

StartPoint.asm:

;------------------------------------------------------------
.286                               ; CPU type
;------------------------------------------------------------
.model TINY                        ; memory of model
;---------------------- EXTERNS -----------------------------
extrn               BootMain_:near     ; prototype of C func
;------------------------------------------------------------
;------------------------------------------------------------
.code
org             07c00h         ; for BootSector
main:
                jmp short start    ; go to main
                nop

;----------------------- CODE SEGMENT -----------------------
start:
        cli
        mov ax,cs               ; Setup segment registers
        mov ds,ax               ; Make DS correct
        mov es,ax               ; Make ES correct
        mov ss,ax               ; Make SS correct
        mov bp,7c00h
        mov sp,7c00h            ; Setup a stack
        sti
                                ; start the program
        call           BootMain_
        ret

        END main                ; End of program

Then I use the following commands to compile it: wcl.exe -v -mt -s -c -bt=dos -fo=main.obj main.c & ".\VC152\wasm.exe" -q -0 -fo="StartPoint.obj" ".\StartPoint.asm" .\VC152\wlink.exe file "StartPoint.obj" file "main.obj" name bootloader.com format dos com option nodefaultlibs option quiet

But when I try to link both files I get the following error: Error! E2028: small_code is an undefined reference

How can I fix that?


Solution

  • From the OpenWatcom reference guide:

    small_code If this undefined reference occurs when you are trying to create a 16-bit application, we have saved you many hours of debugging! The reason for this undefined reference is that the "main" entry point has been compiled for a big code model (in any one of medium, large, or huge memory models).

    ...

    There may be another cause of this problem, the "main" function must be entered in lower case letters ("Main" or "MAIN" are not identified as being the same as "main" by the compiler). The compiler will identify the module that contains the definition of the function "main" by creating the public definition of either small_code or big_code depending on the memory model it was compiled in.

    So this is your issue in a nutshell: no main function, so Watcom's internal machinery doesn't work as supposed. You can either rename your "main" function to actual main and let that machinery work, or provide a public symbol _small_code_ somewhere.