]]>用汇~编写DOS下的内存ȝE序(3)http://www.aygfsteel.com/ThinkingTalking/archive/2007/09/30/149741.htmlThinkingTalkingThinkingTalkingSun, 30 Sep 2007 00:20:00 GMThttp://www.aygfsteel.com/ThinkingTalking/archive/2007/09/30/149741.htmlhttp://www.aygfsteel.com/ThinkingTalking/comments/149741.htmlhttp://www.aygfsteel.com/ThinkingTalking/archive/2007/09/30/149741.html#Feedback0http://www.aygfsteel.com/ThinkingTalking/comments/commentRss/149741.htmlhttp://www.aygfsteel.com/ThinkingTalking/services/trackbacks/149741.html
3.1 IBM PC提供的中?
IBM PC有两U基本Ş态的中断.如果是由外围讑֤所产生的中断就叫做g中断(Hardware interrupt),譬如:键盘,盘机和旉{外围设备都可以产生g中断.外围讑֤所产生的中断信号都q接C断控制器,中断控制器可以根据它们之间的重要性来安排优先序,以便使CPU有效地处理这些硬件信?另一U中断是软g中断(Software interrupt),软g中断也叫做陷?Trap),它是由执行中的Y件所产生.虽然软g包中断的处理方式和硬件中断完全相?但是通常软g中断是希望执行操作系l所提供?a class="channel_keylink" >服务.
?.1是IBM PC所提供的中?q些中断是根据中断号码和中断矢量(Interrupt vector)排列.
IBM PC的用h是编写应用程序的E序人员很少?x)直接接触到g中断,除非是用某些特D的g,或是需要较严格的要求时,最常被修改的硬件中断是敲键盘所产生的中?9H),其是文本编辑的E序.大体而言,只有g设计者基是系l程序h员才?x)注意到所有在g中断;~写内存ȝE序的设计h员则只用到部分g中断而已,其?键盘中断和计时器(Timer)的中?
反之,软g中断对于M~写?a class="channel_keylink" >~程序的?甚至对编写高U语aE序的h都相当的重要.软g中断是应用程序进入到IBM PC操作pȝ的接?l由q些接口应用E序才可以执行所要求的系l?a class="channel_keylink" >服务.
其中软g中断中最重要,同时也是最常被汇编语言E序设计师所用到是DOS INT 21H.q个中断是执行DOSpȝ调用的Y件中?它可以让应用E序执行MDOS的操?
接下来最有用的Y件中断是ROM-BIOS(基本输入输出pȝ)所提供的中?q些软g中断是IBM PC所提供的的低层?a class="channel_keylink" >服务,譬如:键盘输入,昄器输出和盘机的输入与输出等.
3.2 键盘输入的方?
以下׃IBM PC从键盘读取字Wؓ(f)例子,来说明中断的工作方式.IBM PC从键盘读取字W时,使用了两U不同Ş式中?亦即:g中断和Y件中?当用者从键盘敲下一个键?键盘的线路就?x)送出一个信?q个信号?x)造成g中断发生,从而触发低层次的键盘中断处理程序开始执?q个中断处理E序马上从键盘的gd使用者所敲入的字W?然后把它攑ֈ一个队列中,如果q个队列填满?键盘中断处理E序?x)IBM PC发出一声响.键盘中断处理E序做完q些事情之后,它就把控制权交还l原先被中断的程?如果有一个程序希望从键盘d一个字W时,它就发出适当的Y件中断信?q时候就q对应的中断处理程序去(g)查键盘队?q且传回队列中的W一个字W?
上面所介绍的键盘输入工作方?在中断驱动系l中很普遍地采用.q和做法可以把实际上需要输入的应用E序和实际上执行输入的处理部分分开?q种做法也可以用在其它不同Ş式的输入和输出外围设?
3.3 改变输入矢量
中断矢量储存在IBM PC最前面?00H个字节中.每一个矢量的长度是四个字节组?q四个字节内所存放的是中断处理E序执行的地址?其中前两个字节包含地址值的位移(Offset)部分,后面的两个字节则包含了段(Segment)部分.
中断矢量有两U修Ҏ(gu)?可以直接地设|中断矢量的地址?或是使用DOS所提供的系l调用设|中断矢量的地址?
3.3.1 直接讄中断矢量
因ؓ(f)中断矢量只是存放地址值的存储位置,因此我们可以直接地把地址存放到存储位|中.以下是一个小例子:
mov ax,0
mov es,ax
mov word ptr es:24,offset Keyboard
mov word ptr es:26,seg Keyboard
在许多情况下,上面的程序都可以正确地执?但是如果上面的程序正在执行时H然敲下一个键的话,可能会(x)问题;而最p的?冉|发生:W三个MOV已经执行完毕,而第四个MOV未执行?如果在此时敲下Q何键的话,键盘中断矢量都没有Q何意?而造成整个p?l死?因此我们可以在设|中断矢量时,让中断无?譬如:
mov ax,0
mov es,ax
cli
mov word ptr es:24,offset Keyboard
mov word ptr es:26,seg Keyboard
上面的做法在大部分的情况下都可以正确地执?但是CLIq个指o(h)无法停止NMI中断(不可屏蔽中断),因此如果发生NMI中断时就 没用办法.下面的这一U做法虽然比较复?但是对于所有的中断都有?q包括了NMI中断在内:
mov word ptr kbd-ptr[0],offset Keyboard
mov word ptr kbd-ptr[2],seg Keyboard
mov di,0 ;Use Di to Set ES to zero
mov es,di ;Set ES to destination segment
mov di,24 ;Set DI to destination offset
mov si,offset kbdptr ;set SI to source offset
mov cx,2 ;Set word count to 2
cld ;Set direction to forward
cli ;Disable interrupts
rep movsw ;Copy the new vector
sti ;Enable interrupts
kbdptr dd ?
上面的程序中,kbdptr是两个字?WORD)的指?Pointer),其中包含了键?中断处理E序的v始志?REPq个指o(h)根据寄?器CX所讄的次数来重复执行MOVSW,而整个指令就如同单一的指令一?NMI中断不能够发生在一个完整的指o(h)?因ؓ(f)地址值搬Uȝ?作都能包含在一个单一指o(h)?因此可以免除M中断的干?
3.3.2 使用DOS来设|中断矢?
因ؓ(f)要想安全地设|中断矢量需要一些技?因此DOS提供了一特D的服务,以帮助程序h员安全地讄中断矢量,如果只?DOS所提供的这?a class="channel_keylink" >服务来设定中断矢量的?那么׃必担心会(x)发生前面所叙述的差?DOS同时也提供了:d中断矢量?a class="channel_keylink" >服务.因ؓ(f)?取中断矢量的内容不会(x)修改pȝ的状?因此若直接写E序d,也很安全.但是如果你要自己直接d中断矢量的内Ҏ(gu),必计?Z断矢量的位置.而DOS已经提供了这?a class="channel_keylink" >服务.
使用DOS所提供的系l调?来读取中断矢量的内容?必须利用INT 21H中的函数35H(d中断矢量),q个函数热气矢量L(fng)?计算中断矢量的地址,然后q回其中的内?以下是一个例?
Old_Keyboard_IO dd ?
mov al,16h
mov ah,35h
int 21h
mov word ptr Old_Keyboard_IO,bx ;Offset of interrupt handler
mov word ptr Old_Keyboard_IO,es ;Segment of interrupt handler
用DOS来设|中断矢量例?
New_Keyboard_IO dd ?
mov word ptr New_Keyboard_IO,bx ;Offset of interrupt handler
mov word ptr New_Keyboard_IO,es ;Segment of interrupt handler
mov al,16h
mov ah,25h
int 21h
3.4 (g)查中断矢?
q里都是采用COM格式~程,可以建立一个BAT文g来处理写好的E序,以减击键次?设BAT文g名ؓ(f)MAKE.BAT:
MASM %1
LINK %1
EXE2BIN %1.EXE %1.COM
如果写好的程序名为MACRO.ASM,则可敲入:
C:\MAKE MACRO.ASM
卛_.
3.5 昄中断矢量
下面q个例子可以列出所有的重要的中断矢量内?在刚刚打开PC?q且没有执行MȝE序?可以发现所有的中断矢量D值都相同,q些地址值所存放的是ROM的程?当你修改中断矢量之后,可以利用这个程序观察到中断矢量的变?以下是IVEC.ASM的内?
cseg segment para public 'CODE'
org 100h
jmp start
assume cs:cseg,ds:cseg
start:
mov bx,cs ;Make data seg be the same as
mov ds,bx ;the code seg
call vectors
waitIn:
mov ah,0bh
int 21h
cmp al,0ffh
jne waitIn
mov ah,4ch
int 21h
;****************************************************************************
;Scan through display table,prinying two vectors per line
;If any record has an interrupt #=zero,this indicates
;end of the table.
;****************************************************************************
mov di,offset disptab ;Pointer to start of table
mov dh,0 ;Zero out top half of DX
vloop:
mov dl,[di] ;Get the interrupt number
cmp dl,0 ;If it's zero,we are done
je vdone ;so exit loop
add di,1 ;Advance pointer 1 byte
mov si,[di] ;Get pointer to description
call dvector ;Call the display routine
add di,2 ;Get the interrupt number
mov dl,[di] ;Advance to the next record
cmp dl,0 ;If it's zero,we are done
je vdone ;so exit loop
add di,1 ;Advance pointer 1 byte
mov si,[di] ;get pointer to description
call dvector ;Call the display routine
add di,2 ;Advance to the next record
jmp vloop
vdone: ;Print final CRLF
ret
vectors endp
;----------------------------------------------------------------------------
;Displays an interrupt vector.Display is in the form of
;<banner>,<interrupt#>,<seg>:<offset>
;where <interrupt #>,<seg>and<offset>
;are all dexadecimal numbers
;Call with
;DX -interrupt number
;DS:SI -pointer to banner string
;----------------------------------------------------------------------------
dvector proc near
call dstring ;Display the string in DS:SI
call dbyte ;Display the byte in DL
call dspace ;Display a space
call dspace
;
mov al,dl ;move the interrupt number to AL
mov ah,35h ;Function is Get interrupt vector
int 21h
mov dx,bx ;Move BX to DX so we can display
call ddword ;double-word in ES:DX
call dEndFra
call dcrlf ;Display a newline
ret
dvector endp
;----------------------------------------------------------------------------
;DS:SI points to ASCII string to be printed
;----------------------------------------------------------------------------
dstring proc near
push si
push ax
dis: mov al,[si] ;Fetch the next character
cmp al,0 ;If it's zero,we are done
je disdone
call dchar ;If not,point it
inc si ;Advance pointer to nest char
jmp dis
disdone:pop ax
pop si
ret
dstring endp
;----------------------------------------------------------------------------
;ES:DX contains double word to be displayed
;----------------------------------------------------------------------------
ddword proc near
push dx ;Save offset temporarily
mov dx,es ;Move segment to DX
call dsword ;Display segment
call dcolon ;Print a ";"
; call dcrlf
pop dx ;Restore offset to DX
call dsword ;Display offset
ret
ddword endp
;----------------------------------------------------------------------------
;DX containes single word to be displayed
;----------------------------------------------------------------------------
dsword proc near
push dx ;Save low byte temporarily
mov dl,dh ;Move high byte to low byte
call dbyte ;Display high byte
pop dx ;Restore low byte to DL
call dbyte ;Display low byte
ret
dsword endp
;----------------------------------------------------------------------------
;DL contains byte to be displayed
;----------------------------------------------------------------------------
dbyte proc near
push ax ;Save any registers used
push dx
push si
push dx ;Save low nybble temporarily
push cx ;Save CX
mov cl,4 ;Set shift count to 4
shr dx,cl ;Shift high nybble into low nybble
and dx,0fh ;Mask out all but low nybble
mov si,dx ;Use low nybble as index into
mov al,hextab[si] ;hexadecimal character table
call dchar ;Display character
pop cx ;Restore CX
pop dx ;Restore low nybble
and dx,0fh ;Mask out all but low nybble
mov si,dx ;Use low nybble as an index into
mov al,hextab[si] ;hexadecimal character table
call dchar ;Display character
pop si ;Restore registers
pop dx
pop ax
ret
dbyte endp
;----------------------------------------------------------------------------
;Display a ":"
;----------------------------------------------------------------------------
dcolon proc near
mov al,':'
call dchar
ret
dcolon endp
;----------------------------------------------------------------------------
;Display a " "
;--
--------------------------------------------------------------------------
dspace proc near
mov al,' '
call dchar
ret
dspace endp
;----------------------------------------------------------------------------
;Display a Carriage Return/Line Feed
;----------------------------------------------------------------------------
dcrlf proc near
mov al,0dh
call dchar
mov al,0ah
call dchar
ret
dcrlf endp
;----------------------------------------------------------------------------
;Display the character contained in AL
;----------------------------------------------------------------------------
dchar proc near
push ax
push bx
mov bh,1
mov ah,0eh
int 10h
pop bx
pop ax
ret
dchar endp
;----------------------------------------------------------------------------
;Data define
;----------------------------------------------------------------------------
hextab db '0123456789ABCDEF',0
disptab db 05h ;Print screen
dw v05
db 19h ;Bootstrap loader
dw v19
db 08h ;Timer tick
dw v08
db 1ah ;Real_time clock
dw v1a
db 09h ;Keyboard input
dw v09
db 1bh ;CTRL_Break handler
dw v1b
db 0bh ;Comm.port 1
dw v0b
db 1ch ;Timer control
dw v1c
db 0ch ;Comm.port 0
dw v0c
db 1dh ;Pointer to video parameter table
dw v1d
db 0dh ;Hard disk controller
dw v0d
db 1eh ;Pointer to disk parameter table
dw v1e
db 0eh ;Floppy disk controller
dw v0e
db 1fh ;Pointer graphics character table
dw v1f
db 0fh ;Printer controller
dw v0f
db 20h ;Program terminate
dw v20
db 10h ;Video driver
dw v10
db 21h ;DOS universal function
dw v21
db 11h ;Equipment check
dw v11
db 22h ;Pointer to termination handler
dw v22
db 12h ;Memorey size check
dw v12
db 23h ;Pointer to Ctrl_C handler
dw v23
db 13h ;Disk driver
dw v13
db 24h ;Pointer to critical error handler
dw v24
db 14h ;Communications driver
dw v14
db 25h ;Absolute disk read
dw v25
db 15h ;Cassette driver
dw v15
db 26h ;Absolute disk write
dw v26
db 16h ;Keyboard driver
dw v16
db 27h ;Terminate and stay resident
dw v27
db 17h ;Printer driver
dw v17
db 2fh ;Print spooler
dw v2f
db 18h ;Rom basic
dw v18
db 0
dw 0
v05 db 186,5 dup (20h),'Print screen:',26 dup (20h),0
v08 db 186,5 dup (20h),'Timer tick controller:',17 dup (20h),0
v09 db 186,5 dup (20h),'Keyboard input:',24 dup (20h),0
v0b db 186,5 dup (20h),'Communication port 1:',18 dup (20h),0
v0c db 186,5 dup (20h),'Communication port 0:',18 dup (20h),0
v0d db 186,5 dup (20h),'Hard disk controller:',18 dup (20h),0
v0e db 186,5 dup (20h),'Floppy disk controller:',16 dup (20h),0
v0f db 186,5 dup (20h),'Printer controller:',20 dup (20h),0
v10 db 186,5 dup (20h),'Video driver:',26 dup (20h),0
v11 db 186,5 dup (20h),'Equipment check:',23 dup (20h),0
v12 db 186,5 dup (20h),'Memory size check:',21 dup (20h),0
v13 db 186,5 dup (20h),'Disk driver:',27 dup (20h),0
v14 db 186,5 dup (20h),'Communication driver:',18 dup (20h),0
v15 db 186,5 dup (20h),'Cassette driver:',23 dup (20h),0
v16 db 186,5 dup (20h),'Keyboard driver:',23 dup (20h),0
v17 db 186,5 dup (20h),'Printer driver:',24 dup (20h),0
v18 db 186,5 dup (20h),'ROM BASIC:',29 dup (20h),0
v19 db 186,5 dup (20h),'Bootstrap loader:',22 dup (20h),0
v1a db 186,5 dup (20h),'Real_time clock:',23 dup (20h),0
v1b db 186,5 dup (20h),'Ctrl_break handler:',20 dup (20h),0
v1c db 186,5 dup (20h),'Timer control:',25 dup (20h),0
v1d db 186,5 dup (20h),'Video parameter table:',17 dup (20h),0
v1e db 186,5 dup (20h),'Disk parameter:',24 dup (20h),0
v1f db 186,5 dup (20h),'Graphic character table:',15 dup (20h),0
v20 db 186,5 dup (20h),'Programe terminate:',20 dup (20h),0
v21 db 186,5 dup (20h),'DOS universal function:',16 dup (20h),0
v22 db 186,5 dup (20h),'Terminate vector:',22 dup (20h),0
v23 db 186,5 dup (20h),'Ctrl_C vector:',25 dup (20h),0
v24 db 186,5 dup (20h),'Critical error vector:',17 dup (20h),0
v25 db 186,5 dup (20h),'Absolute disk read:',20 dup (20h),0
v26 db 186,5 dup (20h),'Absolute disk write:',19 dup (20h),0
v27 db 186,5 dup (20h),'Terminate and stay resident:',11 dup (20h),0
v2f db 186,5 dup (20h),'Print spooler:',25 dup (20h),0
cseg ends
end start