bootsect.s文件阅读问题集
 ? 這個(gè)是我學(xué)習(xí)bootsect.s文件時(shí),看完了本版關(guān)于bootsect文件后匯集了一下。 
 有些問題實(shí)在是書上很明顯的地方,我就沒有摘錄上去
 有些問題實(shí)在和bootsect這個(gè)代碼沒有關(guān)系,我也沒有摘錄上去 
都是大家問的問題,也是自己最想問的問題。我看了幾遍依然還是有很多問題。
 其實(shí)很多問題,以前大家都問過了,確實(shí)是這樣的。 
查閱很方便,都是按照行號來的!
 ---------------------------------------- 
關(guān)于bootsect.s中出現(xiàn)的移位指令
 -------------------------------------------------------
 操作數(shù)的長度用加在指令后的符號表示b(byte, 8-bit), w(word, 16-bits), l(long, 32-bits),如“movb %al, %bl”,“movw %ax, %bx”,“movl %eax, %ebx ”。 
如果沒有指定操作數(shù)長度的話,編譯器將按照目標(biāo)操作數(shù)的長度來設(shè)置。
 比如指令“mov %ax, %bx”,由于目標(biāo)操作數(shù)bx的長度為word,那么編譯器將把此指令等同于“movw %ax, %bx”,指令“mov $4, %ebx”等同于指令“movl $4, %ebx”,“push %al”等同于“pushb %al”。 
對于沒有指定操作數(shù)長度,但編譯器又無法猜測的指令,編譯器將會報(bào)錯,比如指令“push $4”。
 ====================================== 
L25 .globl begtext,begdata,begbbs,endtext,enddata,endbbs
 L26 .text
 L27 begintext:
 L28 .data
 L29 begdata:
 L30 .bss
 L31 begbbs:
 L32 .text
 ...
 .....
 .......
 L255 .text
 L256 endtext:
 L257 .data
 L258 enddata:
 L259 .bss
 L260 endbbs: 
Q:
 可以看出.text .data .bss重疊的,我的疑問是在模塊連接時(shí),.text 和其他模塊的.text合并,.data和其他模塊的.data合并,那不會出現(xiàn)問題?
 還有就是語法問題,為什么.text會出現(xiàn)3次?
 -------------------------------------------------------------------------------
 A:
 重疊段的用法通常只用于單個(gè)文件。
 前后兩個(gè).text開始text段并起定義段“標(biāo)號”的用途,這樣在帶符號調(diào)試時(shí)可以分清。bootsect和setup都單獨(dú)編譯鏈接,不與其他目標(biāo)文件合并。在組建內(nèi)核Image文件時(shí),tools/build.c文件會直接把他們?nèi)コ髯缘念^結(jié)構(gòu)后順序組合在一起。.text就定義其后面的代碼在.text段中。若后面又出現(xiàn)其他.XXXX,則表示.XXXX后面開始是XXXXX段中的代碼或數(shù)據(jù)。
 ########################################################################### 
最近我在學(xué)習(xí)as匯編,了解了分段方面的知識。但在閱讀bootsect.s文件時(shí)產(chǎn)生了疑問
 整個(gè)文件的結(jié)構(gòu)是這樣的
 .globl begtext,begdata,begbbs,endtext,enddata,endbbs
 .text
 begintext:
 .data
 begdata:
 .bss
 begbbs:
 .text
 ...
 .....
 .......
 .text
 endtext:
 .data
 enddata:
 .bss
 endbbs:
 Q:我不理解這種分段的方法,難道linus為了把代碼段和數(shù)據(jù)段編譯在一個(gè)段內(nèi)?
 即便如此,為什么最后還要有endtext等標(biāo)示符?
 -----------------------------------------------------------
 A: bootsect程序都統(tǒng)統(tǒng)放在512字節(jié)之內(nèi)。在這么小的地方?jīng)]有必要分離各個(gè)sections。
 標(biāo)號begtext和endtext可分別用來指明text段的開始和結(jié)束。 
##########################################################################
 25 .globl begtext, begdata, begbss, endtext, enddata, endbss
 26 .text
 27 begtext:
 28 .data
 29 begdata:
 30 .bss
 31 begbss:
 32 .text 
Q:我看了一下MASM的語法,然后又看了一下as86的幫助,但是不知道上面幾句話到底起什么作用,在MASM中有定義段的語句,正好對應(yīng)段寄存器,as86的幫助上說.text,.data是置當(dāng)前段(set current segment)我想跟MASM中的某些語句相當(dāng),但是.text和.bss對應(yīng)什么段寄存器呢?另外as86中好像沒有看到像MASM那樣在源代碼中分段,是不是as86在匯編的時(shí)候自動根據(jù)源代碼來劃分相應(yīng)段?
A:這些偽指令是供編譯器使用的。這些標(biāo)號供ld86使用。
 .text指明程序中的代碼段;.data是數(shù)據(jù)段;.bss是未初始化的數(shù)據(jù)區(qū)。 
 注意,上面的“段”的含義并不是段寄存器的意思,它只是指明目標(biāo)文件或執(zhí)行文件中的代碼或數(shù)據(jù)區(qū)(塊)。其中對于硬盤上的執(zhí)行文件來講不含bss,只有到了執(zhí)行文件被加載到內(nèi)存中時(shí)才會為其分配bss段(區(qū)),并且位于data段的后面。 
 鏈接程序(例如ld)會使用這些偽指令把所有鏈接模塊中的這些段都分別組合在一起,從而在輸出文件中形成已經(jīng)組合過的代碼和數(shù)據(jù)部分。這方面的內(nèi)容可以參考: 
 http://www.oldlinux.org/cgi-bin/LB5000XP/topic.cgi?forum=1&topic=1139&show=25 
########################################################################
 Q: 在啟動的文件中定義的幾個(gè)globl變量沒有使用是不是可以不要啊
 我在閱讀過程中看不出這幾個(gè)globl變量有什么用啊 
 ----------------------------------------------------------------------
 A: 一般情況下或者需要使用你自己指定的全局變量時(shí)不能不要.global。但是我你的所有段都是重疊的并且不使用除了鏈接器使用的幾個(gè)全局變量時(shí),就可以省略它們。例如,你可以把bootsect.s和setup.s中的.global定義都去掉。
 ####################################################################### 
Q:下面代碼和上面代碼的效果等價(jià)么?
 .globl begtext,begdata,begbbs,endtext,enddata,endbbs
 .text
 begintext:
 begdata:
 begbbs:
 ...
 .....
 .......
 endtext:
 enddata:
 endbbs: 
A: 你還需要在.text后給出.data、.bss
==============================================================================
 3.
 L43? ROOT_DEV=0X306 !指定文件系統(tǒng)設(shè)備是第2個(gè)硬盤的第一個(gè)分區(qū)。
 Q:
 如果內(nèi)核程序和文件系統(tǒng)安裝在同一個(gè)硬盤里時(shí),是否需要把ROOT_DEV=0X301 /dev/hda1?換成第一個(gè)硬盤的第一個(gè)分區(qū).
 還有程序中l(wèi)oad setup、取每個(gè)磁道扇區(qū)數(shù)等時(shí),也需要把驅(qū)動器號改成讀硬盤標(biāo)識? 
 A:
 1. 如果要安裝在同一個(gè)分區(qū)中,那么就需要使用專用獨(dú)立的能從文件系統(tǒng)中取得內(nèi)核Image文件并加載的引導(dǎo)軟件。例如,shoelace,grub,lilo等。本站有人已經(jīng)自己做了一個(gè)專門的。請參考第2個(gè)分論壇中(精華區(qū))。 
 2. 你說的沒錯。很多(基本上全部:)都沒用,可刪除。不過從這點(diǎn)可以看出Linus當(dāng)時(shí)也在不斷學(xué)習(xí)其他人的東東
 L43? ROOT_DEV = 0x306?? ! 0x306-/dev/hd6-第2個(gè)硬盤的第1個(gè)分區(qū)
 Q:
 為什么ROOT_DEV要指向第2個(gè)硬盤的第1個(gè)分區(qū),而不是第一個(gè)硬盤或者其他分區(qū)?有什么特別的道理嗎?
 A:
 因?yàn)楫?dāng)時(shí)Linus的機(jī)器上有兩個(gè)硬盤,而他使用第2個(gè)硬盤來開發(fā)Linux系統(tǒng),第1個(gè)硬盤上安裝的是MINIX系統(tǒng)。 
==============================================================================
L51?? mov cx #256
 ?????? sub si si
 ?????? sub di di 
 ?????? rep
 ?????? movw
 Q:
 將bootsect.s的模塊移到0x90200處,請問怎么知道bootsect.s匯編好后是256個(gè)字?
 A:
 在bootsect.s最后有:
 249L? .org 508
 表示249行后面的代碼從508個(gè)字節(jié)處開始,再往下:
 .word ROOT_DEV
 .word 0xAA55
 共4個(gè)字節(jié),所以整個(gè)文件大小就是508+4=512個(gè)字節(jié)。
 Linus在這里用了.org也可以采用填充0的方法,不論怎樣,總要使512字節(jié)的最后兩個(gè)字節(jié) 是55 AA(用word表是就是AA55了) 
==============================================================================
 L56 jmpi go,INITSEG
 L57 go: mov ax,cs 
 jmpi的語法是jmpi 段值,段內(nèi)偏移
 Q:
 在匯編里好象標(biāo)號指的是段內(nèi)偏移,所以此處的標(biāo)號go應(yīng)該是一個(gè)段內(nèi)偏移,感覺是不是有點(diǎn)問題啊??
 A:
 “jmpi的語法是jmpi 段值,段內(nèi)偏移”--沒錯,這是as86的語法。 
==============================================================================
 L77? j?? load_setup
 Q:
 是否應(yīng)為:? jmp load_Setup?
 A:
 不是印刷錯誤,LD86中就有j這條指令,等價(jià)于JMP 
==============================================================================
 L81 <注釋> 利用INT 0x13的第8號子功能讀取磁盤驅(qū)動器參數(shù),入口參數(shù)ah=0x08,dl=驅(qū)動器號(如果是硬盤則要置位7為1)
 Q:
 驅(qū)動器號是誰分配的,又是怎么分配的,為啥硬盤要置位7為1?
 A: 
 是IBM PC機(jī)BIOS就這樣規(guī)定設(shè)計(jì)的。 
==============================================================================
 L87 seg cs? !表示下一條語句的操作數(shù)在cs段寄存器所指的段中
 Q:
 在bootsect.s中定義了sectors, root_dev, sread,head,track等標(biāo)志符,但是在操作數(shù)中含有sectors, root_dev時(shí),需要seg cs, 而操作數(shù)含有sread,head,track時(shí),之前卻不用加seg cs,why?
 A:
 你仔細(xì)看一下會發(fā)現(xiàn),其實(shí)所有"seg cs"指令都無用。因?yàn)檫@個(gè)程序被連接在一個(gè)段中,即代碼、數(shù)據(jù)段都在一起。Linus當(dāng)時(shí)開發(fā)時(shí)所用的讀盤程序可能是單獨(dú)編寫的,或者是從網(wǎng)上下載后修改的。 
 L87? seg cs
 L88? mov sectors,cx 
 Q:
 語句的意思很好理解,但是這時(shí)DS與CS段是一樣的,是否這里不加87行語句也是可以的呢? 
 A:
 seg cs可以不用。 
==============================================================================
 L94 mov ah,0x03
 L95xor bh,bh
 L96int ox10
 A:
 第94到96行的語句,是否是顯示串前必須做的呢?我以前在核心的代碼里加調(diào)試語句時(shí)是沒有先讀光標(biāo)位置的。是否是第一次顯示時(shí)讀一次就可以了
 Q:
 94-96是必須的。用于設(shè)置int 0x10調(diào)用功能0x13使用的行列值(dx中,串開始位置)。 
 若調(diào)用串顯示函數(shù)時(shí)al的最低比特位=1(al=1或3),則光標(biāo)會在顯示串后被設(shè)置在串的結(jié)尾處。否則若al=0或2,則在顯示后光標(biāo)位置不動 
==============================================================================
 L99 mov bx,#0x0007? !page 0,attribute 7 (normal)
 Q:bl=0x07,有什么作用?
 A:這是顯示參數(shù),請參考VGA顯示卡資料。 
==============================================================================
 L153? test ax,#0x0fff
 Q:
 (1)#0x0fff為啥不是#0x1000呢?
 (2)這一步是不是多余呀,因?yàn)閍x肯定是0x1000,為什么還要測試?出了什么錯才會導(dǎo)致ax和es不等于0x1000?
 A:
 (1)TEST指令:兩操作數(shù)相與不保存結(jié)果,只保存特征條件碼(影響Flag標(biāo)志)。
 這句測試所有三個(gè)0xf代表的12個(gè)比特位應(yīng)該都為零。若都為0則段值肯定是0xN000,對應(yīng)段的地址肯定是0xN0000,也即位于64KB邊界上。
 (2)因?yàn)檫@是個(gè)子程序,它有自己的接口要求。加上這種判斷是良好的編程習(xí)慣 
==============================================================================
 L170xor ax,ax? 
 L171sub ax,bx
 L172shr ax,#9 
Q:
 170行的代碼有疑問,程序跳轉(zhuǎn)到read_it 子程序里時(shí),要完成把磁盤里的數(shù)據(jù)讀入到內(nèi)存中0x10000地址開始的區(qū)域中,整個(gè)讀的過程是先檢測本磁道中剩下的扇區(qū)所包含的字節(jié)總數(shù)是不是可以完全放到當(dāng)前的64K內(nèi)存段里,如果當(dāng)前的64K內(nèi)存段里放不下,就會執(zhí)行到170行這個(gè)地方,170行來了句
 xor ax,ax? 
 sub ax,bx
 shr ax,#9
 這幾行代碼是想獲得可以讀到當(dāng)前的64K內(nèi)存段的扇區(qū)個(gè)數(shù),存放在al里
 對這個(gè)地方,我有一點(diǎn)不解,如果是第一次讀,bx就應(yīng)該是0了,那ax也是0,結(jié)果最后al里面也是0了,那下面緊接著就調(diào)用INT 13號中斷讀磁盤,al 在13號中斷里的含義是從磁盤讀出的扇區(qū)的個(gè)數(shù),當(dāng)al=0時(shí),不知道這個(gè)中斷是怎么執(zhí)行的??
 我查了手冊,手冊上也沒講INT 13號中斷的2號子功能調(diào)用,在當(dāng)al=0時(shí)調(diào)用的結(jié)果是什么,手冊上只是說了,al的值在1-128之間是有效的,我就不知道上面講的那種情況INT 13號中斷是怎么處理的了?
 A:
 第1次讀時(shí)bx確實(shí)是0,但ax不是0。因?yàn)閟read最初是1+SETUPLEN,即5。因此(80 - 5)*512 = 38400 = 37.5KB 沒有超過64KB,所以第1次不會執(zhí)行170行開始的代碼。由于16位寄存器最大只能表示64KB -1,因此這里0表示最大值64KB(已進(jìn)位)。
 軟盤上一個(gè)磁道上有80個(gè)扇區(qū),硬盤上一個(gè)磁道上最多有63個(gè)扇區(qū),
 這樣的話,一個(gè)磁道上的字節(jié)總數(shù)是肯定小于64K的,也就是說不會出現(xiàn),第一次讀磁盤就執(zhí)行到 170行處的:
 xor ax,ax
 sub ax,bx
 shr ax,#9 
 ============================================================================== 
L180mov ax,#1
 L181sub ax,head
 L182jne ok4_read
 L183inc track
 Q:
 當(dāng)0磁頭的當(dāng)前道沒有數(shù)據(jù)可讀后則去讀1磁頭上的數(shù)據(jù),想問這種情況是適用于哪種軟驅(qū)的?我想過去是個(gè)雙面軟驅(qū)。如果不是雙面軟驅(qū),則在read_track里則會死循環(huán)吧。
 A:
 PC機(jī)使用的軟盤驅(qū)動器都是雙頭(雙面)的。沒有見過哪種PC機(jī)用的的是單面的 
==============================================================================
 read_track:
 199???????? push ax
 200???????? push bx
 201???????? push cx
 202???????? push dx
 203???????? mov dx,track
 204???????? mov cx,sread
 205???????? inc cx
 206???????? mov ch,dl
 207???????? mov dx,head
 208???????? mov dh,dl
 209???????? mov dl,#0
 210???????? and dx,#0x0100
 211???????? mov ah,#2
 212???????? int 0x13
 213???????? jc bad_rt <--我用Bochs返匯編出來的是jb... 這個(gè)是不是代碼錯了?
 214???????? pop dx
 215???????? pop cx
 216???????? pop bx
 217???????? pop ax
 218???????? ret 
Q:
 (1)是不是因?yàn)長inux0.11每個(gè)段就給了64KB得長度限制?
 (2)還有就是bootsect.c里面read_it這部分,jc bad_rt <--我用Bochs返匯編出來的是jb... 這個(gè)是不是代碼錯了?
 A:
 沒有限制在64KB,而是每次讀時(shí)最多64KB。 
 另外,查一下手冊看看jb 是否就是 jc 。 
 ?
 ?
 ?
 ?
 
總結(jié)
以上是生活随笔為你收集整理的bootsect.s文件阅读问题集的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: 区分那些是属于构架方面的C++功能
- 下一篇: __VA_ARGS__宏
