私はチュートリアルに従っていますが、コードのコンパイルとリンクに関しては、次のエラーが発生します。
/tmp/cc8gRrVZ.o: In function `main':
main.c:(.text+0xa): undefined reference to `monitor_clear'
main.c:(.text+0x16): undefined reference to `monitor_write'
collect2: ld returned 1 exit status
make: *** [obj/main.o] Error 1
それが私に言っているのは、「monitor_clear」と「monitor_write」の両方を定義していないということです。しかし、私はヘッダーファイルとソースファイルの両方にあります。
それらは次のとおりです。
monitor.c:
// monitor.c -- Defines functions for writing to the monitor.
//             heavily based on Bran's kernel development tutorials,
//             but rewritten for JamesM's kernel tutorials.
#include "monitor.h"
// The VGA framebuffer starts at 0xB8000.
u16int *video_memory = (u16int *)0xB8000;
// Stores the cursor position.
u8int cursor_x = 0;
u8int cursor_y = 0;
// Updates the hardware cursor.
static void move_cursor()
{
    // The screen is 80 characters wide...
    u16int cursorLocation = cursor_y * 80 + cursor_x;
    outb(0x3D4, 14);                  // Tell the VGA board we are setting the high cursor byte.
    outb(0x3D5, cursorLocation >> 8); // Send the high cursor byte.
    outb(0x3D4, 15);                  // Tell the VGA board we are setting the low cursor byte.
    outb(0x3D5, cursorLocation);      // Send the low cursor byte.
}
// Scrolls the text on the screen up by one line.
static void scroll()
{
    // Get a space character with the default colour attributes.
    u8int attributeByte = (0 /*black*/ << 4) | (15 /*white*/ & 0x0F);
    u16int blank = 0x20 /* space */ | (attributeByte << 8);
    // Row 25 is the end, this means we need to scroll up
    if(cursor_y >= 25)
    {
        // Move the current text chunk that makes up the screen
        // back in the buffer by a line
        int i;
        for (i = 0*80; i < 24*80; i++)
        {
            video_memory[i] = video_memory[i+80];
        }
        // The last line should now be blank. Do this by writing
        // 80 spaces to it.
        for (i = 24*80; i < 25*80; i++)
        {
            video_memory[i] = blank;
        }
        // The cursor should now be on the last line.
        cursor_y = 24;
        }
    }
    // Writes a single character out to the screen.
    void monitor_put(char c)
    {
        // The background colour is black (0), the foreground is white (15).
        u8int backColour = 0;
        u8int foreColour = 15;
        // The attribute byte is made up of two nibbles - the lower being the 
        // foreground colour, and the upper the background colour.
        u8int  attributeByte = (backColour << 4) | (foreColour & 0x0F);
        // The attribute byte is the top 8 bits of the word we have to send to the
        // VGA board.
        u16int attribute = attributeByte << 8;
        u16int *location;
        // Handle a backspace, by moving the cursor back one space
        if (c == 0x08 && cursor_x)
        {
            cursor_x--;
        }
        // Handle a tab by increasing the cursor's X, but only to a point
        // where it is divisible by 8.
        else if (c == 0x09)
        {
              cursor_x = (cursor_x+8) & ~(8-1);
        }
        // Handle carriage return
        else if (c == '\r')
        {
            cursor_x = 0;
        }
       // Handle newline by moving cursor back to left and increasing the row
       else if (c == '\n')
       {
            cursor_x = 0;
            cursor_y++;
       }
       // Handle any other printable character.
       else if(c >= ' ')
       {
           location = video_memory + (cursor_y*80 + cursor_x);
           *location = c | attribute;
           cursor_x++;
       }
       // Check if we need to insert a new line because we have reached the end
       // of the screen.
       if (cursor_x >= 80)
       {
           cursor_x = 0;
           cursor_y ++;
       }
       // Scroll the screen if needed.
       scroll();
       // Move the hardware cursor.
       move_cursor();
}
// Clears the screen, by copying lots of spaces to the framebuffer.
void monitor_clear()
{
    // Make an attribute byte for the default colours
    u8int attributeByte = (0 /*black*/ << 4) | (15 /*white*/ & 0x0F);
    u16int blank = 0x20 /* space */ | (attributeByte << 8);
    int i;
    for (i = 0; i < 80*25; i++)
    {
         video_memory[i] = blank;
    }
    // Move the hardware cursor back to the start.
    cursor_x = 0;
    cursor_y = 0;
    move_cursor();
}
// Outputs a null-terminated ASCII string to the monitor.
void monitor_write(char *c)
{
    int i = 0;
    while (c[i])
    {
        monitor_put(c[i++]);
    }
}
void monitor_write_hex(u32int n)
{
    s32int tmp;
    monitor_write("0x");
    char noZeroes = 1;
    int i;
    for (i = 28; i > 0; i -= 4)
    {
        tmp = (n >> i) & 0xF;
        if (tmp == 0 && noZeroes != 0)
        {
            continue;
        }
        if (tmp >= 0xA)
        {
            noZeroes = 0;
            monitor_put (tmp-0xA+'a' );
        }
        else
        {
            noZeroes = 0;
            monitor_put( tmp+'0' );
        }
    }
    tmp = n & 0xF;
    if (tmp >= 0xA)
    {
         monitor_put (tmp-0xA+'a');
    }
    else
    {
        monitor_put (tmp+'0');
    }
}
void monitor_write_dec(u32int n)
{
    if (n == 0)
    {
        monitor_put('0');
        return;
    }
    s32int acc = n;
    char c[32];
    int i = 0;
    while (acc > 0)
    {
        c[i] = '0' + acc%10;
        acc /= 10;
        i++;
    }
    c[i] = 0;
    char c2[32];
    c2[i--] = 0;
    int j = 0;
    while(i >= 0)
    {
         c2[i--] = c[j++];
    }
    monitor_write(c2);
}
monitor.h:
// monitor.h -- Defines the interface for monitor.h
//              From JamesM's kernel development tutorials.
#ifndef MONITOR_H
#define MONITOR_H
#include "common.h"
// Write a single character out to the screen.
void monitor_put(char c);
// Clear the screen to all black.
void monitor_clear();
// Output a null-terminated ASCII string to the monitor.
void monitor_write(char *c);
#endif // MONITOR_H
common.c:
// common.c -- Defines some global functions.
//             From JamesM's kernel development tutorials.
#include "common.h"
// Write a byte out to the specified port.
void outb ( u16int port, u8int value )
{
        asm volatile ( "outb %1, %0"  : : "dN" ( port ), "a" ( value ) );
}
u8int inb ( u16int port )
{
    u8int ret;
asm volatile ( "inb %1, %0" : "=a" ( ret ) : "dN" ( port ) );
return ret;
}
u16int inw ( u16int port )
{
u16int ret;
asm volatile ( "inw %1, %0" : "=a" ( ret ) : "dN" ( port ) );
return ret;
}
// Copy len bytes from src to dest.
void memcpy(u8int *dest, const u8int *src, u32int len)
{
const u8int *sp = ( const u8int * ) src;
u8int *dp = ( u8int * ) dest;
for ( ; len != 0; len-- ) *dp++ =*sp++;
}
// Write len copies of val into dest.
void memset(u8int *dest, u8int val, u32int len)
{
u8int *temp = ( u8int * ) dest;
for ( ; len != 0; len-- ) *temp++ = val;
}
// Compare two strings. Should return -1 if 
// str1 < str2, 0 if they are equal or 1 otherwise.
int strcmp(char *str1, char *str2)
{
int i = 0;
int failed = 0;
while ( str1[i] != '\0' && str2[i] != '\0' )
{
    if ( str1[i] != str2[i] )
    {
        failed = 1;
        break;
    }
    i++;
}
// Why did the loop exit?
if ( ( str1[i] == '\0' && str2[i] != '\0' || (str1[i] != '\0' && str2[i] =='\0' ) )
    failed =1;
return failed;
}
// Copy the NULL-terminated string src into dest, and
// return dest.
char *strcpy(char *dest, const char *src)
{
do
{
    *dest++ = *src++;
}
while ( *src != 0 );
}
// Concatenate the NULL-terminated string src onto
// the end of dest, and return dest.
char *strcat(char *dest, const char *src)
{
while ( *dest != 0 )
{
    *dest = *dest++;
}
do 
{
    *dest++ = *src++;
}
while ( *src != 0 );
return dest;
}
common.h:
// common.h -- Defines typedefs and some global functions.
//             From JamesM's kernel development tutorials.
#ifndef COMMON_H
#define COMMON_H
// Some nice typedefs, to standardise sizes across platforms.
// These typedefs are written for 32-bit x86.
typedef unsigned    int     u32int;
typedef         int         s32int;
typedef unsigned    short           u16int;
typedef         short       s16int;
typedef unsigned    char        u8int;
typedef         char            s8int;
void outb ( u16int port, u8int value );
u8int inb ( u16int port );
u16int inw ( u16int port );
#endif //COMMON_H
main.c:
// main.c -- Defines the C-code kernel entry point, calls initialisation routines.
//           Made for JamesM's tutorials <www.jamesmolloy.co.uk>
#include "monitor.h"
int main(struct multiboot *mboot_ptr)
{
    monitor_clear();
monitor_write ( "hello, world!" );
return 0;
}
これが私のmakefileです:
C_SOURCES=  main.c monitor.c common.c
S_SOURCES= boot.s
C_OBJECTS=$(patsubst %.c, obj/%.o, $(C_SOURCES))
S_OBJECTS=$(patsubst %.s, obj/%.o, $(S_SOURCES))
CFLAGS=-nostdlib -nostdinc -fno-builtin -fno-stack-protector -m32 -Iheaders
LDFLAGS=-Tlink.ld -melf_i386 --oformat=elf32-i386
ASFLAGS=-felf
all: kern/kernel
.PHONY: clean
clean:
-rm -f kern/kernel
kern/kernel: $(S_OBJECTS) $(C_OBJECTS)
ld $(LDFLAGS) -o $@ $^
$(C_OBJECTS): obj/%.o : %.c 
gcc $(CFLAGS) $< -o $@
vpath %.c source
$(S_OBJECTS): obj/%.o : %.s
    nasm $(ASFLAGS) $< -o $@
vpath %.s asem
うまくいけば、これはあなたが何が間違っているのか、そしてそれを修正する方法を理解するのに役立つでしょう:L
前もって感謝します。
ジェイミー。