主頁 > 資料庫 > 是什么導致CPU在此函式中掛起?

是什么導致CPU在此函式中掛起?

2021-12-15 22:39:28 資料庫

我的代碼中有一個函式可以加載到 FAT 和根目錄中。此函式會導致 PCem 仿真器上的某種 CPU 掛起,但不會導致 QEMU 或 PCjs 等其他仿真器上的 CPU 掛起。如果這不是 PCem 的錯誤,那我的程式為什么會這樣?

FAT加載功能:

loadfilesystem:
    mov ax,0x0050
    mov word [fatseg],ax
    mov es,ax
    xor bx,bx
    
    mov cx,word [reserved_sects] ;start of fat
    mov ax,word [sects_per_fat]

    call readsectors ;read fat     
        
    ;calculate start of root directory on disk
    mov ax,word [sects_per_fat]
    mov bl,byte [num_fats]
    mul bl
    add ax,[reserved_sects]
    mov cx,ax
    push cx ;1

    ;also calculate where in memory to put the data

    xor dx,dx
    div bx ;only 1 fat is loaded
    
    mov cl,5
    shl ax,cl
    add ax,0x50
    mov word [rootdirectoryseg],ax
    mov es,ax ;the segment
    xor bx,bx

    mov ax,word [num_rootentries] ;get size of root directory
    mov cl,4
    shr ax,cl
    pop cx ;1
    
    push ax ;1 save size of root directory
    call readsectors

“讀取扇區”功能

readsectors: ;input: cx for lba, al for sectors to read, es:bx for buffer and dl for drive numbers
    call lbatochs ;convert lba to chs
    mov ah,0x02 ;read sectors

    mov dl,byte [drive_num] ;load drive number

    clc ;clear carry for error checking
    int 13h

    jc short readsectorerror ;error
    
    ret ;success

整個程式:

cpu 8086
bits 16

jmp short bootstart ;fat 12 entrypoint code
nop

;fat 12 bpb

oem_label db "OS_BOOT " ;oem label (8 bytes)
bytes_per_sect dw 512 ;bytes per sector
sects_per_cluster db 1 ;sectors per cluster
reserved_sects dw 1 ;reserved sectors
num_fats db 2 ;num of fats
num_rootentries dw 320 ;num of root entries
sect_count dw 320 ;sector count
media_type db 0xfe ;media type (0xfe = 5.25 inch, 160kb)
sects_per_fat dw 1 ;sects per fat
sects_per_track dw 8 ;sects per track
num_heads dw 1 ;num of heads
hidden_sects dd 0 ;hidden sectors
large_sects dd 0 ;large sectors when the disk has more than 65535 sectors
drive_num dw 0 ;drive number
signature db 0x28 ;floppy signature
volume_id dd 0 ;volumeid
volume_label db "OS_BOOT51/4" ;volume label (11 bytes)
file_system db "FAT12   " ;file system (8 bytes)

bootstart:
    cli ;clear interrupts until they can be used
    cld ;clear direction flag for text and other
    mov ax,0x07c0
    mov ds,ax ;data segment initialisation
    
    mov byte [drive_num],dl ;save drive number stored in dl by the bios
    mov ax,0x6c0 ;4096 bytes below bootsector
    mov ss,ax
    mov sp,0x1000
    sti
    
loadfilesystem:
    mov ax,0x0050
    mov word [fatseg],ax
    mov es,ax
    xor bx,bx
    
    mov cx,word [reserved_sects] ;start of fat
    mov ax,word [sects_per_fat]

    call readsectors ;read fat     
        
    ;calculate start of root directory on disk
    mov ax,word [sects_per_fat]
    mov bl,byte [num_fats]
    mul bl
    add ax,[reserved_sects]
    mov cx,ax
    push cx ;1

    ;also calculate where in memory to put the data

    xor dx,dx
    div bx ;only 1 fat is loaded
    
    mov cl,5
    shl ax,cl
    add ax,0x50
    mov word [rootdirectoryseg],ax
    mov es,ax ;the segment
    xor bx,bx

    mov ax,word [num_rootentries] ;get size of root directory
    mov cl,4
    shr ax,cl
    pop cx ;1
    
    push ax ;1 save size of root directory
    call readsectors

    ;now calculate location of the data area
    mov ax,word [sects_per_fat]
    mov bl,byte [num_fats]
    mul bl

    mov bx,ax
    pop ax ;1 load size of root directory
    push ax ;1 save for later but keep ax for a bit
    add ax,bx ;add size of fat
    add ax,word [reserved_sects] ;add reserved sectors
    
    ;we now have the lba of the data area
    mov word [datalba],ax ;save it
    
    ;we now need to find the base segment to load the data at
    pop ax ;1
    mov cl,5
    shl ax,cl
    add ax,[rootdirectoryseg]
    mov word [dataseg],ax ;save the base segment
    
findfile:
    mov ax,word [rootdirectoryseg]
    mov es,ax ;now at the offset of the root directory table
    xor di,di
    mov bx,word [num_rootentries] ;number of entries to search through

findfileloop:
    mov si,filename
    mov cx,11 ;number of bytes the filename is
    repe cmpsb
    je short filefound
    test bx,bx
    je bootfailed ;out of retries
    mov ax,es
    add ax,0x02 ;increase by 2 segments aka 32 bytes
    mov es,ax
    xor di,di
    dec bx ;number of tries left minus one
    jmp short findfileloop

filefound:
    mov ax,word [es:di 0x0f] ;get cluster number
    xor bx,bx ;data load offset
    xor di,di ;fat read offset    
    push ax ;1 save ax

readcluster:
    ;set buffer for data
    mov cx,word [dataseg]
    mov es,cx
    
    ;load sector
    sub ax,2 ;minus 2 clusters
    mov cl,[sects_per_cluster]
    mul cl
    add ax,word [datalba]
    mov cx,ax
    mov al,byte [sects_per_cluster]
    call readsectors
    
    ;increase buffer
    mov al,byte [sects_per_cluster]
    mov ah,0
    mov cl,9
    shl ax,cl
    add bx,ax
    
    pop ax ;1 restore ax
    
    ;set buffer for fat
    mov cx,[fatseg]
    mov es,cx
    
    mov cl,3 ;multiply by three
    mul cl
    shr ax,1 ;divide by two
    mov di,ax    

    mov ax,word [es:di] ;get cluster
    test al,1 ;even or odd cluster
    jnz short evenclus

oddclus:
    mov cl,4
    shr ax,cl
    jmp short evaluatecluster

evenclus:
    and ax,0x0fff

evaluatecluster:
    cmp ax,0x0ff8 ;end of chain
    jae short finishboot
    ;do nothing to cluster and load
    push ax
    jmp short readcluster

finishboot:
    ;this effectively jumps to a pointer
    mov ax,word [dataseg]
    mov ds,ax
    push ax ;push segment
    xor ax,ax
    push ax ;push offset
    retf ;return to offset and segment on stack

readsectors: ;input: cx for lba, al for sectors to read, es:bx for buffer and dl for drive numbers
    call lbatochs ;convert lba to chs
    mov ah,0x02 ;read sectors

    mov dl,byte [drive_num] ;load drive number

    clc ;clear carry for error checking
    int 13h

    jc short readsectorerror ;error
    
    ret ;success

readsectorerror:
    pop dx ;1 clean out stack if error
    call resetdrive
    jmp short readsectors

lbatochs: ;input: cx for lba, output: cx for cylinder and sector, and dh for head
    push ax ;1 save for later
    push bx ;2 save bx
    
    ;find temp variable
    xor dx,dx
    mov ax,cx ;ax now has lba

    push ax ;3 save lba
    mov bx,word [sects_per_track] ;sectors per track
    div bx ;ax is now temp
    
    ;cylinder
    push ax ;4 save temp
    xor dx,dx
    mov bx,word [num_heads] ;number of heads
    div bx ;ax is now cylinder
    mov cx,ax ;cx stores cylinder
    pop ax ;4 retrieve temp
    ;cx is now cylinder
    
    ;head
    push dx ;4 heads already in dx
    
    ;sector
    pop dx ;4 pop dx to get stack value underneath it
    pop ax ;3 retrieve lba
    push dx ;3 push dx back on
    push cx ;4 save cylinder
    xor dx,dx
    mov word bx,[sects_per_track]
    div bx
    inc dx ;dx now has sectors
    mov bx,dx ;now bx has sectors
    pop cx ;4
    pop dx ;3
        
    ;put params together
    mov ch,cl ;cylinder in ch
    mov cl,bl ;sector in cl
    mov dh,dl ;head in dh
    mov dl,0 ;erase dl
        
    pop bx ;2 load old bx
    pop ax ;1 load old ax
    ret

resetdrive:
    mov byte dl,[drive_num] ;get drive number
    mov ah,0x00 ;reset disk interrupt
    int 13h
    jc bootfailed
    ret
    
bootfailed:
    mov si,bootfailmsg
    call printstring
    jmp hangcpu

printstring: ;video mode is set by bios so no need to set it
    lodsb ;load byte from si into al
    test al,al ;compare al with 0
    jz return ;jump if zero to return
    mov bx,0x0007 ;page = bh, color = bl
    mov ah,0xe ;type char interrupt
    int 10h
    jmp short printstring ;go back to start
    
return:
    ret ;return from subroutine
    
hangcpu:
    hlt ;dont run cpu unless interrupt
    jmp short hangcpu

;variables for booting

bootfailmsg db "FAILURE!",0
filename db "BOOT    BIN"

rootdirectoryseg dw 0
fatseg dw 0
dataseg dw 0
datalba dw 0

times 510-($-$$) db 0
bootsignature dw 0xaa55

uj5u.com熱心網友回復:

readsectors: ;input: cx for lba, al for sectors to read, es:bx for buffer and dl for drive numbers
    call lbatochs ;convert lba to chs
    mov ah,0x02 ;read sectors
    mov dl,byte [drive_num] ;load drive number
    clc ;clear carry for error checking
    int 13h
    jc short readsectorerror ;error
    ret ;success

readsectorerror:
    pop dx ;1 clean out stack if error
    call resetdrive
    jmp short readsectors

resetdrive:
    mov byte dl,[drive_num] ;get drive number
    mov ah,0x00 ;reset disk interrupt
    int 13h
    jc bootfailed
    ret

經常發生必須重新讀取扇區的情況。這是正常的,但是在您的讀取扇區代碼中存在一些錯誤:

  • 當BIOS.ReadSector功能02H失敗,代碼去readsectorerror那里是一個無與倫比的pop dx(剩余從早期的編輯),使回傳主程式不可能的
  • resetdrive代碼成功重置驅動器時,代碼會重新啟動readectors例程,但這一次來自AL并且CX不再存在的必要輸入
readsectors:             ;input: cx LBA, al Sectors to read, es:bx Buffer
    push ax
    push cx

    call lbatochs        ; -> CH CL DH

    mov  dl, [drive_num]
    clc                  ;clear carry for error checking
    mov  ah, 0x02        ;read sectors
    int  13h
    jnc  readsectorOK
    mov  ah, 0x00        ;reset disk
    int  13h
    pop  cx
    pop  ax
    jnc  readsectors
    jmp  bootfailed
readsectorOK:
    pop  cx
    pop  ax
    ret

lbatochs程式有幾個多余的指令,是方式復雜!
知道這個引導扇區位于 5.25" 160KB 單面雙密度軟盤上,您可以大大縮短代碼(我相信這是您的目標)。

  • 只有1個頭;因此除以 NumberOfHeads 將是矯枉過正。
  • SectorsPerTrack 僅為 8;無需除法 - 只需向右移動 3 次。
  • 不使用子程式保存CALLRET指令。
readsectors:             ;input: cx LBA, al Sectors to read, es:bx Buffer
    push ax
    push cx

    mov  dx, cx          ; LBA
    shr  dx, 1
    shr  dx, 1
    shr  dx, 1           ; -> DH is Head == 0
    and  cx, 7
    inc  cx              ; -> CL is Sector
    mov  ch, dl          ; -> CH is Cylinder

    mov  dl, [drive_num]
    clc                  ;clear carry for error checking
    mov  ah, 0x02        ;read sectors
    int  13h
    jnc  readsectorOK
    mov  ah, 0x00        ;reset disk
    int  13h
    pop  cx
    pop  ax
    jnc  readsectors
    jmp  bootfailed
readsectorOK:
    pop  cx
    pop  ax
    ret

uj5u.com熱心網友回復:

在 loadfilesystem 函式中,AL 暫存器(要讀取的扇區)設定得太高,導致 BIOS 讀取超過軌道邊界。這不受某些 BIOS 的支持,并且會導致讀取錯誤。

轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/381532.html

標籤:部件 仿真 x86-16 BIOS 个人电脑

上一篇:如何在C程式中嵌入bin檔案

下一篇:如何從WordPress網站的index.php和htaccess檔案中洗掉惡意軟體代碼并順利運行網站

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • GPU虛擬機創建時間深度優化

    **?桔妹導讀:**GPU虛擬機實體創建速度慢是公有云面臨的普遍問題,由于通常情況下創建虛擬機屬于低頻操作而未引起業界的重視,實際生產中還是存在對GPU實體創建時間有苛刻要求的業務場景。本文將介紹滴滴云在解決該問題時的思路、方法、并展示最終的優化成果。 從公有云服務商那里購買過虛擬主機的資深用戶,一 ......

    uj5u.com 2020-09-10 06:09:13 more
  • 可編程網卡芯片在滴滴云網路的應用實踐

    **?桔妹導讀:**隨著云規模不斷擴大以及業務層面對延遲、帶寬的要求越來越高,采用DPDK 加速網路報文處理的方式在橫向縱向擴展都出現了局限性。可編程芯片成為業界熱點。本文主要講述了可編程網卡芯片在滴滴云網路中的應用實踐,遇到的問題、帶來的收益以及開源社區貢獻。 #1. 資料中心面臨的問題 隨著滴滴 ......

    uj5u.com 2020-09-10 06:10:21 more
  • 滴滴資料通道服務演進之路

    **?桔妹導讀:**滴滴資料通道引擎承載著全公司的資料同步,為下游實時和離線場景提供了必不可少的源資料。隨著任務量的不斷增加,資料通道的整體架構也隨之發生改變。本文介紹了滴滴資料通道的發展歷程,遇到的問題以及今后的規劃。 #1. 背景 資料,對于任何一家互聯網公司來說都是非常重要的資產,公司的大資料 ......

    uj5u.com 2020-09-10 06:11:05 more
  • 滴滴AI Labs斬獲國際機器翻譯大賽中譯英方向世界第三

    **桔妹導讀:**深耕人工智能領域,致力于探索AI讓出行更美好的滴滴AI Labs再次斬獲國際大獎,這次獲獎的專案是什么呢?一起來看看詳細報道吧! 近日,由國際計算語言學協會ACL(The Association for Computational Linguistics)舉辦的世界最具影響力的機器 ......

    uj5u.com 2020-09-10 06:11:29 more
  • MPP (Massively Parallel Processing)大規模并行處理

    1、什么是mpp? MPP (Massively Parallel Processing),即大規模并行處理,在資料庫非共享集群中,每個節點都有獨立的磁盤存盤系統和記憶體系統,業務資料根據資料庫模型和應用特點劃分到各個節點上,每臺資料節點通過專用網路或者商業通用網路互相連接,彼此協同計算,作為整體提供 ......

    uj5u.com 2020-09-10 06:11:41 more
  • 滴滴資料倉庫指標體系建設實踐

    **桔妹導讀:**指標體系是什么?如何使用OSM模型和AARRR模型搭建指標體系?如何統一流程、規范化、工具化管理指標體系?本文會對建設的方法論結合滴滴資料指標體系建設實踐進行解答分析。 #1. 什么是指標體系 ##1.1 指標體系定義 指標體系是將零散單點的具有相互聯系的指標,系統化的組織起來,通 ......

    uj5u.com 2020-09-10 06:12:52 more
  • 單表千萬行資料庫 LIKE 搜索優化手記

    我們經常在資料庫中使用 LIKE 運算子來完成對資料的模糊搜索,LIKE 運算子用于在 WHERE 子句中搜索列中的指定模式。 如果需要查找客戶表中所有姓氏是“張”的資料,可以使用下面的 SQL 陳述句: SELECT * FROM Customer WHERE Name LIKE '張%' 如果需要 ......

    uj5u.com 2020-09-10 06:13:25 more
  • 滴滴Ceph分布式存盤系統優化之鎖優化

    **桔妹導讀:**Ceph是國際知名的開源分布式存盤系統,在工業界和學術界都有著重要的影響。Ceph的架構和演算法設計發表在國際系統領域頂級會議OSDI、SOSP、SC等上。Ceph社區得到Red Hat、SUSE、Intel等大公司的大力支持。Ceph是國際云計算領域應用最廣泛的開源分布式存盤系統, ......

    uj5u.com 2020-09-10 06:14:51 more
  • es~通過ElasticsearchTemplate進行聚合~嵌套聚合

    之前寫過《es~通過ElasticsearchTemplate進行聚合操作》的文章,這一次主要寫一個嵌套的聚合,例如先對sex集合,再對desc聚合,最后再對age求和,共三層嵌套。 Aggregations的部分特性類似于SQL語言中的group by,avg,sum等函式,Aggregation ......

    uj5u.com 2020-09-10 06:14:59 more
  • 爬蟲日志監控 -- Elastc Stack(ELK)部署

    傻瓜式部署,只需替換IP與用戶 導讀: 現ELK四大組件分別為:Elasticsearch(核心)、logstash(處理)、filebeat(采集)、kibana(可視化) 下載均在https://www.elastic.co/cn/downloads/下tar包,各組件版本最好一致,配合fdm會 ......

    uj5u.com 2020-09-10 06:15:05 more
最新发布
  • day02-2-商鋪查詢快取

    功能02-商鋪查詢快取 3.商鋪詳情快取查詢 3.1什么是快取? 快取就是資料交換的緩沖區(稱作Cache),是存盤資料的臨時地方,一般讀寫性能較高。 快取的作用: 降低后端負載 提高讀寫效率,降低回應時間 快取的成本: 資料一致性成本 代碼維護成本 運維成本 3.2需求說明 如下,當我們點擊商店詳 ......

    uj5u.com 2023-04-20 08:33:24 more
  • MySQL中binlog備份腳本分享

    關于MySQL的二進制日志(binlog),我們都知道二進制日志(binlog)非常重要,尤其當你需要point to point災難恢復的時侯,所以我們要對其進行備份。關于二進制日志(binlog)的備份,可以基于flush logs方式先切換binlog,然后拷貝&壓縮到到遠程服務器或本地服務器 ......

    uj5u.com 2023-04-20 08:28:06 more
  • day02-短信登錄

    功能實作02 2.功能01-短信登錄 2.1基于Session實作登錄 2.1.1思路分析 2.1.2代碼實作 2.1.2.1發送短信驗證碼 發送短信驗證碼: 發送驗證碼的介面為:http://127.0.0.1:8080/api/user/code?phone=xxxxx<手機號> 請求方式:PO ......

    uj5u.com 2023-04-20 08:27:27 more
  • 快取與資料庫雙寫一致性幾種策略分析

    本文將對幾種快取與資料庫保證資料一致性的使用方式進行分析。為保證高并發性能,以下分析場景不考慮執行的原子性及加鎖等強一致性要求的場景,僅追求最終一致性。 ......

    uj5u.com 2023-04-20 08:26:48 more
  • sql陳述句優化

    問題查找及措施 問題查找 需要找到具體的代碼,對其進行一對一優化,而非一直把關注點放在服務器和sql平臺 降低簡化每個事務中處理的問題,盡量不要讓一個事務拖太長的時間 例如檔案上傳時,應將檔案上傳這一步放在事務外面 微軟建議 4.啟動sql定時執行計劃 怎么啟動sqlserver代理服務-百度經驗 ......

    uj5u.com 2023-04-20 08:26:35 more
  • 云時代,MySQL到ClickHouse資料同步產品對比推薦

    ClickHouse 在執行分析查詢時的速度優勢很好的彌補了MySQL的不足,但是對于很多開發者和DBA來說,如何將MySQL穩定、高效、簡單的同步到 ClickHouse 卻很困難。本文對比了 NineData、MaterializeMySQL(ClickHouse自帶)、Bifrost 三款產品... ......

    uj5u.com 2023-04-20 08:26:29 more
  • sql陳述句優化

    問題查找及措施 問題查找 需要找到具體的代碼,對其進行一對一優化,而非一直把關注點放在服務器和sql平臺 降低簡化每個事務中處理的問題,盡量不要讓一個事務拖太長的時間 例如檔案上傳時,應將檔案上傳這一步放在事務外面 微軟建議 4.啟動sql定時執行計劃 怎么啟動sqlserver代理服務-百度經驗 ......

    uj5u.com 2023-04-20 08:25:13 more
  • Redis 報”OutOfDirectMemoryError“(堆外記憶體溢位)

    Redis 報錯“OutOfDirectMemoryError(堆外記憶體溢位) ”問題如下: 一、報錯資訊: 使用 Redis 的業務介面 ,產生 OutOfDirectMemoryError(堆外記憶體溢位),如圖: 格式化后的報錯資訊: { "timestamp": "2023-04-17 22: ......

    uj5u.com 2023-04-20 08:24:54 more
  • day02-2-商鋪查詢快取

    功能02-商鋪查詢快取 3.商鋪詳情快取查詢 3.1什么是快取? 快取就是資料交換的緩沖區(稱作Cache),是存盤資料的臨時地方,一般讀寫性能較高。 快取的作用: 降低后端負載 提高讀寫效率,降低回應時間 快取的成本: 資料一致性成本 代碼維護成本 運維成本 3.2需求說明 如下,當我們點擊商店詳 ......

    uj5u.com 2023-04-20 08:24:03 more
  • day02-短信登錄

    功能實作02 2.功能01-短信登錄 2.1基于Session實作登錄 2.1.1思路分析 2.1.2代碼實作 2.1.2.1發送短信驗證碼 發送短信驗證碼: 發送驗證碼的介面為:http://127.0.0.1:8080/api/user/code?phone=xxxxx<手機號> 請求方式:PO ......

    uj5u.com 2023-04-20 08:23:11 more