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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

调用门

發布時間:2025/6/15 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 调用门 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

門,顧名思義它是一扇門通向令一個地方,看一下門的結構里面有一個描述符和一個偏移值,門中定義了這扇門通向的目的地,當我們調用一個門的時候會到達這個地方:

門中的選擇子:門中的偏移值,也即下圖的selector:offset

這是我們代碼中國定義的門的數據結構:

#define Gate(Selector,Offset,PCount,Attr)\
.2byte (Offset&0xffff);\
.2byte (Selector);\
.2byte (PCount&0x1f)|((Attr<<8)&0xff00);\
.2byte ((Offset>>16)&0xffff)

?

假設Selector_Gate_Call是調用門的描述符,執行lcall $Selector_Gate_Call,$0語句時偏移值($0)無意義,執行此語句后

CS=調用門中的選擇子
IP=調用門中偏移值
CS:IP=全局描述符表中第(調用門中的選擇子>>3)項描述符給出的段基址+調用門中偏移值


調用門的使用

定義調用門的描述符和選擇子,如下面代碼

/*門描述符*/
Descriptor_Gate_Call:Gate(Selector_Code_Gate,0,0,(DA_386CGate+DA_PL0))

/*調用門選擇子*/
.set?Selector_Gate_Call,(Descriptor_Gate_Call-GDT_START)

?

其中調用門中的選擇子和描述符如下:

Descriptor_CODE_GATE:Descriptor(0x0,CodeGLen,DA_C+DA_32)

.set? Selector_Code_Gate,(Descriptor_CODE_GATE-GDT_START)

?

Descriptor_CODE_GATE的初始化和代碼段如下:

InitDescrptor(Descriptor_CODE_GATE,LABEL_CODE_G);

LABEL_CODE_G:?

??? movl $((80*12+0)*2),%edi/*第10行,0列*/?
??? movb $0x0c,%ah/*高四位0000表示黑底,低四位1100表示紅字*/?
??? movb $'G',%al/*要顯示的字符*/?
??? movw %ax,%gs:(%edi)????
jmp .
?.set CodeGLen,(. - LABEL_CODE_G)

?

這時lcall $Selector_Gate_Call,$0就會看到紅色的'G’打印出來,和ljmp Selector_Code_Gate,$0的效果是一樣的,但是這并不是多此一舉的,這涉及的特權級轉換的問題,這里我們先不關心這些。

?

/*初始全局描述符Descriptor_CODE_GATE*/?
InitDescrptor(Descriptor_CODE_GATE,LABEL_CODE_G);

具體代碼如下:

[html] view plaincopy
  • #define?Descriptor(base,lim,attr)\??
  • .word?lim&0xffff;\??
  • .word?base&0xffff;\??
  • .byte?(base>>16)&0xff;\??
  • .word?((lim>>8)&0xf00)|(attr&0x0f0ff);\??
  • .byte?((base>>24)&0xff)????
  • ????
  • /*????
  • *InitDescrptor(Descriptor,SegBase)初始化描述符函數????
  • *Descriptor:要初始化的描述符????
  • *SegBase:段基址????
  • */????
  • #define?InitDescrptor(Descriptor,SegBase)\??
  • xor?????%eax,%eax;?\??
  • mov?????%cs,%ax??;?\??
  • shl?????$4,%eax??;?\??
  • addl????$(SegBase),?%eax?;\??
  • movw????%ax,?(Descriptor?+?2);\??
  • shr?????$16,?%eax;\??
  • movb????%al,?(Descriptor?+?4);\??
  • movb????%ah,?(Descriptor?+?7)????
  • ??
  • #define?Gate(Selector,Offset,PCount,Attr)\??
  • .2byte?(Offset&0xffff);\??
  • .2byte?(Selector);\??
  • .2byte?(PCount&0x1f)|((Attr<<8)&0xff00);\??
  • .2byte?((Offset>>16)&0xffff)????
  • ??
  • DA_386CGate?=?0x8c??
  • DA_PL0?=?0x00??
  • DA_C???=?0x98????
  • DA_32??=?0x4000????
  • DA_DRW?=?0x92????
  • SA_TIL?=?0x4????
  • DA_LDT?=?0x82????
  • ????
  • .text????
  • .globl?start????
  • .code16????
  • start:????
  • ?jmpl?$0x0,?$code?????
  • ?????
  • /**-----------------------------------------------------------------????
  • ?*?全局描述符表:?GDT????
  • ?*-------------------------------*/?????????
  • GDT_START:??????
  • Descriptor_DUMMY:?Descriptor(0x0,0x0,0x0)????
  • Descriptor_CODE32:Descriptor(0x0,0xffffffff,DA_C+DA_32)????
  • Descriptor_VIDEO:?Descriptor(0xb8000,0x0ffff,DA_DRW)????
  • Descriptor_CODE_GATE:Descriptor(0x0,CodeGLen,DA_C+DA_32)??
  • ??
  • /*門描述符*/???
  • Descriptor_Gate_Call:Gate(Selector_Code_Gate,0,0,(DA_386CGate+DA_PL0))????
  • GDT_END:????
  • ????
  • GdtPtr:????
  • ????.word?(GDT_END-GDT_START)-1?#?so?does?gdt?????
  • ????.long?GDT_START?????#?This?will?be?rewrite?by?code.????
  • ??
  • .set????selector_Code32,(Descriptor_CODE32-GDT_START)??
  • .set????Selector_Video,(Descriptor_VIDEO-GDT_START)???????
  • .set??Selector_Code_Gate,(Descriptor_CODE_GATE-GDT_START)??
  • /*調用門選擇子*/??
  • .set????Selector_Gate_Call,(Descriptor_Gate_Call-GDT_START)??
  • ???
  • msg:????
  • ?.string?"Hello?world!"????
  • ?????
  • ?????
  • code:????
  • ????mov?????%cs,%ax???????
  • ????mov?????%ax,%ds?????
  • ????mov?????%ax,%es????????
  • ????mov?????%ax,%ss??????
  • ????mov??$0x8000,%sp??????
  • ????/*顯示HelloWorld字符串*/????
  • ????mov?$msg???,%ax????
  • ????mov?%ax????,%bp????
  • ????mov?$12????,%cx????
  • ????mov?$0x1301,%ax????
  • ????mov?$0x000c,%bx????
  • ????mov?$0?????,%dl????
  • ????????
  • ????int?$0x10????
  • ????????
  • ????
  • /*初始全局描述符Descriptor_CODE32*/????
  • InitDescrptor(Descriptor_CODE32,LABEL_SEG_CODE32);????
  • ????
  • /*初始全局描述符Descriptor_CODE_GATE*/????
  • InitDescrptor(Descriptor_CODE_GATE,LABEL_CODE_G);????
  • ??
  • /*加載gdtr即將全局描述符表gdt的首地址和gdt的界限賦給gdtr寄存器*/???????????
  • ????lgdt?GdtPtr????
  • ????
  • /*關中斷*/????
  • ????cli????
  • ????
  • /*打開地址線A20*/????
  • ????inb?$0x92,%al????
  • ????or??$0x02,%al????
  • ????outb?%al,$0x92????
  • ????
  • /*設置cr0寄存器,切換到保護模式*/????
  • ????movl?%cr0,%eax????
  • ????or???$1,%eax????
  • ????movl?%eax,%cr0????
  • ????
  • ????
  • /*真正進入保護模式,執行此命令后CS=0x8,IP=0*/????
  • ????ljmp?$selector_Code32,$0????
  • ????
  • ??
  • LABEL_SEG_CODE32:????
  • .align??32????
  • .code32????
  • ????
  • ????movw?$Selector_Video,%ax????
  • ????movw?%ax,%gs/*?視頻段選擇子(目的)*/????
  • ????movl?$((80*11+79)*2),%edi/*第11行,79列*/????
  • ????movb?$0x0c,%ah/*高四位表示黑底,低四位表示紅字*/????
  • ????movb?$'P',%al/*顯示的字符*/????
  • ????movw?%ax,%gs:(%edi)????
  • ?????????
  • ????#ljmp?$Selector_Gate_Call,$0??
  • ????lcall?$Selector_Gate_Call,$0????
  • ????
  • ????????
  • jmp?.????
  • ????????
  • LABEL_CODE_G:????
  • ??
  • ????movl?$((80*12+0)*2),%edi/*第10行,0列*/????
  • ????movb?$0x0c,%ah/*高四位0000表示黑底,低四位1100表示紅字*/????
  • ????movb?$'G',%al/*要顯示的字符*/????
  • ????movw?%ax,%gs:(%edi)????
  • ??????
  • jmp?.??
  • ???
  • .set?CodeGLen,(.?-?LABEL_CODE_G)????
  • ????
  • .org?0x1fe,?0x90?????
  • .word?0xaa55???
  • 執行結果如下圖,可以看到紅色的‘G’打印出來


    在LABEL_CODE_G中我們打印完字符就讓程序挺在了這里,這時候如下兩段代碼的效果是一樣的。

    ljmp $Selector_Gate_Call,$0
    ?lcall $Selector_Gate_Call,$0

    但ljmp和lcall是不一樣的,它們都會改變寄存器CS和IP實現程序的跳轉,但lcall還會影響堆棧?,段內跳轉回將ip如棧段間跳轉回將cs和ip入棧,等到lret執行時這個ip(或者cs和ip)會從堆棧中彈出。

    下面我們就實現一個帶返回的調用門:

    [plain] view plaincopy
  • #define?Descriptor(base,lim,attr)\??
  • .word?lim&0xffff;\??
  • .word?base&0xffff;\??
  • .byte?(base>>16)&0xff;\??
  • .word?((lim>>8)&0xf00)|(attr&0x0f0ff);\??
  • .byte?((base>>24)&0xff)????
  • ????
  • /*????
  • *InitDescrptor(Descriptor,SegBase)初始化描述符函數????
  • *Descriptor:要初始化的描述符????
  • *SegBase:段基址????
  • */????
  • #define?InitDescrptor(Descriptor,SegBase)\??
  • xor?????%eax,%eax;?\??
  • mov?????%cs,%ax??;?\??
  • shl?????$4,%eax??;?\??
  • addl????$(SegBase),?%eax?;\??
  • movw????%ax,?(Descriptor?+?2);\??
  • shr?????$16,?%eax;\??
  • movb????%al,?(Descriptor?+?4);\??
  • movb????%ah,?(Descriptor?+?7)????
  • ??
  • #define?Gate(Selector,Offset,PCount,Attr)\??
  • .2byte?(Offset&0xffff);\??
  • .2byte?(Selector);\??
  • .2byte?(PCount&0x1f)|((Attr<<8)&0xff00);\??
  • .2byte?((Offset>>16)&0xffff)????
  • ??
  • DA_386CGate?=?0x8c??
  • DA_PL0?=?0x00??
  • DA_C???=?0x98????
  • DA_32??=?0x4000????
  • DA_DRW?=?0x92????
  • SA_TIL?=?0x4????
  • DA_LDT?=?0x82????
  • ????
  • .text????
  • .globl?start????
  • .code16????
  • start:????
  • ?jmpl?$0x0,?$code?????
  • ?????
  • /**-----------------------------------------------------------------????
  • ?*?全局描述符表:?GDT????
  • ?*-------------------------------*/?????????
  • GDT_START:??????
  • Descriptor_DUMMY:?Descriptor(0x0,0x0,0x0)????
  • Descriptor_CODE32:Descriptor(0x0,0xffffffff,DA_C+DA_32)????
  • Descriptor_VIDEO:?Descriptor(0xb8000,0x0ffff,DA_DRW)????
  • Descriptor_CODE_GATE:Descriptor(0x0,CodeGLen,DA_C+DA_32)??
  • Descriptor_LDT:???Descriptor(0x0,LDTLen?-?1,?DA_LDT)??
  • ??
  • /*門描述符*/???
  • Descriptor_Gate_Call:Gate(Selector_Code_Gate,0,0,(DA_386CGate+DA_PL0))????
  • GDT_END:????
  • ????
  • GdtPtr:????
  • ????.word?(GDT_END-GDT_START)-1?#?so?does?gdt?????
  • ????.long?GDT_START?????#?This?will?be?rewrite?by?code.????
  • ??
  • /**-----------------------------------------------------------------????
  • ?*?GDT中的選擇子??
  • ?*-------------------------------*/???
  • .set????selector_Code32,(Descriptor_CODE32-GDT_START)??
  • .set????Selector_Video,(Descriptor_VIDEO-GDT_START)???????
  • .set??Selector_Code_Gate,(Descriptor_CODE_GATE-GDT_START)??
  • .set????SelectorLDT,(Descriptor_LDT-GDT_START)??
  • /*調用門選擇子*/??
  • .set????Selector_Gate_Call,(Descriptor_Gate_Call-GDT_START)??
  • ??
  • /**-----------------------------------------------------------------??
  • ?*?局部描述符表:?LDT??
  • ?*-------------------------------*/??
  • LDT_START:??
  • /*???????????????????????段基址????段界限??????屬性*/??
  • Descriptor_LDT_CODEA:?Descriptor(0,?CodeALen?-?1,?DA_C?+?DA_32)#?Code,?32?位??
  • ??
  • .set????LDTLen,(.?-?LDT_START)??
  • ??
  • #LDT?選擇子??
  • .set??SelectorLDTCodeA,(0x0?+?SA_TIL)??
  • ???
  • msg:????
  • ?.string?"Hello?world!"????
  • ?????
  • ?????
  • code:????
  • ????mov?????%cs,%ax???????
  • ????mov?????%ax,%ds?????
  • ????mov?????%ax,%es????????
  • ????mov?????%ax,%ss??????
  • ????mov??$0x8000,%sp??????
  • ????/*顯示HelloWorld字符串*/????
  • ????mov?$msg???,%ax????
  • ????mov?%ax????,%bp????
  • ????mov?$12????,%cx????
  • ????mov?$0x1301,%ax????
  • ????mov?$0x000c,%bx????
  • ????mov?$0?????,%dl????
  • ????????
  • ????int?$0x10????
  • ????????
  • ????
  • /*初始全局描述符Descriptor_CODE32*/????
  • InitDescrptor(Descriptor_CODE32,LABEL_SEG_CODE32);???
  • ??
  • /*初始全局描述符Descriptor_LDT*/??
  • InitDescrptor(Descriptor_LDT,LDT_START);??
  • ????
  • /*初始全局描述符Descriptor_CODE_GATE*/????
  • InitDescrptor(Descriptor_CODE_GATE,LABEL_CODE_G);????
  • ??
  • /*初始LDT?中的描述符Descriptor_LDT_CODEA*/??
  • InitDescrptor(Descriptor_LDT_CODEA,LABEL_CODE_A);??
  • ??
  • /*加載gdtr即將全局描述符表gdt的首地址和gdt的界限賦給gdtr寄存器*/???????????
  • ????lgdt?GdtPtr????
  • ????
  • /*關中斷*/????
  • ????cli????
  • ????
  • /*打開地址線A20*/????
  • ????inb?$0x92,%al????
  • ????or??$0x02,%al????
  • ????outb?%al,$0x92????
  • ????
  • /*設置cr0寄存器,切換到保護模式*/????
  • ????movl?%cr0,%eax????
  • ????or???$1,%eax????
  • ????movl?%eax,%cr0????
  • ????
  • ????
  • /*真正進入保護模式,執行此命令后CS=0x8,IP=0*/????
  • ????ljmp?$selector_Code32,$0????
  • ????
  • ??
  • ??
  • LABEL_SEG_CODE32:????
  • .align??32????
  • .code32????
  • ????
  • ????movw?$Selector_Video,%ax????
  • ????movw?%ax,%gs/*?視頻段選擇子(目的)*/????
  • ????movl?$((80*11+79)*2),%edi/*第11行,79列*/????
  • ????movb?$0x0c,%ah/*高四位表示黑底,低四位表示紅字*/????
  • ????movb?$'P',%al/*顯示的字符*/????
  • ????movw?%ax,%gs:(%edi)????
  • ?????????
  • ????lcall?$Selector_Gate_Call,$0????
  • ????
  • ??
  • ????movw?$SelectorLDT,%ax??
  • ????????lldt?%ax/*加載lgtr*/??
  • ??
  • ????????ljmp????$SelectorLDTCodeA,$0????/*?跳入局部任務?LABEL_CODE_A*/??
  • ????????
  • jmp?.????
  • ????????
  • LABEL_CODE_G:????
  • ??
  • ????movl?$((80*12+0)*2),%edi/*第10行,0列*/????
  • ????movb?$0x0c,%ah/*高四位0000表示黑底,低四位1100表示紅字*/????
  • ????movb?$'G',%al/*要顯示的字符*/????
  • ????movw?%ax,%gs:(%edi)????
  • ??????????
  • ????????lret??
  • .set?CodeGLen,(.?-?LABEL_CODE_G)????
  • ??
  • LABEL_CODE_A:??
  • ????movw?$0x10,%ax??
  • ????movw?%ax,%gs/*?視頻段選擇子(目的)*/??
  • ????movl?$((80*12+10)*2),%edi/*第10行,0列*/??
  • ????movb?$0x0c,%ah/*高四位0000表示黑底,低四位1100表示紅字*/??
  • ????movb?$'A',%al/*要顯示的字符*/??
  • ????movw?%ax,%gs:(%edi)??
  • ??????
  • loop3:??
  • ????jmp?loop3??
  • .set?CodeALen,(.?-?LABEL_CODE_A)??
  • ????
  • .org?0x1fe,?0x90?????
  • .word?0xaa55???

  • 其結果是打印完'G'后返回,然后又打印出'A'如下圖:

    ?

    門也是一個描述符,我們放到了GDT中,我們通過門的選擇子訪問門,門通過它記錄的選擇子和偏移值又把我們傳送到了目的地。

    ?

    總結

    以上是生活随笔為你收集整理的调用门的全部內容,希望文章能夠幫你解決所遇到的問題。

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