`
lobin
  • 浏览: 383357 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

再谈x86中断

 
阅读更多

09H中断

09H中断实际上被称为键盘中断处理程序,它是一个硬件中断

 

09H中断处理程序

000fe987: (                    ): cli                       ; fa
000fe988: (                    ): push ax                   ; 50
000fe989: (                    ): mov al, 0xad              ; b0ad
000fe98b: (                    ): out 0x64, al              ; e664
000fe98d: (                    ): mov al, 0x0b              ; b00b
000fe98f: (                    ): out 0x20, al              ; e620
000fe991: (                    ): in al, 0x20               ; e420
000fe993: (                    ): and al, 0x02              ; 2402
000fe995: (                    ): jz .+64                   ; 7440
000fe997: (                    ): in al, 0x60               ; e460
000fe999: (                    ): sti                       ; fb
000fe99a: (                    ): push ds                   ; 1e
000fe99b: (                    ): pusha                     ; 60
000fe99c: (                    ): mov ah, 0x4f              ; b44f
000fe99e: (                    ): stc                       ; f9
000fe99f: (                    ): int 0x15                  ; cd15
000fe9a1: (                    ): push bp                   ; 55
000fe9a2: (                    ): mov bp, sp                ; 89e5
000fe9a4: (                    ): mov byte ptr ss:[bp+16], al ; 884610
000fe9a7: (                    ): pop bp                    ; 5d
000fe9a8: (                    ): jnb .+34                  ; 7322
000fe9aa: (                    ): push 0x0040               ; 6a40
000fe9ac: (                    ): pop ds                    ; 1f
000fe9ad: (                    ): cmp al, 0xe0              ; 3ce0
000fe9af: (                    ): jnz .+10                  ; 750a
000fe9b1: (                    ): mov al, byte ptr ds:0x0096 ; a09600
000fe9b4: (                    ): or al, 0x02               ; 0c02
000fe9b6: (                    ): mov byte ptr ds:0x0096, al ; a29600
000fe9b9: (                    ): jmp .+17                  ; eb11
000fe9bb: (                    ): cmp al, 0xe1              ; 3ce1
000fe9bd: (                    ): jnz .+10                  ; 750a
000fe9bf: (                    ): mov al, byte ptr ds:0x0096 ; a09600
000fe9c2: (                    ): or al, 0x01               ; 0c01
000fe9c4: (                    ): mov byte ptr ds:0x0096, al ; a29600
000fe9c7: (                    ): jmp .+3                   ; eb03
000fe9c9: (                    ): call .+27899              ; e8fb6c
000fe9cc: (                    ): popa                      ; 61
000fe9cd: (                    ): pop ds                    ; 1f
000fe9ce: (                    ): cli                       ; fa
000fe9cf: (                    ): call .-20389              ; e85bb0
000fe9d2: (                    ): mov ax, 0x9102            ; b80291
000fe9d5: (                    ): int 0x15                  ; cd15
000fe9d7: (                    ): mov al, 0xae              ; b0ae
000fe9d9: (                    ): out 0x64, al              ; e664
000fe9db: (                    ): pop ax                    ; 58
000fe9dc: (                    ): iret                      ; cf

 

 

BIOS中断

10H中断

https://www.iteye.com/blog/lobin-2047031

 

13H中断:磁盘中断。直接磁盘服务(Direct Disk Service)

 

13H扩展中断

 

INT 13 Extensions API

 

版本:

1.x

2.0 / EDD-1.0

2.1 / EDD-1.1

EDD-3.0

 

1.x版本

 

2.0 / EDD-1.0版本

 

2.1 / EDD-1.1版本

 

EDD-3.0版本

 

02H功能号:读扇区

入口参数:

AH=02H

AL=扇区数

CH=柱面

CL=扇区

DH=磁头

DL=驱动器, 00H~7FH:软盘; 80H~0FFH:硬盘

ES:BX=缓冲区的地址

 

出口参数:

CF=0:操作成功,AH=00H,AL=传输的扇区数;否则,AH=状态代码

 

由于读取的扇区数存放在AL寄存器中,所以最多只能读取255(2的8次方 - 1)个扇区.扇区大小为512字节,所以最多只能读取127.5K数据。

 

实际上,试图通过DMA访问跨越64K(65536字节,128个扇区)边界或者大于0x80(128)个扇区的话,就会报错,提示:

data boundary error (attempted DMA across 64K boundary or >80h sectors)

这种情况下,CF标志位置位,AH寄存器置为0x09.。

 

但我在实际实验中,在试图读取57个扇区的时候就出现了错误,在调试的时候发现CF标志位置位,AH寄存器置为0x09.。

 

在实际实验中,还遇到过在试图读取56个扇区的时候,在最后调用中断的时候,即int $0x13的时候,程序卡死在这个地方一直执行不下去,中断也不返回。

 

 

这里的扇区指的是扇区号,这里直接使用物理扇区号。物理扇区号从1开始,后面依次为2,3,4,...,所以第一个扇区的扇区号为1。

 

U_DATA_SEG	=	3000h

_text segment
	org	7c00h
_start:	
	; es, user data segment
	mov	dx, U_DATA_SEG
	mov	es, dx


	mov	ah, 02h	

	;mov	dl, 81h	; drive 0 驱动器 00H~7FH:软盘;80H~0FFH:硬盘 
	mov	dl, 80h
	;mov	dl, 0
	mov	dh, 0	; head 0 磁头
	mov	ch, 0	; track 柱面
	mov	cl, 1	; sector 扇区 

	mov	al, 1
	mov	bx, 0	; 将指定扇区读到es:bs位置
	int	13h

	jnc	read_sector_ok
	

read_sector_error:
	mov	si, m_read_sector_error
p1:
	mov	al, [si]
	add	si, 1
	cmp	al, 00h
	je	endl
	mov	ah, 0eh
	mov	bx, 0fh
	int	10h
	jmp	p1

read_sector_ok:
	mov	si, m_read_sector_ok
p0:
	mov	al, [si]
	add	si, 1
	cmp	al, 00h
	je	jmp_to
	mov	ah, 0eh
	mov	bx, 0fh
	int	10h
	jmp	p0


jmp_to:
	; jmp	3000h:0h
	;db	0eah		; jmp far
	;dw	0000h		; offset
	;dw	U_DATA_SEG	; segment: U_DATA_SEG = 3000h


	; jmp	3000h:0h
	;db	0eah			; jmp far
	;dw	0000h, U_DATA_SEG	; offset, segment. segment: U_DATA_SEG = 3000h


	; jmp	3000h:0h
offset_segment_jmp_to:	
	dw	0000h, U_DATA_SEG

	mov	ax, cs
	cmp	ax, U_DATA_SEG
	jz	_1
	jmp	dword ptr offset_segment_jmp_to
_1:
	jmp	dword ptr offset_segment_jmp_to - 7c00h
	
endl:
	hlt
	jmp endl

m_read_sector_ok:
	db	0ah, 0ah
	db	"[ook] read sector", 0dh, 0ah
	db	0ah, 0ah
	db	00h

m_read_sector_error:
	db	0ah, 0ah
	db	"[err] read sector", 0dh, 0ah
	db	0ah, 0ah
	db	00h

	; MBR扇区位于整个硬盘的第一个扇区.
	; 硬盘扇区为512字节,所以主引导程序大小仅能也只能512字节。
	db	510-($-seg _start) dup(0)
	; MBR结束标志
	db	85, 170	; 0x55, 0xaa
_text ends
	end	_start

 

 

 

上面的例子读磁盘MBR扇区将boot loader程序加载到3000h:0h,然后执行原跳转到3000h:0h继续执行boot loader程序,如此这样一直循环下去。

 

另外, 由于masm不支持jmp 3000h:0h写法,这里采用了2种方式来实现远距离跳转。

 

第一种方法:直接写机器码

	; jmp	3000h:0h
	;db	0eah		; jmp far
	;dw	0000h		; offset
	;dw	U_DATA_SEG	; segment: U_DATA_SEG = 3000h


	; jmp	3000h:0h
	;db	0eah			; jmp far
	;dw	0000h, U_DATA_SEG	; offset, segment. segment: U_DATA_SEG = 3000h

 

 

第二种方法:采用远距离间接地址跳转

 

	; jmp	3000h:0h
offset_segment_jmp_to:	
	dw	0000h, U_DATA_SEG

	mov	ax, cs
	cmp	ax, U_DATA_SEG
	jz	_1
	jmp	dword ptr offset_segment_jmp_to
_1:
	jmp	dword ptr offset_segment_jmp_to - 7c00h

在第二种方式中,由于MBR扇区的boot loader程序被加载到0000h:4c00h处执行,而在读磁盘加载

MBR扇区的boot loader程序时是加载到3000h:0h处,当cs为0000h时,计算出的offset_segment_jmp_to的偏移地址是正常的,当cs为3000h时,需要在原来计算出的offset_segment_jmp_to的偏移减去7c00h才是正确的偏移地址。

 

 

41H功能号:检查13H扩展中断是否支持

 

Int 13/AH=41h/BX=55AAh,IBM/MS INT 13 Extensions - INSTALLATION CHECK

在Bochs中不支持该中断,如果使用了该中断的话,会打印如下一条日志:

00014042366i[BIOS  ] int13_diskette: unsupported AH=41

 

int13_ext_check:
	mov	$0x41, %ah
	mov	$0x55aa, %bx
	mov	$0x00, %dl
	int	$0x13

	jnc	bprint_int13_extensions_not_supported

 

 

42H功能号:读扇区

Int 13/AH=42h,该中断为int 13扩展中断:IBM/MS INT 13 Extensions - EXTENDED READ

在Bochs中不支持该中断,如果使用了该中断的话,会打印如下一条日志:

00014042363i[BIOS  ] int13_diskette: unsupported AH=42

int13_42h:
	jmp	int13_42h_begin
init_disk_address_packet:
	.byte	0x10
	.byte	0x00
	.word	k_kernel_size_in_sector

	.word	k_seg
	.word	k_offset

	.word	0x02
	.word	0x00
	.word	0x00
	.word	0x00
int13_42h_begin:
	mov	$0x42, %ah
	mov	$0x00, %dl
	mov	$init_disk_address_packet, %si
	int	$0x13
	jnc	bprint_setup_load_error

	jmp	bprint_setup_load_error

 

 

15H中断

获取内存信息

 

16H中断

键盘I/O中断

另一个和键盘相关的中断是09H中断。09H中断实际上被称为键盘中断处理程序,它是一个硬件中断,而16H中断是一个软件中断。

 

00H功能号:读键盘.从键盘读入字符

	.model small

.data
	press_any_key_to_continue	db 'Press any key to continue...', 0dh, 0ah, '$'


.code
_start:	
	mov	ax, _data
	mov	ds, ax


	mov	dx, offset press_any_key_to_continue
	mov	ah, 9
	int	21h

	; wait key for input
	mov	ah, 00h
	int	16h
_ret:
	mov	ah, 4ch
	mov	al, 0
	int	21h
end _start

 

 

 

21H中断:DOS系统调用中断

 

系统调用功能主要包括程序终止,键盘I/O,显卡显示I/O,通讯I/O,打印机I/O,控制台I/O,磁盘I/O,文件I/O,中断向量操作,段操作,日期时间设置,获取DOS信息,信号(Ctrl-Break)处理,本地(Locale)信息,设备文件I/O,内存管理,程序装载执行,程序返回等。

 

09H功能号:输出字符串

segment data
	message db 'Welcome!' , 0dh, 0ah
		db 'X2', 0dh, 0ah
		db 'version: 1.0.0 2010-02-14 Express Edition', 0dh, 0ah
		db '(c) Next G', 0dh, 0ah
	end1	db '$'

segment code 
; ..start:	
_start:
	mov     ax,data 
        mov     ds,ax 

	mov dx, message
	mov ah, 09h
	int 21h

	mov ah, 4ch
	int 21h

3FH功能号:读文件或设备

参数:

DS:DX数据缓冲区地址

BX文件代号

CX读取的字节数

 

成功返回:

AX实际读入的字节数

如果AX为0,除非CX指定0(读取0字节),否则表示已读到文件尾(EOF)。

 

出错返回:

AX错误码

 

注意:

如果CX指定0(读取0字节),调用中断不会出错,也不会读取任何数据,返回时AX为0。

 

打开/关闭文件

mov ax, _DATA
mov ds, ax

mov dx, offset f_name

; ah指定3dh表示打开文件,al指定文件打开方式,0表示读,1表示写,3表示读写
; 可以写成如下这样:
; mov ax, 3d00h
; 也可以分开分别设置ah和al
mov ah, 3dh
mov al, 0h
int 21h

 

; 关闭文件
mov ah, 3eh
mov bx, f_hanele
int 21h

 

 

; 打开/关闭文件
; 21H DOS系统调用中断
; 3DH功能号:打开文件
; 3EH功能号:关闭文件
	.model small

.data 
	f_buf	db 1024 dup(0)
	; 要打开的文件路径,以00h或'$'为结束符
	f_name	db 'int21_3d.txt', '$' ; INT21_3D.TXT
	f_handle dw ?
	_ax DB  'ab', 30 DUP(0), '$'
	f_open_ok db 'file open success!', 0dh, 0ah, '$'
	f_open_error db 'file open error!', 0dh, 0ah, '$'
	f_close_ok db 'file close success!', 0dh, 0ah, '$'
	f_close_error db 'file close error!', 0dh, 0ah, '$'
	f_name_label db 'file name: ', '$'
	CRLF DB 0Dh, 0Ah, '$'
.code _proc
; proc ascii
ascii	proc	far
	mov	si,   10
next:	xor	dx,   dx
	div	si
	add	dx,   '0'
	dec	bx
	mov	[bx], dl
	or	ax,   ax
	jnz	next
	ret
ascii	endp

.code 
	; ds:dx 表示打开文件的地址
	; 如果打开文件成功,CF标志位被清除(0)
	; 否则,打开文件失败, CF标志位被设置(1),AX寄存器存放分配失败的错误码,根据该错误码判断原因
	; 
start:	mov ax, _DATA
	mov ds, ax

	mov dx, offset f_name

	; ah指定3dh表示打开文件,al指定文件打开方式,0表示读,1表示写,3表示读写
	; 可以写成如下这样:
	; mov ax, 3d00h
	; 也可以分开分别设置ah和al
	mov ah, 3dh
	mov al, 0h
	int 21h

	mov f_handle, ax

	; proc ascii call requires registers ax and bx
	;mov ax, ax
	;mov bx, offset _ax + 29
	;call far ptr ascii

	; the offset of string in register dx
	; 输出字符串,直到结束符'$'
	;mov dx, offset _ax      ; mov dx, offset FLAT:message 

	;mov ah, 9 ; print _ax
	;int 21h   ; 21h

	jnc io_o_ok
	
	; the offset of string in register dx
	; 输出字符串,直到结束符'$'
	mov dx, offset f_open_error 

	mov ah, 9 ; 
	int 21h   ; 21h

	jmp _ret

io_o_ok:; the offset of string in register dx
	; 输出字符串,直到结束符'$'
	mov dx, offset f_open_ok 

	mov ah, 9 ;
	int 21h   ; 21h

	; the offset of string in register dx
	; 输出字符串,直到结束符'$'
	mov dx, offset f_name_label

	mov ah, 9 ;
	int 21h   ; 21h

	; the offset of string in register dx
	; 输出字符串,直到结束符'$'
	mov dx, offset f_name

	mov ah, 9 ;
	int 21h   ; 21h

	; the offset of string in register dx
	; 输出字符串,直到结束符'$'
	mov dx, offset CRLF

	mov ah, 9 ;
	int 21h   ; 21h

	; 关闭文件
	mov ah, 3eh
	mov bx, f_handle
	int 21h

	jnc io_close_ok

	; the offset of string in register dx
	; 输出字符串,直到结束符'$'
	mov dx, offset f_close_error 

	mov ah, 9 ; 
	int 21h   ; 21h

	jmp _ret
io_close_ok:	
	; the offset of string in register dx
	; 输出字符串,直到结束符'$'
	mov dx, offset f_close_ok 

	mov ah, 9 ; 
	int 21h   ; 21h

_ret:	mov ah, 4ch
	mov al, 0 ; 指定返回码。类似C/C++在main函数中返回0,和调用exit(0)函数
	int 21h
end start

 

打开/读取文件

; 打开/读取文件
; 21H DOS系统调用中断
; 3DH功能号:打开文件
; 3FH功能号:读取文件
	.model small

.data 
	f_buf	db 1024 dup(0), '$'
	; 要打开的文件路径,以00h或'$'为结束符
	f_name	db 'int21_3d.txt', '$' ; INT21_3D.TXT
	f_handle dw ?
	_ax DB  'ab', 30 DUP(0), '$'
	f_open_ok db 'file open success!', 0dh, 0ah, '$'
	f_open_error db 'file open error!', 0dh, 0ah, '$'
	f_close_ok db 'file close success!', 0dh, 0ah, '$'
	f_close_error db 'file close error!', 0dh, 0ah, '$'
	f_name_label db 'file name: ', '$'
	f_data_label db 'file content: ', 0dh, 0ah, '$'
	CRLF DB 0Dh, 0Ah, '$'

.code _proc
; proc ascii
ascii	proc	far
	mov	si,   10
next:	xor	dx,   dx
	div	si
	add	dx,   '0'
	dec	bx
	mov	[bx], dl
	or	ax,   ax
	jnz	next
	ret
ascii	endp

.code 
	; ds:dx 表示打开文件的地址
	; 如果打开文件成功,CF标志位被清除(0)
	; 否则,打开文件失败, CF标志位被设置(1),AX寄存器存放分配失败的错误码,根据该错误码判断原因
	; 
start:	mov ax, _DATA
	mov ds, ax

	; the offset of string in register dx
	; 输出字符串,直到结束符'$'
	mov dx, offset f_name

	; ah指定3dh表示打开文件,al指定文件打开方式,0表示读,1表示写,3表示读写
	; 可以写成如下这样:
	; mov ax, 3d00h
	; 也可以分开分别设置ah和al
	mov ah, 3dh
	mov al, 0h
	int 21h

	mov f_handle, ax

	; proc ascii call requires registers ax and bx
	;mov ax, ax
	;mov bx, offset _ax + 29
	;call far ptr ascii

	; the offset of string in register dx
	; 输出字符串,直到结束符'$'
	;mov dx, offset _ax      ; mov dx, offset FLAT:message 

	;mov ah, 9 ; print _ax
	;int 21h   ; 21h

	jnc io_ok
	
	; the offset of string in register dx
	; 输出字符串,直到结束符'$'
	mov dx, offset f_open_error 

	mov ah, 9 ; 
	int 21h   ; 21h

	jmp _ret

io_ok:	; the offset of string in register dx
	; 输出字符串,直到结束符'$'
	mov dx, offset f_open_ok 

	mov ah, 9 ;
	int 21h   ; 21h

	; the offset of string in register dx
	; 输出字符串,直到结束符'$'
	mov dx, offset f_name_label

	mov ah, 9 ;
	int 21h   ; 21h

	; the offset of string in register dx
	; 输出字符串,直到结束符'$'
	mov dx, offset f_name

	mov ah, 9 ;
	int 21h   ; 21h

	; the offset of string in register dx
	; 输出字符串,直到结束符'$'
	mov dx, offset CRLF

	mov ah, 9 ;
	int 21h   ; 21h

	; the offset of string in register dx
	; 输出字符串,直到结束符'$'
	mov dx, offset f_data_label

	mov ah, 9 ;
	int 21h   ; 21h


	mov ah, 3fh
	mov bx, f_handle
	mov dx, offset f_buf
	mov cx, 1024
	int 21h

	; the offset of string in register dx
	; 输出字符串,直到结束符'$'
	mov dx, offset f_buf

	mov ah, 9 ;
	int 21h   ; 21h

	; the offset of string in register dx
	; 输出字符串,直到结束符'$'
	mov dx, offset CRLF

	mov ah, 9 ;
	int 21h   ; 21h

	; 关闭文件
	mov ah, 3eh
	mov bx, f_handle
	int 21h

	jnc io_close_ok

	; the offset of string in register dx
	; 输出字符串,直到结束符'$'
	mov dx, offset f_close_error 

	mov ah, 9 ; 
	int 21h   ; 21h

	jmp _ret
io_close_ok:	
	; the offset of string in register dx
	; 输出字符串,直到结束符'$'
	mov dx, offset f_close_ok 

	mov ah, 9 ; 
	int 21h   ; 21h

_ret:	mov ah, 4ch
	mov al, 0 ; 指定返回码。类似C/C++中main函数返回0,或调用exit(0)函数退出程序
	int 21h
end start

 

  • 大小: 85.2 KB
  • 大小: 8.9 KB
  • 大小: 24 KB
  • 大小: 9.7 KB
  • 大小: 12.6 KB
  • 大小: 18.7 KB
  • 大小: 21.3 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics