1. 程式人生 > >王爽.彙編.第三版.課程設計2

王爽.彙編.第三版.課程設計2

讀完王爽彙編第三版的精簡版的作業系統,對沒有錯,就是作業系統
需要注意的是:
0、多謝:http://www.cnblogs.com/S-E-P/archive/2010/04/06/2045067.html的程式碼。
1、將程式碼拷貝到軟盤,然後再從軟盤拷貝到記憶體的時候,程式中用到的字串怎麼定址,因為按照目前書中的知識面,如果用標號訪問字串,則用的是偏移地址,而程式碼經過這樣的2次拷貝後,地址早不知道偏移到哪去了(字串地址=cs+偏移,如果要固定死cs,就限制太大了)。
解決方案:就是將各個功能分段,將每個功能放到獨立的段裡,此問題就大大簡化了。
2、需要注意的是,功能函式的返回可以用retf簡化程式的跳轉,如下,跳轉到2000:0

    mov  ax,2000h
    push ax
    mov  ax,0
    push ax
    retf

當然也可以用call dword 2000:0。
測試環境:
1、我用的是vbox安裝MS dos7.10。
2、用winImage製作共享軟盤share.vfd和系統啟動盤boot.vfd。注意,同時只能有一個程式訪問vfd檔案,因此winImage修改vfd時,要關閉dos,反之亦然。
2.1 share.vfd用於windows和vbox的dos系統共享軟體用的,放在2號軟碟機(碟符B:)
2.2 boot.vfd是用於寫入自制的作業系統的,放在1號軟碟機(碟符A:),這和bios的啟動規則有關係,不贅述(見Page312)
測試過程:
直接在dos上編譯程式碼的直接忽略這些步驟,我是在windows上的dosbox上測試並編輯程式碼,然後再virtual dos上測試。
1、將程式碼儲存成kcsj2.asm,上位機編譯成程式kcsj2.exe。
2、用winImage開啟share.vfd,拖入kcsj.exe儲存。
3、直接在v dos上將kcsj2.exe拷貝到c盤,執行kcsj2.exe製作系統盤,重啟。
附錄一,程式碼:

; 簡化kcsj2的程式
; 任務選單,只保留,restpc,startsystem,clock(只顯示時間)
;注意有軟盤模擬工具

;系統盤製作 段    
assume  cs:FloppyInstallCode    
FloppyInstallCode segment

start:
    ;-------------------
    ;注意,此處沒有考慮拷貝的長度,軟盤上肯定有多餘的字
    ;節,但是沒有關係,因為指令會將那些位元組跳過去
    ;-------------------
    ; 拷貝程式碼載入程式
    mov ax, lodesysSeg
    mov es, ax
    mov bx, 0
mov al,1 mov ch,0 mov cl,1 ; 第一扇區 mov dl,0 mov dh,0 mov ah,3 int 13h call showerror ; 拷貝任務程式 mov ax, taskCodeSeg mov es, ax mov bx, 0 mov al,15 ; 此處是為了保險,寫的15 mov cl,2 ; 第二扇區 mov ah,3 int 13h call showerror ;安裝結束,返回 mov ax,4c00h int 21h showerror: jmp short showerror_code err db 'error: ', 0 ok db 'ok',0 buff db '0123456789abcdef' showerror_code: push ax push bx push ds mov bx, 0b800h mov ds, bx cmp ah, 0 jne showerror_error mov byte ptr ds:[18], 'o' mov byte ptr ds:[20], 'k' jmp short showerror_exit showerror_error: mov byte ptr ds:[0], 'e' mov byte ptr ds:[2], 'r' mov byte ptr ds:[4], 'r' mov byte ptr ds:[6], 'o' mov byte ptr ds:[8], 'r' mov byte ptr ds:[10], ':' mov al, ah and al, 00001111b shr ah, 1 shr ah, 1 shr ah, 1 shr ah, 1 sub bx, bx mov bl, al mov bl, buff[bx] mov byte ptr ds:[12], bl mov bl, ah mov bl, buff[bx] mov byte ptr ds:[14], bl mov byte ptr ds:[16], '!' jmp short showerror_exit showerror_exit: pop ds pop bx pop ax ret FloppyInstallCode ends ;-------------------------------- ;引導扇區的程式 ;主載入程式 ;包含所有子程式的直接定址表,扇區載入程式,選單 assume cs:lodesysSeg lodesysSeg segment init: call loadsys ; 調到第二扇區執行,2000地址,自己任意設定,只要大於512位元組跳過lodesysSeg就可以了 mov ax,2000h push ax mov ax,0 push ax retf loadsys: mov ax,2000h ;軟盤資料讀取到2000:0 mov es,ax mov bx,0 mov al,15 ;讀取的扇區數 mov ch,0 ;0磁軌 mov cl,2 ;2扇區 mov dl,0 ;0號驅動器 mov dh,0 ;0面 mov ah,2 int 13h ret lodesysSegend: nop lodesysSeg ends ;------------------------------------------ ; 任務程式碼, 第二扇區以後 assume cs:taskCodeSeg taskCodeSeg segment realcode: jmp short run tip1 db "1. rest pc",0 tip2 db "2. start system",0 tip3 db "3. clock",0 tipoff dw tip1, tip2, tip3 run: ; mov dh, 12 ; mov dl, 34 ; call showtime call showtips mov ah, 0 int 16h ; al cmp al, '1' je if_1 cmp al, '2' je if_2 cmp al, '3' je if_3 cmp al, 'q' jmp exit jmp run if_1: call reset_pc jmp run if_2: call start_system jmp run if_3: call clock jmp run mov ax, 4c00h int 21h showtips: push ds push es push si push di push ax push bx push cx push dx mov ax, 0b800h mov ds, ax mov ax, 0 mov dx, 0 ; ?st tip mov si, 0 ; screen pos mov cx, 3 ; 3 tips showtips_loop: push si mov bx, dx mov bx, tipoff[bx] showonetip: mov al, byte ptr cs:[bx] cmp al, 0 je showonetip_over mov byte ptr ds:[si], al mov byte ptr ds:[si+1], 00000100b add si, 2 inc bx jmp showonetip showonetip_over: pop si add si, 160 add dx, 2 loop showtips_loop pop dx pop cx pop bx pop ax pop di pop si pop es pop ds ret ;--------------- exit: mov ax, 4c00h int 21h reset_pc: ;直接設定cs:ip,跳轉到ffff:0 mov ax, 0 mov word ptr ds:[0], ax mov ax, 0ffffh mov ds:[2], ax call dword ptr ds:[0] ret start_system: ;將C盤的第001扇區讀入到0:7C00 mov ax, 0 mov es, ax mov bx, 07c00h mov al, 1 mov ch, 0 mov cl, 1 mov dl, 80h mov dh, 0 mov ah, 2 int 13h ; 返回到0:7c00,注意retf的使用 mov ax, 0h push ax mov ax, 7c00h push ax retf clock: ;顯示時間 mov dh, 12 mov dl, 34 call showtime ret ;-------------------------- ; show cmos time ; 引數:dh:dl,位置中的行和列 showtime: jmp short showtime_code showtime_data: db 9,8,7,4,2,0 ; 埠中時間的位元組偏移 db '// :: ' ; 間隔符 showtime_code: push es push si push ds push di push bx push cx push dx call clearscreen ; 寫入的位置 mov ax, 0b800h mov es, ax push dx sub ax, ax mov al, dh mov bx, 160 mul bx mov cx, ax pop dx sub ax, ax mov al, dl mov bx, 2 mul bx add ax, cx mov di, ax ; ds:si=cmos偏移欄位快取區的地址 mov ax, cs mov ds, ax mov ax, offset showtime_data mov si, ax mov cx, 6 showtime_looptime: push cx ;偏移 mov al, byte ptr ds:[si] out 70h, al in al, 71h ;十位的計算 mov bh, al and bh, 11110000b mov cl, 4 shr bh, cl add bh, 30h mov byte ptr es:[di], bh mov byte ptr es:[di+1], 00000010b ;個位的計算 mov bl, al and bl, 00001111b add bl, 30h mov byte ptr es:[di+2], bl mov byte ptr es:[di+3], 00000010b ;顯示分隔符 mov al, byte ptr ds:[si+6] mov byte ptr es:[di+4], al mov byte ptr es:[di+5], 00000010b add di, 6 inc si pop cx loop showtime_looptime pop dx pop cx pop bx pop di pop ds pop si pop es ret ;------------------------------------------ ; 引數:無 ; 清屏 clearscreen: push ax push bx push cx push es mov ax, 0b800h mov es, ax mov bx, 0 mov ax, 0 mov cx, 160*25 clearscreen_loop: mov byte ptr word ptr es:[bx], ' ' add bx,2 loop clearscreen_loop pop es pop cx pop bx pop ax ret taskCodeSeg ends end start

附錄二,vfd注意事項:
1、新建
這裡寫圖片描述
2、不要直接儲存,要使用save as:
這裡寫圖片描述
3、剩下的dos和winImage不要同時使用就可以了