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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

x86汇编从实模式到保护模式-程序加载器

發(fā)布時間:2024/4/18 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 x86汇编从实模式到保护模式-程序加载器 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

調試一天半,復刻成功!!!

;文件名:Program_Loader.asm ;文件說明:硬盤主引導扇區(qū)代碼(加載程序) ;創(chuàng)建日期:2021-11-1;用戶程序起始邏輯扇區(qū)號 ;;Main: ;設置堆棧 ;計算用戶程序加載的段地址 ;設置程序讀取的上文(先讀取一個扇區(qū),獲取基本信息) ;利用基本信息,計算程序的總扇區(qū)數(shù) ;(若剩余扇區(qū)數(shù)>0)讀取剩余扇區(qū) ;重置段表 ;跳轉至用戶程序入口 ; ; application equ 10 ;用戶程序所在扇區(qū)號 section app_load align=16 vstart=0x7c00;設置堆棧指針 mov ax,0 mov ss,ax mov sp,0x0;設置用戶程序加載位置 mov ax,[cs:phy_base] ;低位 mov dx,[cs:phy_base+0x2] ;高位 mov bx,0x10 div bx mov ds,ax ;ds與es指向用戶程序加載位置 ;mov es,ax;讀取一個扇區(qū)大小的用戶程序 mov di,0 ;扇區(qū)讀取目標地址ds:di mov si,application ;需讀取扇區(qū)號 call read_HardDisk_0 ;開始讀取;計算用戶程序大小 mov dx,[0x2] ;用戶程序大小高地址 mov ax,[0x0] ;用戶程序大小低地址 mov bx,512 ;一個扇區(qū)大小 div bx ;ax為商,dx為余 cmp dx,0x0 ;ax:所占用完整的扇區(qū)數(shù) jnz @1 ;dx為0,則共需讀取ax個扇區(qū)(別忘了已經(jīng)讀取過一個扇區(qū)) dec ax ;dx不為0,則共需讀取ax+1個扇區(qū)(別忘了已經(jīng)讀取過一個扇區(qū));判斷用戶程序所占扇區(qū)大小 @1: ;若ax為0,則無需再讀取 cmp ax,0 jz re_entrymov cx,ax ;讀取剩余扇區(qū)的程序 @2: ;此時di=512,ds=0x10000 inc si ;si為需讀取扇區(qū)號 call read_HardDisk_0 ;讀取第si個扇區(qū) loop @2;用戶程序讀取完畢;用戶程序起始地址:0x10000 re_entry: ;重置用戶程序代碼入口 mov dx,[0x8] ;代碼段入口高地址 mov ax,[0x6] ;代碼段入口低地址 call translaion_address ;返回段地址ax mov [0x6],ax ;重寫程序入口段基址mov di, 0xc ;段基址重定位表首地址 mov cx,[0xa] ;需重置段基址數(shù)量 re_section: mov dx,[di+0x2] ;代碼段入口高地址 mov ax,[di] ;代碼段入口低地址 call translaion_address ;返回段地址ax mov [di],ax ;重寫程序入口段基址 add di,4 ;下一需重定位段基址 loop re_sectionjmp far [0x4] ;跳轉至用戶程序入口 ;---------------------------------------------------------------------------------- ;硬盤讀取 read_HardDisk_0: ;si為所需扇區(qū)號;ds:di為目標地址 push cxmov al,0x1 ;讀取扇區(qū)數(shù) mov dx,0x1f2 ;0x01f2端口 out dx,al inc dx;0x01f3端口,0x01f4端口,0x01f5端口,0x01f6端口 ;LBA地址0~7,LBA地址8~15,LBA地址16~23,LBA地址24~27 ;0~27:LBA28邏輯扇區(qū) ;28~31: ;28:[0:主硬盤/1:從硬盤] ;29~31:[101:CHS/111:LBA]mov ax,si out dx,al ;0x01f3端口,LBA地址0~7 inc dxmov al,0x0 out dx,al ;0x01f4端口,LBA地址8~15 inc dxout dx,al ;0x01f5端口,LBA地址16~23 inc dxmov al,0xe0 out dx,al ;0x01f6端口,LBA地址24~27 inc dx ;28~31,模式設置mov al,0x20 out dx,al ;0x01f7端口,向端口寫入0x20(寫命令);等待硬盤數(shù)據(jù)準備 wait_: in al,dx ;0x01f7端口為狀態(tài)寄存器 and al,0x88 ;留下第7位,第4位 cmp al,0x8 ;第7位為0表示不忙,第4位為1表示數(shù)據(jù)以準備好 jnz wait_mov dx,0x1f0 ;數(shù)據(jù)傳送端口 mov cx,256;開始讀取硬盤 ;讀取字數(shù) read_: in ax,dx mov [di],ax inc di inc di loop read_pop cxret ;-------------------------------------------------------------------------------------- translaion_address: ;輸入;dx為16位高地址(2B);ax為16位低地址(2B);phy_base=0x10000(4B) add ax,[cs:phy_base] ;低位相加,CF進位 adc dx,[cs:phy_base+0x2] ;高位相加,加上CF進位,由此完成32位加法;此時dx:ax為內(nèi)存中入口點代碼段起始地址;8086中僅有20位地址線(前20位有效);所以dx:ax僅有20位有效;因為ax有16位有效;于是dx雖有16位,dx僅有最后4位有效;只取20位中高16位作為段地址 shl dx,12 ;dx低4位放于高4位返回 shr ax,4 ;保留ax高12位放于低12位返回 add ax,dx ;返回段地址axret ;---------------------------------------------------------------------------------- phy_base dd 0x10000 ;用戶程序加載位置,16字節(jié)對齊 db 510-($-$$) dup(0) ;補充滿一個扇區(qū) db 0x55,0xaa

總結

以上是生活随笔為你收集整理的x86汇编从实模式到保护模式-程序加载器的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。