日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

Linux内核——实模式

發布時間:2024/5/8 linux 51 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linux内核——实模式 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 項目目錄
    • 1. 匯編程序的運行條件
      • 1.1 可執行文件
      • 1.2 偏移地址
      • 1.3 硬盤
      • 1.4 代碼段和數據段
      • 1.5 邏輯地址
      • 1.6 物理地址
      • 1.7 cpu 取指
    • 2. x86 虛擬機 bochs 實驗環境
      • 2.1 安裝 bochs
      • 2.2 匯編、鏈接程序
      • 2.3 制作硬盤鏡像文件
      • 2.4 啟動 bochs
      • 2.5 BIOS
    • 3. 匯編程序詳解
      • 3.1 偽指令
      • 3.2 符號
      • 3.3 設置代碼段
      • 3.4 設置數據段
      • 3.5 中斷處理程序
      • 3.6 調用中斷處理程序
      • 3.7 使 cpu 進入死循環
      • 3.8 引導扇區標志

項目目錄

root:[.] +--.DS_Store +--bochsrc.bxrc +--print_tree_file.py +--run.sh +--test1| +--bootsect.s| +--run_test1.sh

1. 匯編程序的運行條件

cpu 只能識別、運行機器指令,無法運行匯編程序 bootsect.s 中的匯編指令,所以只有把匯編程序 bootsect.s 匯編、鏈接生成二進制可執行文件 bootsect.bin ,并將其加載到物理內存后,cpu 才能逐條從物理內存中取指、解析、執行可執行文件 bootsect.bin 中的機器指令。

1.1 可執行文件

我們使用 as 匯編器和 ld 鏈接器把匯編程序 bootsect.s 匯編、鏈接成可執行文件 bootsect.bin。

可執行文件由可以被 cpu 直接運行的機器指令和機器指令運行過程中需要訪問的數據組成。可執行文件 bootsect.bin 如圖1.1所示,機器指令在前面,每個實線方框表示一條指令;數據緊跟在機器指令的后面,每個虛線方框表示一個(組)數據。可執行文件 bootsect.bin 由13條機器指令和3個(組)數據組成,其中,機器指令由匯編文件 bootsect.s 中的匯編指令匯編、鏈接得到,數據由匯編文件 bootsect.s 中的偽指令匯編、鏈接得到。

圖1.1.1 可執行文件bootsect.bin

1.2 偏移地址

可執行文件中的每個字節都有唯一的地址——偏移地址。如圖1.1(1)所示,第一個字節 0xea 的偏移地址為0,每條機器指令和每個(組)數據都有唯一的偏移地址,是它們的第1個字節的偏移地址。第一個實線方框中的機器指令的偏移地址為0,第2個實線方框中的機器指令的偏移地址為5。

表1.2.1 匯編程序bootsect.s

1.3 硬盤

只有把可執行文件加載到物理內存后,cpu才能逐條從物理內存中讀取可執行文件的機器指令,并解析和執行機器指令。但是因為保存在物理內存中的數據在掉電之后會消失,所以需要將可執行文件保存在掉電后數據不會消失的硬盤中。在運行可執行文件之前,再將其從硬盤加載到物理內存。

我們可以把硬盤看做是一個由扇區組成的一維數組,每個扇區大小為512B,其中第一個扇區叫作引導扇區(本書中所有實驗中使用的硬盤大小為1MB,共計2048個扇區,引導扇區的扇區號為0)。

1.4 代碼段和數據段

可執行文件加載到物理內存后,把占用的一段物理內存叫作物理段,每個物理段都有一個屬性:物理段起始地址。將可執行文件 bootsect.bin 加載到物理內存后,占用的物理段的物理地址空間為 0x7c00~0x7dff(512B),物理段的起始地址為0x7c00。

當物理內存中的可執行文件 bootsect.bin 在 cpu 中運行時,把機器指令所在的物理段叫作代碼段,把數據所在的物理段叫作數據段。可執行文件 bootsect.bin 中包含了機器指令和數據,所以代碼段和數據段共用同一個物理段,因此代碼段和數據段起始地址都是 0x7c00。

1.5 邏輯地址

當可執行文件被加載到物理內存的物理段之后,代碼段中的機器指令和數據段中的數據就擁有了邏輯地址。在實模式下,邏輯地址的格式為:[右移4位后的代碼/數據段的物理起始地址:偏移地址]。第一個實線方框中的機器指令的邏輯地址為:[0x7c0:0],第2個實線方框中的機器指令的邏輯地址為[0x7c0:5],第一個虛線方框中的數據邏輯地址為:[0x7c0:0x20],最后一個虛線方框的數據邏輯地址為:[0x7c0:0x1fe]。

1.6 物理地址

物理內存可以看做是一個由字節組成的一維數組,每個字節都有唯一的物理地址。物理內存中的第1個字節的物理地址為0。機器指令/數據的物理地址=代碼/數據段的物理段起始地址+偏移地址

1.7 cpu 取指

cpu 中有2個用于 cpu 從物理內存中讀取機器指令的寄存器:

  • 代碼段寄存器 cs。
  • 機器指令偏移地址寄存器 ip。

寄存器 [cs:ip] 保存了 cpu 下一條需要從物理內存讀取的機器指令的邏輯地址。

2. x86 虛擬機 bochs 實驗環境

2.1 安裝 bochs

在 Ubuntu 18.04 中安裝 x86 虛擬機 bochs 的debugger 版本的命令如下:

sudo apt-get install build-essential libx11-dev xorg-dev libgtk2.0-dev wget https://sourceforge.net/projects/bochs/files/bochs/2.6.8/bochs-2.6.8.tar.gz tar zxvf bochs-2.6.8.tar.gz cd bochs-2.6.8/ ./configure --enable-debugger --enable-disasm --enable-debugger-gui make -j4 sudo make install

2.2 匯編、鏈接程序

as 是匯編器,-o bootsect.o 表示生成的可執行文件的文件名為 bootsect.o。可執行文件 bootsect.o 還需要鏈接才能在 cpu 上運行。

ld 是鏈接器,將 bootsect.o 鏈接成 bootsect.bin。

  • --oformat binary:表示可執行文件 bootsect.bin 中只包含機器指令和數據;
  • -Ttext=0:表示第一條機器指令的偏移地址為0。
  • -o bootsect.bin:表示生成的可執行文件的文件名為 bootsect.bin。

run_test1.sh 程序內容:

# 匯編、鏈接bootsect.bin as -o bootsect.o bootsect.s ld --oformat binary -Ttext=0 -o bootsect.bin bootsect.o# 制作硬盤鏡像文件 dd if=/dev/zero of=../c.img bs=512 count=2048 dd if=bootsect.bin of=../c.img bs=512 seek=0 conv=notrunc

將匯編和鏈接命令集合到 run_test1.sh 程序中,只需要使用 sh run_test1.sh 命令即可實現匯編和鏈接功能。

2.3 制作硬盤鏡像文件

在 bochs 中,需要使用硬盤鏡像文件虛擬物理硬盤。

給上層 test 目錄創建一個大小為 1MB 的硬盤鏡像文件 c.img 的命令:dd if=/dev/zero of=../c.img bs=512 count=2048。

  • dd:文件拷貝命令。
  • if=/dev/zero:表示拷貝的源文件的路徑,dev/zero是一個特殊的文件,可以提供 n(bs*count) 個 0。
  • of=../c.img:表示拷貝的目標文件路徑,若不存在則創建。
  • bs=512:塊的大小,單位為B。
  • count=2048:表示拷貝的文件的塊的數量。

硬盤鏡像文件制作好后,將可執行文件 bootsect.bin 拷貝到硬盤鏡像文件 c.img 的引導扇區的命令:dd if=bootsect.bin of=../c.img bs=512 seek=0 conv=notrunc。

  • seek=0:表示把可執行文件 bootsect.bin 拷貝到硬盤鏡像文件 c.img 的引導扇區。
  • conv=notrunc:表示不改變目標文件的大小,若沒有該項,則硬盤鏡像文件 c.img 的大小會由 1MB 變為可執行文件 bootsect.bin 的大小512B。

2.4 啟動 bochs

“硬盤”制作好后,要想啟動 bochs,還需要一個配置文件(bochsrc.bxrc),文件內容如下:

romimage: file=/usr/local/share/bochs/BIOS-bochs-latest vgaromimage: file=/usr/local/share/bochs/VGABIOS-lgpl-latest ata0-master: type=disk, path="c.img" megs: 16 cpu: count=1 boot: disk
  • romimage:指定 bochs 運行過程中使用 ROM-BIOS 的路徑。
  • vgaromimage:指定 bochs 運行過程中使用的 VGA 的 ROM-BIOS 的路徑。
  • ata0-master:指定硬盤鏡像文件 c.img 的路徑。
  • megs:指定物理內存的大小,單位為MB,bochs 中只有 16MB 物理內存。
  • cpu:指定 cpu 個數,僅有1個cpu。
  • boot:指定啟動方式,硬盤啟動。

run.sh 保存了啟動 bochs 的命令,文件內容如下:

bochs -q -f bochsrc.bxrc
  • -q:跳過 bochs 啟動后的配置界面。
  • -f bochsrc.bxrc:指定配置文件的路徑。

運行sh run.sh 命令后,就相當于我們按下了一臺電腦的開機鍵。bochs 首先進行一些自身的初始化工作,最終在終端輸出如下信息,并等待用戶輸入調試命令。

Next at t=0 (0) [0x0000fffffff0] f000:fff0 (unk. ctxt): jmpf 0xf000:e05b ; ea5be000f0 <bochs:1>
  • 第1行:t 的值表示,cpu 從上電開始已經運行了多少條機器指令。

  • 第2行:cpu 上電后運行的第1條機器指令的信息(數字均為16進制)

    • [0x0000fffffff0]:該機器指令在物理內存中的物理地址,在實模式下,cpu 最多只能訪問 1MB 物理內存,即該機器指令的物理地址為 0xffff0;
    • f000:fff0:當前寄存器[cs:ip]的值,該機器指令的邏輯地址。
    • jmpf 0xf000:e05b:該機器指令對應的匯編指令;
    • ea5be000f0:機器指令的內容。
  • 第3行:用戶輸入調試命令的命令行。

    • 查看 cpu 中寄存器的值:r 命令和 sreg 命令。

    • <bochs:1> reax: 0x00000000 0ecx: 0x00000000 0edx: 0x00000000 0ebx: 0x00000000 0esp: 0x00000000 0ebp: 0x00000000 0esi: 0x00000000 0edi: 0x00000000 0eip: 0x0000fff0eflags 0x00000002: id vip vif ac vm rf nt IOPL=0 of df if tf sf zf af pf cf<bochs:2> sreges:0x0000, dh=0x00009300, dl=0x0000ffff, valid=7Data segment, base=0x00000000, limit=0x0000ffff, Read/Write, Accessedcs:0xf000, dh=0xff0093ff, dl=0x0000ffff, valid=7Data segment, base=0xffff0000, limit=0x0000ffff, Read/Write, Accessedss:0x0000, dh=0x00009300, dl=0x0000ffff, valid=7Data segment, base=0x00000000, limit=0x0000ffff, Read/Write, Accessedds:0x0000, dh=0x00009300, dl=0x0000ffff, valid=7Data segment, base=0x00000000, limit=0x0000ffff, Read/Write, Accessedfs:0x0000, dh=0x00009300, dl=0x0000ffff, valid=7Data segment, base=0x00000000, limit=0x0000ffff, Read/Write, Accessedgs:0x0000, dh=0x00009300, dl=0x0000ffff, valid=7Data segment, base=0x00000000, limit=0x0000ffff, Read/Write, Accessedldtr:0x0000, dh=0x00008200, dl=0x0000ffff, valid=1tr:0x0000, dh=0x00008b00, dl=0x0000ffff, valid=1gdtr:base=0x00000000, limit=0xffffidtr:base=0x00000000, limit=0xffff
    • 打斷點是重要的調試手段之一,bochs 提供了多個打斷點的命令,其中 vb 命令使用邏輯地址打斷點,b 命令使用物理地址打斷點,使用 blist 可以查看所有斷點信息。斷點打好后,使用 c 命令運行程序,當 cpu 下一條即將運行的機器指令被打了斷點時,cpu 停止在該機器指令前,等待輸入新的命令。

    • <bochs:3> vb 0x0:0x7c00<bochs:4> b 0x7c00<bochs:5> blistNum Type Disp Enb Address1 vbreakpoint keep y 0x0000:00007c002 pbreakpoint keep y 0x000000007c00<bochs:6> c00000004661i[BIOS ] $Revision: 12579 $ $Date: 2014-12-26 11:31:39 +0100 (Fr, 26. Dez 2014) $00000318049i[KBD ] reset-disable command received00000320818i[BIOS ] Starting rombios3200000321256i[BIOS ] Shutdown flag 000000321840i[BIOS ] ram_size=0x0100000000000322261i[BIOS ] ram_end=16MB00000362771i[BIOS ] Found 1 cpu(s)00000376975i[BIOS ] bios_table_addr: 0x000fa498 end=0x000fcc0000000704770i[PCI ] i440FX PMC write to PAM register 59 (TLB Flush)00001032699i[P2ISA ] PCI IRQ routing: PIRQA# set to 0x0b00001032718i[P2ISA ] PCI IRQ routing: PIRQB# set to 0x0900001032737i[P2ISA ] PCI IRQ routing: PIRQC# set to 0x0b00001032756i[P2ISA ] PCI IRQ routing: PIRQD# set to 0x0900001032766i[P2ISA ] write: ELCR2 = 0x0a00001033536i[BIOS ] PIIX3/PIIX4 init: elcr=00 0a00001041217i[BIOS ] PCI: bus=0 devfn=0x00: vendor_id=0x8086 device_id=0x1237 class=0x060000001043496i[BIOS ] PCI: bus=0 devfn=0x08: vendor_id=0x8086 device_id=0x7000 class=0x060100001045614i[BIOS ] PCI: bus=0 devfn=0x09: vendor_id=0x8086 device_id=0x7010 class=0x010100001045839i[PIDE ] new BM-DMA address: 0xc00000001046455i[BIOS ] region 4: 0x0000c00000001048489i[BIOS ] PCI: bus=0 devfn=0x0b: vendor_id=0x8086 device_id=0x7113 class=0x068000001048721i[ACPI ] new irq line = 1100001048733i[ACPI ] new irq line = 900001048758i[ACPI ] new PM base address: 0xb00000001048772i[ACPI ] new SM base address: 0xb10000001048800i[PCI ] setting SMRAM control register to 0x4a00001212893i[CPU0 ] Enter to System Management Mode00001212904i[CPU0 ] RSM: Resuming from System Management Mode00001376925i[PCI ] setting SMRAM control register to 0x0a00001391791i[BIOS ] MP table addr=0x000fa570 MPC table addr=0x000fa4a0 size=0xc800001393613i[BIOS ] SMBIOS table addr=0x000fa58000001395781i[BIOS ] ACPI tables: RSDP addr=0x000fa6a0 ACPI DATA addr=0x00ff0000 size=0xf7200001398971i[BIOS ] Firmware waking vector 0xff00cc00001400766i[PCI ] i440FX PMC write to PAM register 59 (TLB Flush)00001401489i[BIOS ] bios_table_cur_addr: 0x000fa6c400001529106i[VBIOS ] VGABios $Id: vgabios.c,v 1.76 2013/02/10 08:07:03 vruppert Exp $00001529177i[BXVGA ] VBE known Display Interface b0c000001529209i[BXVGA ] VBE known Display Interface b0c500001532134i[VBIOS ] VBE Bios $Id: vbe.c,v 1.65 2014/07/08 18:02:25 vruppert Exp $00001570128i[XGUI ] charmap update. Font Height is 1600001856608i[XGUI ] charmap update. Font Height is 1600001876307i[BIOS ] ata0-0: PCHS=2/16/63 translation=none LCHS=2/16/6300005753481i[BIOS ] IDE time out00017844201i[BIOS ] Booting from 0000:7c00(0) Breakpoint 1, in 0000:7c00 (0x00007c00)Next at t=17844256(0) [0x000000007c00] 0000:7c00 (unk. ctxt): jmpf 0x07c0:0005 ; ea0500c007<bochs:7>
    • 使用 u 命令查看 cpu 下一條即將運行的機器指令。

    • <bochs:3> u /500007c00: ( ): jmpf 0x07c0:0005 ; ea0500c00700007c05: ( ): mov ax, 0x0600 ; b8000600007c08: ( ): mov ch, 0x00 ; b50000007c0a: ( ): mov cl, 0x00 ; b10000007c0c: ( ): mov dh, 0x18 ; b618
    • 使用 xp 命令可以查看物理內存中的指定物理地址的內容。查看物理內存 0x7dfe 開始的2個字節的內容。

    • /2bx:打印2個字節(參數b為1個字節,還有h、w)

      /13c:將13個字節作為 ASCII 碼對應的字符打印出來

    • <bochs:4> xp /2bx 0x7dfe[bochs]:0x00007dfe <bogus+ 0>: 0x55 0xaa
    • 使用 n 命令讓 cpu 運行一條機器指令后,停止并等待輸入新的命令。

    • <bochs:5> nNext at t=17844257(0) [0x000000007c05] 07c0:0005 (unk. ctxt): mov ax, 0x0600 ; b80006
    • 使用 xp 命令查看中斷向量表中的 0x10 號中斷處理程序的入口邏輯地址。

    • <bochs:6> xp /1wx 0x40[bochs]:0x00000040 <bogus+ 0>: 0xc0000152

2.5 BIOS

x86 架構的 cpu 在上電后處于實模式,在實模式下,cpu 最多只能訪問 1MB 物理內存,其中 BIOS 占用的物理段的物理地址空間為:0xc0000~0xfffff。cpu 上電后,運行的第1條機器指令的物理地址為 0xffff0,該物理地址正好位于 BIOS 占用的物理段內,因此 cpu 上電后首先運行 BIOS。

BIOS 主要工作:

  • 檢測、初始化系統中的硬件。如顯示器、硬盤等。
  • 創建中斷系統。在 1MB 物理內存的前 1KB 物理地址空間內初始化中斷向量表,在最后 256KB 物理地址空間內保存中斷處理程序。
  • 將引導扇區中的可執行文件 bootsect.bin 拷貝到物理地址空間為 0x7c00~0x7dff 的物理內存中的物理段中。
  • 將寄存器 cs 和 ip 分別賦值為 0x0和 0x7c00,因此 cpu 下一條運行的機器指令的物理地址為 0x7c00,即可執行文件 bootsect.bin 的第1條機器指令。
  • BIOS 運行完畢后,內存狀態為:

    圖2.5.1 1MB 物理內存空間

    3. 匯編程序詳解

    代碼清單(test1/bootsect.s) .code16 BOOTSEG = 0x7c0ljmp $BOOTSEG, $go go:movw %cs, %axmovw %ax, %dsmovw %ax, %esmovw $msg, %bpmovb $0x13, %ahmovb $0x01, %almovb $2, %blmovw msg_len, %cxmovb $0, %dhmovb $0, %dlint $0x10jmp . msg:.ascii "hello, world." msg_len:.word . - msg.org 0x1fe.word 0xaa55

    3.1 偽指令

    在匯編程序中,以.開頭的匯編語句叫作偽指令,匯編器 as 不會把偽指令匯編成機器指令。

    • .code16:在實模式下,cpu 只能運行16位的機器指令,該偽指令的作用是:告訴匯編器,把匯編程序 bootsect.s 中的匯編、鏈接為16位的機器指令。
    • .ascii "hello, world.":在可執行文件 bootsect.bin 中的偏移地址空間 0x20~0x2c 中定義字符串“hello,world.”。
    • .word . - msg:在可執行文件 bootsect.bin 中的偏移地址空間 0x2d~0x2e 中定義一個2字節大小的數據(x86架構中使用小端模式,低字節存放在物理內存的低地址字節)。
    • .org 0x1fe:將第22行偽指令對應的數據在可執行文件 bootsect.bin 中的偏移地址設置為 0x1fe,若不是用該偽指令,則第22行偽指令對應的數據的偏移地址為 0x2f,并將可執行文件 bootsect.bin 中偏移地址 0x2f~0x1fd 中的內容用0填充。

    3.2 符號

    在匯編程序中,使用符號表示一個數,有兩種方式:

    • 使用=表示。如代碼清單第2行所示,符號 BOOTSEG 值為 0x7c0。
    • 使用:表示。則符號表示=后面的匯編語句對應的機器指令或數據在可執行文件中的偏移地址。符號 go 的值為 0x5,符號 msg 的值為 0x20。

    在將匯編程序 bootsect.s 匯編為可執行文件 bootsect.o 的過程中,匯編器 as 首先把匯編程序 bootsect.s 中所有的符號用其表示的數替換。

    3.3 設置代碼段

    機器指令的邏輯地址和物理地址是多對一的關系,即一個物理地址可以由多個邏輯地址計算得到。

    BIOS 把bootsect.bin 從引導扇區加載到物理內存的物理地址空間 0x7c00~0x7dff 后,將寄存器 [cs:ip] 賦值為可執行文件 bootsect.bin 的第一條機器指令的邏輯地址 [0x0:0x7c00],代碼段和數據段的物理起始地址為 0。當 cpu 運行 可執行文件 bootsect.bin 時,代碼段的物理起始地址為 0x7c00,故可執行文件 bootsect.bin 的第一條機器指令需要對寄存器 [cs:ip] 重新賦值。

    ljmp 匯編指令的作用是為寄存器 [cs:ip] 賦值,在匯編指令中寄存器前加 % 。

    3.4 設置數據段

    通常代碼段設置完成后,必須設置數據段。在實模式下,cpu 中除了用于保存代碼段的物理段起始地址右移4位的寄存器 cs 外,還有用于保存數據段的物理段起始地址右移 4 位的寄存器——數據段寄存器 ds 和數據段寄存器 es。

    cpu 運行可執行文件 bootsect.bin 時,代碼段和數據段的物理段起始地址都為 0x7c00,所以只需要將寄存器 cs 的值賦給寄存器 ds 和寄存器 es 即可,如代碼清單5~7行所示,不能將一個段寄存器的值直接賦給另外一個段寄存器

    每條 mov 匯編指令都有一個后綴:

    • b:賦值給寄存器的數據大小為1個字節;
    • w:賦值給寄存器的數據大小為2個字節;
    • l:賦值給寄存器的數據大小為4個字節;

    3.5 中斷處理程序

    BIOS 在創建中斷系統時,在 1MB 物理內存的最后 256KB 物理地址空間內保存了大量的中斷處理程序。這些中斷處理程序用于訪問系統中已有的硬件,訪問不同的硬件需要調用不同的中斷處理程序,每個中斷處理程序都有唯一的編號——中斷號。

    常用中斷號舉例:

    • 0x10:往顯示器的屏幕上打印字符。
    • 0x13:從硬盤讀取數據。

    調用中斷處理程序前,需要借助 cpu 中的寄存器傳遞參數。例如:調用 0x10 中斷處理程序往顯示器的屏幕上打印字符前,需要給 0x10 號中斷處理程序傳遞參數,告訴它在屏幕的什么位置顯示什么內容,內容的長度以及屬性。

    • 寄存器 ah:0x13 表示向屏幕打印字符串。

    • 寄存器[es:bp]:保存字符串的首字符在數據段中的邏輯地址。

    • 寄存器 cs:保存字符串的長度。

    • 寄存器 (dh, dl):字符串在屏幕上的起始坐標,寄存器 dh 為行號(0~24),寄存器 dl 為列號(0~79)。

    • 寄存器 al:指定光標和字符的屬性。

      • 0:表示字符的屬性保存在寄存器 bl 中,光標停留在字符串的首字符
      • 1:表示字符的屬性保存在寄存器 bl 中,光標停留在字符串的尾字符
      • 2:表示字符的屬性緊跟在字符之后,光標停留在字符串的首字符
      • 3:表示字符的屬性緊跟在字符之后,光標停留在字符串的尾字符
    • 寄存器 bl:若寄存器 al 的值為 0 或者 1,保存字符的屬性值。

      • 字符屬性:

      • 字符和背景顏色對照表:

      二進制顏色二進制顏色
      0000黑色1000灰色
      0001藍色1001淡藍色
      0010綠色1010淡綠色
      0011青色1011淡青色
      0100紅色1100淡紅色
      0101紫紅色1101淡紫紅色
      0110棕色1110黃色
      0111銀色1111白色

    使用 mov 指令賦值:

  • 數據在寄存器中。如代碼第7行所示。
  • 數據在機器指令中。如代碼第8行所示。將 $ 后面的數字 0x20 (符號 msg 的值)賦值給寄存器 bp。
  • 數據在內存中。如果符號前沒有 $ ,則說明用來賦值的數據保存在物理內存中,而非偏移地址(符號的值)。類似于 cpu 將寄存器 [cs:ip] 中的機器指令的邏輯地址轉換為物理地址后,使用物理地址從物理內存中讀取機器指令,cpu 也將數據的邏輯地址轉換為物理地址后,通過物理地址從物理內存中讀取數據,不同之處是:1. 機器指令的邏輯地址中的段起始地址右移4位的值保存在代碼段寄存器 cs,而數據的邏輯地址中的段起始地址右移4位的值默認保存在數據段寄存器 ds 中;2. 機器指令的邏輯地址中的偏移地址保存在寄存器 ip 中,而數據的邏輯地址中的偏移地址,通常由機器指令提供。如代碼12行所示,將字符串“hello, world.”的長度13賦值給寄存器cx。
  • 3.6 調用中斷處理程序

    設置好為 0x10 號中斷處理程序傳遞參數的寄存器后,在匯編程序 bootsect.s 使用 int 匯編指令調用 0x10 號中斷處理程序,cpu 執行第15行匯編指令對應的機器指令的過程如下:

  • 將當前寄存器 [cs:ip] 中的邏輯地址(第16行匯編指令)保存起來。

  • 將 0x10 號中斷處理程序的入口邏輯地址加載到寄存器[cs:ip]之中。每個中斷處理程序的入口邏輯地址都保存在中斷向量表中。中斷處理程序的入口邏輯地址按照中斷號依次存放在中斷向量表中,可以通過 0x10 號中斷處理程序的中斷號 0x10 從中斷向量表中獲取 0x10 中斷處理程序的入口邏輯地址[0xc000:0x152],將入口邏輯地址賦值給寄存器[cs:ip]后,cpu下一條運行的是 0x10 號中斷處理程序的第1條指令,物理地址為0xc0152。

  • 圖 3.6.1 0x10 號中斷處理程序調用過程
  • 運行 0x10 號中斷處理程序。

  • 將 cpu 保存的第16行匯編指令對應的機器指令的邏輯地址,重新賦值給 [cs:ip],因此 cpu 重新進入 bootsect.bin 中運行。

  • 3.7 使 cpu 進入死循環

    因為 cpu 會不停地根據寄存器 [cs:ip] 中的邏輯地址轉換后的物理地址,從物理內存中讀取機器指令,然后對其解析、執行,因此需要一條讓 cpu 進入死循環的機器指令作為可執行文件的最后一條機器指令,如代碼第16行所示,與 ljmp 不同的是,jmp 只給寄存器 ip 賦值。cpu 會一直循環運行第 16 行指令,不會將第1個虛線方框中的部分數據看做機器指令,進行取指、解析、執行。

    3.8 引導扇區標志

    BIOS 會將引導扇區中的可執行文件拷貝到物理內存,但是在拷貝前,會檢查引導扇區中的可執行文件 bootsect.bin 的最后兩個字節的值是不是0x55和0xaa,若不是,則 BIOS 不會拷貝。

    總結

    以上是生活随笔為你收集整理的Linux内核——实模式的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。