設(shè)置
  • 日夜間
    隨系統(tǒng)
    淺色
    深色
  • 主題色

Linux 0.11 第 2 回 | 從 0x7c00 到 0x9000

低并發(fā)編程 2022/9/30 20:02:30 責(zé)編:子非

本文來自微信公眾號(hào):低并發(fā)編程 (ID:dibingfa),作者:閃客

書接上回,上回書咱們說到,CPU 執(zhí)行操作系統(tǒng)的最開始的兩行代碼。

mov ax,0x07c0
mov ds,ax

將數(shù)據(jù)段寄存器 ds 的值變成了 0x07c0,方便了之后訪問內(nèi)存時(shí)利用這個(gè)段基址進(jìn)行尋址。

接下來我們帶著這兩行代碼,繼續(xù)往下看幾行。

mov ax,0x07c0
mov ds,ax
mov ax,0x9000
mov es,ax
mov cx,#256
sub si,si
sub di,di
rep movw

此時(shí) ds 寄存器的值已經(jīng)是 0x07c0 了,然后又通過同樣的方式將 es 寄存器的值變成 0x9000,接著又把 cx 寄存器的值變成 256(代碼里確實(shí)是用十進(jìn)制表示的,與其他地方有些不一致,不過無(wú)所謂)。

再往下看有兩個(gè) sub 指令,這個(gè) sub 指令很簡(jiǎn)單,比如

sub a,b

就表示

a = a - b

那么代碼中的

sub si,si

就表示

si = si - si

所以如果 sub 后面的兩個(gè)寄存器一模一樣,就相當(dāng)于把這個(gè)寄存器里的值清零,這是一個(gè)基本玩法。

那就非常簡(jiǎn)單了,經(jīng)過這些指令后,以下幾個(gè)寄存器分別被附上了指定的值,我們梳理一下。

ds = 0x07c0

es = 0x9000

cx = 256

si = 0

di = 0

還記得上一講畫的 CPU 寄存器的總圖么?此時(shí)就是這樣了

干嘛要給這些毫不相干的寄存器附上值呢?其實(shí)就是為下一條指令服務(wù)的,就是

rep movw

其中 rep 表示重復(fù)執(zhí)行后面的指令。

而后面的指令 movw 表示復(fù)制一個(gè)(word 16 位),那其實(shí)就是不斷重復(fù)地復(fù)制一個(gè)字。

那下面自然就有三連問:

重復(fù)執(zhí)行多少次呢?是 cx 寄存器中的值,也就是 256 次。

從哪復(fù)制到哪呢?是從 ds:si 處復(fù)制到 es:di 處。

一次復(fù)制多少呢?剛剛說過了,復(fù)制一個(gè)字,16 位,也就是兩個(gè)字節(jié)。

上面是直譯,那把這段話翻譯成更人話的方式講出來就是,將內(nèi)存地址 0x7c00 處開始往后的 512 字節(jié)的數(shù)據(jù),原封不動(dòng)復(fù)制到 0x90000 處。

就是下圖的第二步。

沒錯(cuò),就是這么折騰了一下?,F(xiàn)在,操作系統(tǒng)最開頭的代碼,已經(jīng)被挪到了 0x90000 這個(gè)位置了。

再往后是一個(gè)跳轉(zhuǎn)指令。

jmpi go,0x9000
 
  mov ax,cs
  mov ds,ax

仔細(xì)想想或許你能猜到它想干嘛。

jmpi 是一個(gè)段間跳轉(zhuǎn)指令,表示跳轉(zhuǎn)到 0x9000:go 處執(zhí)行。

還記得上一講說的 段基址: 偏移地址 這種格式的內(nèi)存地址要如何計(jì)算吧?段基址仍然要先左移四位,因此結(jié)論就是跳轉(zhuǎn)到 0x90000 + go 這個(gè)內(nèi)存地址處執(zhí)行。忘記的趕緊回去看看,這才過了一回哦,要穩(wěn)扎穩(wěn)打。

再說 go,go 就是一個(gè)標(biāo)簽,最終編譯成機(jī)器碼的時(shí)候會(huì)被翻譯成一個(gè)值,這個(gè)值就是 go 這個(gè)標(biāo)簽在文件內(nèi)的偏移地址。

這個(gè)偏移地址再加上 0x90000,就剛好是 go 標(biāo)簽后面那段代碼 mov ax,cs 此時(shí)所在的內(nèi)存地址了。

那假如 mov ax,cx 這行代碼位于最終編譯好后的二進(jìn)制文件的 0x08 處,那 go 就等于 0x08,而最終 CPU 跳轉(zhuǎn)到的地址就是 0x90008 處。

所以到此為止,前兩回的內(nèi)容,其實(shí)就是一段 512 字節(jié)的代碼和數(shù)據(jù),從硬盤的啟動(dòng)區(qū)先是被移動(dòng)到了內(nèi)存 0x7c00 處,然后又立刻被移動(dòng)到 0x90000 處,并且跳轉(zhuǎn)到此處往后再稍稍偏移 go 這個(gè)標(biāo)簽所代表的偏移地址處,也就是 mov ax,cs 這行指令的位置。

仍然是保持每回的簡(jiǎn)潔,本文就講到這里,希望大家還跟得上,接下來的下一回,我們就把目光定位到 go 標(biāo)簽處往后的代碼,看看他又要折騰些什么吧。

后面的世界越來越精彩,欲知后事如何,且聽下回分解。

廣告聲明:文內(nèi)含有的對(duì)外跳轉(zhuǎn)鏈接(包括不限于超鏈接、二維碼、口令等形式),用于傳遞更多信息,節(jié)省甄選時(shí)間,結(jié)果僅供參考,IT之家所有文章均包含本聲明。

相關(guān)文章

關(guān)鍵詞:Linux,linux

軟媒旗下網(wǎng)站: IT之家 最會(huì)買 - 返利返現(xiàn)優(yōu)惠券 iPhone之家 Win7之家 Win10之家 Win11之家

軟媒旗下軟件: 軟媒手機(jī)APP應(yīng)用 魔方 最會(huì)買 要知