Ucore lab1實驗報告


練習一 Makefile

1.1 OS鏡像文件ucore.img 是如何一步步生成的?

+ cc kern/init/init.c
+ cc kern/libs/readline.c
+ cc kern/libs/stdio.c
+ cc kern/debug/kdebug.c
+ cc kern/debug/kmonitor.c
+ cc kern/debug/panic.c
kern/debug/panic.c: In function '__panic':
kern/debug/panic.c:27:5: warning: implicit declaration of function 'print_stackframe' [-Wimplicit-function-declaration]
     print_stackframe();
     ^
+ cc kern/driver/clock.c
+ cc kern/driver/console.c
+ cc kern/driver/intr.c
+ cc kern/driver/picirq.c
+ cc kern/trap/trap.c
+ cc kern/trap/trapentry.S
+ cc kern/trap/vectors.S
+ cc kern/mm/pmm.c
+ cc libs/printfmt.c
+ cc libs/string.c
+ ld bin/kernel
+ cc boot/bootasm.S
+ cc boot/bootmain.c
+ cc tools/sign.c
tools/sign.c: In function 'main':
tools/sign.c:17:5: warning: unknown conversion type character 'l' in format [-Wformat=]
     printf("'%s' size: %lld bytes\n", argv[1], (long long)st.st_size);
     ^
tools/sign.c:17:5: warning: too many arguments for format [-Wformat-extra-args]
tools/sign.c:19:9: warning: unknown conversion type character 'l' in format [-Wformat=]
         fprintf(stderr, "%lld >> 510!!\n", (long long)st.st_size);
         ^
tools/sign.c:19:9: warning: too many arguments for format [-Wformat-extra-args]
+ ld bin/bootblock
'obj/bootblock.out' size: 480 bytes
build 512 bytes boot sector: 'bin/bootblock' success!

其中Makefile文件中include tools/function.mk  其中定義了一些Makefile中用到的函數

生成ucore.img  需要kernel和bootblock 如下:

# create ucore.img
UCOREIMG    := $(call totarget,ucore.img)

$(UCOREIMG): $(kernel) $(bootblock)
    $(V)dd if=/dev/zero of=$@ count=10000
    $(V)dd if=$(bootblock) of=$@ conv=notrunc
    $(V)dd if=$(kernel) of=$@ seek=1 conv=notrunc

$(call create_target,ucore.img)

kernel編譯鏈接:

# -------------------------------------------------------------------
# kernel

# kernel中頭文件目錄
KINCLUDE    += kern/debug/ \
               kern/driver/ \
               kern/trap/ \
               kern/mm/

# kernel的源代碼目錄
KSRCDIR        += kern/init \
               kern/libs \
               kern/debug \
               kern/driver \
               kern/trap \
               kern/mm

# 在編譯選項中添加頭文件包含目錄
KCFLAGS        += $(addprefix -I,$(KINCLUDE))

# 調用function.mk中的add_files_cc函數,將kernel的全部源文件編譯,將源文件和編譯生成的OBJ文件加入kernel包(packet)中
$(call add_files_cc,$(call listf_cc,$(KSRCDIR)),kernel,$(KCFLAGS))

# 將KOBJS定義為編譯生成的.o文件列表(大概??)
KOBJS    = $(call read_packet,kernel libs)

# create kernel target
# (在kernel前面加上bin/目錄名)
kernel = $(call totarget,kernel)

# kernel目標依賴於tools/kernel.ld文件
$(kernel): tools/kernel.ld

# kernel目標依賴於編譯生成的OBJ文件
$(kernel): $(KOBJS)
        # 輸出"+ ld bin/kernel"到控制台
    @echo + ld $@
    # 即命令"ld -m    elf_i386 -nostdlib -T tools/kernel.ld -o bin/kernel  obj/kern/init/init.o ... obj/libs/printfmt.o"
    $(V)$(LD) $(LDFLAGS) -T tools/kernel.ld -o $@ $(KOBJS)
    # 將OBJ文件全部反編譯為匯編文件
    @$(OBJDUMP) -S $@ > $(call asmfile,kernel)
    # 輸出OBJ文件對應的符號表
    @$(OBJDUMP) -t $@ | $(SED) '1,/SYMBOL TABLE/d; s/ .* / /; /^$$/d' > $(call symfile,kernel)

# 將kernel包和OBJ文件添加到目標依賴
$(call create_target,kernel)

bootblock:

# -------------------------------------------------------------------

# create bootblock
# bootfiles為boot/文件夾下的全部文件列表
bootfiles = $(call listf_cc,boot)
# 編譯boot/文件夾下的全部文件
$(foreach f,$(bootfiles),$(call cc_compile,$(f),$(CC),$(CFLAGS) -Os -nostdinc))

# (在bootblock前面加上bin/目錄名)
bootblock = $(call totarget,bootblock)

# bootblock目標的依賴項為源文件對應的OBJ文件和bin/sign
$(bootblock): $(call toobj,$(bootfiles)) | $(call totarget,sign)
        # 輸出"+ ld bin/bootblock"到控制台
        @echo + ld $@
        # 將OBJ文件鏈接為bin/bootblock
    $(V)$(LD) $(LDFLAGS) -N -e start -Ttext 0x7C00 $^ -o $(call toobj,bootblock)
    # 將bin/bootblock文件反編譯
    @$(OBJDUMP) -S $(call objfile,bootblock) > $(call asmfile,bootblock)
    # 將bin/bootblock轉換成bin/bootblock.out二進制文件
    @$(OBJCOPY) -S -O binary $(call objfile,bootblock) $(call outfile,bootblock)
    # 用鏈接出的bin/sign工具將bin/bootblock.out再轉換回bin/bootblock二進制文件
    @$(call totarget,sign) $(call outfile,bootblock) $(bootblock)

# 將bootblock包添加到bootblock目標
$(call create_target,bootblock)

sign:

# -------------------------------------------------------------------

# create 'sign' tools
# 將tools/sign.c編譯到OBJ文件,將源文件和中間文件添加到sign包
$(call add_files_host,tools/sign.c,sign,sign)
# 將sign包添加到sign目標
$(call create_target_host,sign,sign)

ucore.img:

# -------------------------------------------------------------------

# create ucore.img
# 在ucore.img前面加上bin/
UCOREIMG    := $(call totarget,ucore.img)

$(UCOREIMG): $(kernel) $(bootblock)
        # 創建一個大小為10000字節的空白文件
    $(V)dd if=/dev/zero of=$@ count=10000
    # 向上述文件中拷貝bin/bootblock
    $(V)dd if=$(bootblock) of=$@ conv=notrunc
    # 向上述文件中繼續(第二個塊)拷貝bin/kernel
    $(V)dd if=$(kernel) of=$@ seek=1 conv=notrunc

# 將ucore.img包添加到ucore.img目標
$(call create_target,ucore.img)

dd的一些參數的含義:(dd命令說明
-if表示輸入文件,如果不指定,那么會默認從stdin中讀取輸入
-of表示輸出文件,如果不指定,那么會stdout
bs表示以字節為單位的塊大小
count表示被賦值的塊數
/dev/zero是一個字符設備,會不斷返回0值字節\0
conv = notrunc 不截短輸出文件
seek=blocks 從輸出文件開頭跳過blocks個塊后再開始復制

 

生成kernel的.obj實際命令:

gcc -Ikern/init/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/init/init.c -o obj/kern/init/init.o
gcc -Ikern/libs/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/libs/stdio.c -o obj/kern/libs/stdio.o
gcc -Ikern/libs/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/libs/readline.c -o obj/kern/libs/readline.o
gcc -Ikern/debug/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/debug/panic.c -o obj/kern/debug/panic.o
gcc -Ikern/debug/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/debug/kdebug.c -o obj/kern/debug/kdebug.o
gcc -Ikern/debug/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/debug/kmonitor.c -o obj/kern/debug/kmonitor.o
gcc -Ikern/driver/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/driver/clock.c -o obj/kern/driver/clock.o
gcc -Ikern/driver/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/driver/console.c -o obj/kern/driver/console.o
gcc -Ikern/driver/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/driver/picirq.c -o obj/kern/driver/picirq.o
gcc -Ikern/driver/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/driver/intr.c -o obj/kern/driver/intr.o
gcc -Ikern/trap/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/trap/trap.c -o obj/kern/trap/trap.o
gcc -Ikern/trap/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/trap/vectors.S -o obj/kern/trap/vectors.o
gcc -Ikern/trap/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/trap/trapentry.S -o obj/kern/trap/trapentry.o
gcc -Ikern/mm/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/mm/pmm.c -o obj/kern/mm/pmm.o
gcc -Ilibs/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/  -c libs/string.c -o obj/libs/string.o
gcc -Ilibs/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/  -c libs/printfmt.c -o obj/libs/printfmt.o

參數及其意義:(gcc官方文檔

 

    • -I:添加包含目錄
    • -fno-builtin:只接受以“__builtin_”開頭的名稱的內建函數
    • -Wall:開啟全部警告提示
    • -ggdb:生成GDB需要的調試信息
    • -m32:為32位環境生成代碼,int、long和指針都是32位
    • -gstab:生成stab格式的調試信息,僅用於gdb
    • -nostdinc:不掃描標准系統頭文件,只在-I指令指定的目錄中掃描
    • -fno-stack-protector:生成用於檢查棧溢出的額外代碼,如果發生錯誤,則打印錯誤信息並退出
    • -c:編譯源文件但不進行鏈接
    • -o:結果的輸出文件

鏈接生成kernel二進制文件的命令為:

    • ld -m    elf_i386 -nostdlib -T tools/kernel.ld -o bin/kernel  obj/kern/init/init.o obj/kern/libs/stdio.o obj/kern/libs/readline.o obj/kern/debug/panic.o obj/kern/debug/kdebug.o obj/kern/debug/kmonitor.o obj/kern/driver/clock.o obj/kern/driver/console.o obj/kern/driver/picirq.o obj/kern/driver/intr.o obj/kern/trap/trap.o obj/kern/trap/vectors.o obj/kern/trap/trapentry.o obj/kern/mm/pmm.o  obj/libs/string.o obj/libs/printfmt.o

      參數及其意義:(ld參數說明

      • -m elf_i386:使用elf_i386模擬器
      • -nostdlib:只查找命令行中明確給出的庫目錄,不查找鏈接器腳本中給出的(即使鏈接器腳本是在命令行中給出的)
      • -T tools/kernel.ld:將tools/kernel.ld作為鏈接器腳本
      • -o bin/kernel:輸出到bin/kernel文件

      生成bootblock和sign工具所需全部OBJ文件的實際命令包括:

      gcc -Iboot/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Os -nostdinc -c boot/bootasm.S -o obj/boot/bootasm.o
      gcc -Iboot/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Os -nostdinc -c boot/bootmain.c -o obj/boot/bootmain.o
      gcc -Itools/ -g -Wall -O2 -c tools/sign.c -o obj/sign/tools/sign.o
      gcc -g -Wall -O2 obj/sign/tools/sign.o -o bin/sign

      參數及其意義(重復的參數不再列出):

      • -Os:對輸出文件大小進行優化,開啟全部不增加代碼大小的-O2優化
      • -g:以操作系統原生格式輸出調試信息,gdb可以處理這一信息
      • -O2:進行大部分不以空間換時間的優化

      鏈接生成bootblock二進制文件的命令為:

      ld -m    elf_i386 -nostdlib -N -e start -Ttext 0x7C00 obj/boot/bootasm.o obj/boot/bootmain.o -o obj/bootblock.o
      'obj/bootblock.out' size: 488 bytes
      build 512 bytes boot sector: 'bin/bootblock' success!(這兩行是sign的輸出)

      參數及其意義:

        • -N:將文字和數據部分置為可讀寫,不將數據section置為與頁對齊, 不鏈接共享庫
        • -e start:將start符號置為程序起始點
        • -Ttext 0x7C00:鏈接時將".bss"、".data"或".text"置於絕對地址0x7C00

1.2 一個被系統認為是符合規范的硬盤主引導扇區的特征是什么?

tool/sign.c

輸入的主引導扇區記錄小於等於510字節(446+64)

最后兩個字節是0x55AA

練習2:

  使用Qemu和gdb調試lab1 實驗目的:熟悉單步調試gdb方法 進一步了解os啟動流程

練習3:

  bootloader進入保護模式的過程

  BIOS通過讀取硬盤主引導扇區到內存,並跳轉到對應內存中的位置執行bootloader,從實模式轉換到保護模式。

bootloader啟動過程主要工作:1切換到保護模式,啟用分段機制

     2讀磁盤中ELF執行文件格式的ucore到內存

     3顯示字符串信息

     4把控制權交給ucore操作系統

1.開啟A20地址線

2.初始化GDT表

3.進入保護模式


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM