2016年1月8日 星期五

進出 x86 保護模式 - 使用 masm

這是 80x86 汇编语言程序设计教程的範例程式,書中的版本有點錯誤, 我做了一點修正。

我自然不熟悉 masm, 通常我的開發環境都是 linux。會使用 masm 來測試這個程式, 純粹是好玩。我已經有了 gas, nasm 的進入保護模式的版本, 想再補上 masm。

如何使用 masm 5.0 讓我傷透腦筋, masm 5.0 可以在 windows xp 執行, 卻不能在 windows 8 執行, 我得在 windows xp 使用 masm, 並把執行檔想辦法傳到 linux/qemu 上, 繞了一大圈總算搞定。

組譯完成後的是一個 dos exe 檔案, 我在 qemu/dos 上測試, 沒問題, 保險起見, 又在真實機器上以 dos 為開機片再測試過, 真的可以正確執行。

spm.asm
  1 ; test by masm 5.0
  2 ; t10-1.asm 80x86 汇编语言程序设计教程 page 376
  3 JUMP MACRO selector, offsetv
  4   DB 0eah
  5   DW offsetv
  6   DW selector
  7   ENDM
  8 
  9 ECHOCH MACRO ascii
 10   mov ah, 2
 11   mov dl, ascii
 12   int 21h
 13   endm
 14 
 15 DESCRIPTOR STRUC
 16 LIMITL DW 0
 17 BASEL DW 0
 18 BASEM DB 0
 19 ATTRIBUTES DW 0
 20 BASEH DB 0
 21 DESCRIPTOR ENDS
 22 
 23 PDESC STRUC
 24 LIMIT DW 0
 25 BASE DD 0
 26 PDESC ENDS
 27 
 28 ATDW = 92H
 29 ATCE = 98H
 30 .386P
 31 
 32 DSEG SEGMENT USE16
 33 GDT LABEL BYTE
 34 DUMMY DESCRIPTOR <>
 35 CODE DESCRIPTOR <0FFFFH,,,ATCE,>
 36 CODE_SEL = CODE - GDT
 37 DATAS DESCRIPTOR <0FFFFH,0H,11H,ATDW,0>
 38 DATAS_SEL = DATAS - GDT
 39 DATAD DESCRIPTOR<0FFFFH,,,ATDW,>
 40 DATAD_SEL = DATAD - GDT
 41 GDTLEN = $ - GDT
 42 VGDTR PDESC <GDTLEN-1>
 43 BUFFERLEN = 256
 44 BUFFER DB BUFFERLEN DUP(0)
 45 DSEG ENDS
 46 
 47 CSEG SEGMENT USE16
 48   ASSUME CS:CSEG, DS:DSEG
 49 START:
 50   xchg bx, bx
 51   mov ax, dseg
 52   mov ds, ax
 53   mov bx, 16
 54   mul bx
 55   add ax, offset gdt
 56   adc dx, 0
 57   mov word ptr vgdtr.base, ax
 58   mov word ptr vgdtr.base+2, dx
 59   mov ax, cs
 60   mul bx
 61   mov code.basel, ax
 62   mov code.basem, dl
 63   mov code.baseh, dh
 64   mov ax, ds
 65   mul bx
 66   add ax, offset buffer
 67   adc dx, 0
 68   mov datad.basel, ax
 69   mov datad.basem, dl
 70   mov datad.baseh, dh
 71 
 72   lgdt qword ptr vgdtr
 73 
 74   cli
 75   call ea20
 76 
 77   mov eax, cr0
 78   or eax, 1
 79   mov cr0, eax
 80 
 81   JUMP <CODE_SEL>, <OFFSET VIRTUAL>
 82 
 83 VIRTUAL:
 84   mov ax, datas_sel
 85   mov ds, ax
 86   mov ax, datad_sel
 87   mov es, ax
 88   cld
 89   xor si, si
 90   xor di, di
 91   mov cx, bufferlen/4
 92   repz movsd
 93 
 94   mov eax, cr0
 95   and eax, 0fffffffeh
 96   mov cr0, eax
 97 
 98   JUMP <SEG REAL>,<OFFSET REAL>
 99 
100 REAL:
101   call da20
102   sti
103   mov ax, dseg
104   mov ds, ax
105   mov si, offset buffer
106   cld
107   mov bp, bufferlen/16
108 NEXTLINE:
109   mov cx, 16
110 NEXTCH:
111   lodsb
112   push ax
113   shr al, 4
114   call toascii
115   ECHOCH al
116   pop ax
117   call toascii
118   echoch al
119   echoch ' '
120   loop nextch
121   echoch 0dh
122   echoch 0ah
123   dec bp
124   jnz nextline
125 
126   mov ax, 4c00h
127   int 21h
128 
129 TOASCII PROC
130         and    al, 0fh
131         cmp     al, 9
132         ja      EN
133         add    al, 030h
134         jmp     EX
135 EN:
136         sub     al, 0ah
137         add     al, 041h
138 EX:
139         ret
140 TOASCII ENDP
141 
142 EA20 PROC
143   push ax
144   in al, 92h
145   or al, 2
146   out 92h, al
147   pop ax
148   ret
149 EA20 ENDP
150 
151 DA20 PROC
152   push ax
153   in al, 92h
154   and al, 0fdh
155   out 92h, al
156   pop ax
157   ret
158 DA20 ENDP
159 
160 
161 
162 
163 
164 CSEG ENDS
165   END START
166 

4 則留言:

  1. 我自己沒試過 DOSBOX 去跑MASM 只是給你參考一下
    但是曾經看過人家用DOSBOX under Vista 下面跑 Legacy BIOS compiler 會用到MASM 6.15 之類的
    http://www.ansmachine.net/2013/12/masm-using-dos-box-in-windows-8.html

    回覆刪除
  2. 謝謝,

    不過我建議還是用 qemu 之類的軟體, 我之前吃過 dosbox 的虧, dosbox 可以把錯誤的程式執行的很正常, 結果我用真實機器執行該程式是完全不正確的。

    這也是我為什麼堅持要在真實機器跑過一次的原因。

    回覆刪除
  3. 不知道你的錯誤程式 可以執行得很正常是怎樣的回事
    我是說可以不用另外用XP 直接用MASM 在DOSBOX 下編譯
    然後程式還是要在真實機器跑過的!

    我大膽猜測你的問題是 因為DOSBOX 它只是模擬所以可能沒有正確做過某些初始化
    導致程式在DOSBOX 下很正常 但是到真實狀況下不正常
    如果是這樣情形 應該是用的時候心理就要預期才是
    古早以前就連HW Emulator 都有聽過有人抱怨跟實際的MCU 不一樣
    因為某些 實際上的 IO 驅動能力不一樣呀! 如果對細節不注意很容易陷入這種問題
    如果不是就當作我胡說八道吧!

    回覆刪除
  4. 是的, 程式無法在真實機器上執行應該是這樣的問題。

    而 masm 應該是可以在 dosbox 直接使用。

    回覆刪除

使用 google 的 reCAPTCHA 驗證碼, 總算可以輕鬆留言了。

我實在受不了 spam 了, 又不想讓大家的眼睛花掉, 只好放棄匿名留言。這是沒辦法中的辦法了。留言的朋友需要有 google 帳號。