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
相关推荐
例如,在x86架构中,使用APIC(Advanced Programmable Interrupt Controller)来管理中断。 #### 五、MSI/MSI-X中断机制 MSI/MSI-X中断机制的核心在于利用消息而非电平变化来触发中断。这种方式避免了传统中断方式中...
浅谈嵌入式处理器体系结构的论文主要介绍了嵌入式处理器的体系结构与性能,分析了嵌入式处理器对嵌入式系统性能的影响及发展趋势。论文首先介绍了流行的嵌入式处理器体系结构,如8051、ARM、MIPS、PowerPC、DSP、...
每个子目录代表了一种支持的体系结构,例如`i386`表示x86架构的支持。 #### 三、方法之二:以程序流程为线索,一线串珠 此方法强调从程序执行的逻辑流程出发来理解内核的工作机制。通过追踪程序的执行路径,可以更...
### Linux内核分析方法谈 #### 一、引言 Linux作为一款开源操作系统,其内核源码的公开性吸引了无数计算机爱好者和技术人员的关注。深入分析Linux内核不仅能增进我们对计算机底层工作原理的理解,还能让我们学习到...
对于带有FPU的处理器,如X86架构,Linux内核默认使用`-msoft-float`编译选项,这意味着内核编译为软浮点程序,即依赖于GCC编译器模拟浮点运算。然而,这并不意味着内核本身的性能受到影响,因为内核代码中通常较少...
2. **指令系统**:了解不同处理器(如Intel x86或ARM)的指令集,包括数据处理指令、转移指令、输入输出指令等。 3. **寄存器**:学习CPU内部寄存器的作用,如AX、BX、CX、DX、SP、BP、SI、DI等,以及它们在运算...
在单处理器系统中,能够在单条指令中完成的操作都可以认为是"原子操作",因为中断只能发生于指令之间(因为线程的调度需要通过中断完成)。在对称多处理器结构中,系统中有多个处理器在独立地运行,即使能在单条指令...
在x86-64架构中,页表项中通常包含许多用于控制内存访问权限的标志位,其中第1位(通常称为Read/Write位)控制着对应的内存页是否可写。当这个位为0时,表明该内存页是只读的。 然而,问题是为什么在这个只读的页上...