原文链接:
http://www.cnblogs.com/ljf9201314/archive/2008/07/21/1247653.html
BIOS INT 10-13功能调用的“另类”玩法
Native API、Win32 API 或是早年间学习汇编时接触的 DOS int 21 都不如 BIOS 的中断调用来的直接。
闲暇之余,学写写BIOS的调用代码也还是很好玩的,反正我很喜欢。
还有,现在越来越佩服写BIOS的人了~
今天的代码是吃中饭后,眯午觉前写的。没有技术含量,权当是准备迎第23个中秋节~
原来我在实验 BIOS int 10号中断-13号功能调用 "AL写模式位" 的时候都是采用 "bit 1位" 置0的方法。而这带来的后果就是 —— 某字符串中的每一个字符都(不得不)具有同样的颜色属性 —— 如果我想让字符串里第一个字符是蓝色,第二个字符是红色是没有办法实现的。所以,这 对于“非标准方法爱好者”来说是很不爽的~
So,修改之。只要 "AL寄存器 bit 1位" 置1,且字符串包含交替的字符和属性就可以了,小玩意~ 正好够一个中午的时间。
先来一些“教条”做背景:
在Ralf Brown前辈的《Interrupt List》是这么描述 BIOS INT 10-13的
---------------------------------------------------------------
INT 10 13-- - VIDEO - WRITE STRING (AT and later,EGA)
Inp.:
AH = 13h
AL = write mode
bit 0: update cursor after writing
bit 1: string contains alternating characters and attributes
bits 2-7: reserved (0)
BH = page number
BL = attribute if string contains only characters
CX = number of characters in string
DH,DL = row,column at which to start writing
ES:BP -> string to write
Return: nothing
Notes: recognizes CR, LF, BS, and bell; for the ET4000 BIOS, scrolling,
backspace, and CR only take place in the active page
also available PC or XT with EGA or higher
HP 95LX only supports write mode 00h
IBM documents AL=10h,11h,20h,21h as "private" rather than "reserved"
BUG: on the IBM VGA Adapter, any scrolling which may occur is performed on
the active page rather than the requested page
SeeAlso: AH=09h,AH=0Ah,AH=13h"DOS/V"
[代码及玩法如下]
----------------
将代码编译成Bin文件后,读写引导扇区并做成虚拟软盘镜像,在Bochs或VMWare中启动,就能看到效果了
(就像tiamo前辈所说的那样,在有源代码的情况下,合格的程序员不应该被编译/编译选项难倒~)
PS: 代码里还用到了 BIOS INT 10号中断-06号功能调用 —— 清屏(屏幕向上滚动)
; ============================================ ;
; .: keenjoy95 2007 :. ;
; .: keenjoy95_at_gmail_dot_com :. ;
; -------------------------------------------- ;
; 代码描述 : 引导扇区演示程序 ;
; 编译方法 : nasm boot.asm -o boot.bin ;
; ============================================ ;
; 为了对齐的美观, 下面的代码向前进缩了一些...
org 07c00h ; ORG伪指令也被称为程序起始地址伪指令 / 定位伪指令
; 该伪指令用于指示编译器(链接器)将其后续代码(段)定位于指定地址
; 由于本示例是引导扇区演示程序,所以目标定位地址为0000:7c00h
jmp MYOS_ENTRY ; 无条件跳转到程序的入口点MYOS_ENTRY标号处
BootMessage:
db 0x07 ; "Beep"
dw 0x1048 ; "H" (蓝底 黑字)
dw 0x1465 ; "e" (蓝底 红字)
dw 0x1f6c ; "l" (蓝底 白字)
dw 0x126c ; "l" (蓝底 绿字)
dw 0x166f ; "o" (蓝底 棕字)
dw 0xfc2c ; "," (白底浅红字)
dw 0xf020 ; " " (白底 黑字)
dw 0x4b4d ; "M" (红底浅青字)
dw 0x4179 ; "y" (红底 蓝字)
dw 0x404f ; "O" (红底 黑字)
dw 0x4f53 ; "S" (红底 白字)
dw 0x4c21 ; "!" (红底浅红字)
db 0x07 ; "Beep"
ScrollWindows:
mov ax, 0600h ; AH 赋值为功能号06h(窗口上滚) (BIOS INT 10-06h 定义参数)
; AL 赋值为0, 窗口信息全部移出(清屏) (BIOS INT 10-06h 定义参数)
mov bx, 0700h ; BH 底部空白行属性赋值为黑底灰白字 (BIOS INT 10-06h 定义参数)
; BL 保留
mov cx, 0000h ; 窗口左上角的行列、号赋值为00h 00h (BIOS INT 10-06h 定义参数)
mov dx, 184fh ; 窗口右下角的行列、号赋值为18h 4fh (BIOS INT 10-06h 定义参数)
; ---------------------------------------------------
; 0(00h) 79(4fh)
; 0(00h)┏━━━━━━━━━━━━━━━━┓
; ┃ ┃
; ┃ ┃
; ┃ ┃
; ┃ 显示器 25*80 显示方式 ┃
; ┃ ┃
; ┃ ┃
; ┃ ┃
; 24(18h)┗━━━━━━━━━━━━━━━━┛
;
int 10h ; BIOS 10h号中断-06h号功能 (清屏功能调用)
ret ; 子程序无参数返回
DisplayString:
mov ax, BootMessage ; 取字符串数据(段)的首地址
mov bp, ax ; ES:BP 赋值为待显示字符串的首地址 (BIOS INT 10-13h 定义参数)
mov cx, 14 ; CX 赋值为字符串长度(此处为固定值) (BIOS INT 10-13h 定义参数)
mov ax, 01303h ; AH 赋值为功能号13h(显示字符串) (BIOS INT 10-13h 定义参数)
; AL 输出模式参数赋值为03h (BIOS INT 10-13h 定义参数)
; ---------------------------------------------------
; 第 0 位 : 在输出之后更新光标位置
; 第 1 位 : 字符串包含交替的字符和属性
;
mov bx, 0000h ; BH 页号赋值为0 (BIOS INT 10-13h 定义参数)
; BL 属性赋值为黑底浅红字(属性字BL使用的前提为AL的高位置0)
; ---------------------------------------------------
; 16位色彩编码表 (D7 D6 D5 D4为背景色,D3 D2 D1 D0为前景色)
; ┏━━━━━━━━━━━┳━━━━━━━━━━━┓
; ┃ 0 0 0 0 黑 ┃ 1 0 0 0 灰 ┃
; ┃ 0 0 0 1 蓝 ┃ 1 0 0 1 浅蓝 ┃
; ┃ 0 0 1 0 绿 ┃ 1 0 1 0 浅绿 ┃
; ┃ 0 0 1 1 青 ┃ 1 0 1 1 浅青 ┃
; ┃ 0 1 0 0 红 ┃ 1 1 0 0 浅红 ┃
; ┃ 0 1 0 1 品红 ┃ 1 1 0 1 浅品红 ┃
; ┃ 0 1 1 0 棕 ┃ 1 1 1 0 黄 ┃
; ┃ 0 1 1 1 灰白 ┃ 1 1 1 1 白 ┃
; ┗━━━━━━━━━━━┻━━━━━━━━━━━┛
;
mov dx, 0000h ; DL 赋值为字符串显示的起始行、列号 (BIOS INT 10-13h 定义参数)
int 10h ; BIOS 10h号中断-13h号功能 (字符串屏显功能调用)
ret ; 子程序无参数返回
MYOS_ENTRY:
mov ax, cs ; ┓
mov ds, ax ; ┣ 段寄存器初始化
mov es, ax ; ┛
call ScrollWindows ; 调用清屏子程序
call DisplayString ; 调用字符串显示子程序
jmp $ ; 主程序进入无限循环
MYOS_PAD:
times 510-($-$$) db 0 ; 循环填充剩余空间,使生成的二进制代码大小恰好为一个扇区(512Byte)
dw 0xAA55 ; 引导扇区结束标志
; ---8<----------- [Cut Here] ----------->8--- ;
; .: keenjoy95 2007 :. ;
; .: keenjoy95_at_gmail_dot_com :. ;
; ! NO rights reserved ! ;
; -------------------------------------------- ;
如你所见,每一个输出的字符都可以拥有不同的“背景色”和“前景色”~
代码的注释里我给出了16位的色彩编码表。
然后(也就是现在),小的我眯过午觉了~
再反汇编学习一下,我知道这个很“弱智”,不过~人嘛,都是从弱智开始的,更何况ndisasm反汇编功能更弱智~ :P
; ==================================================== ;
; .: keenjoy95 2007 :. ;
; .: keenjoy95_at_gmail_dot_com :. ;
; ---------------------------------------------------- ;
; 代码描述 : 引导扇区演示程序反汇编 ;
; 逆向方法 : ;
; ndisasm -o 0x7c00 boot.bin >> disboot.asm ;
; ndisasm -o 0x7c00 -k 3,26 boot.bin >> disboot.asm ;
; ==================================================== ;
00007C00 E93D00 jmp 0x7c40 ; 无条件跳转到程序的入口点
; 跳转的指令是"E9 3D00" (地址偏移是003D, 向后
; 跳61D/0x3DH个字节)
;------------------------------------------------------;
; * 下面是错误的反汇编 —— 数据段 * ;
;------------------------------------------------------; "Hello, MyOS!"
00007C03 07 pop es ; "Beep"
00007C04 48 dec ax ; "H"
00007C05 106514 adc [di+0x14],ah ; (0x10) | "e" | (0x14)
00007C08 6C insb ; "l"
00007C09 1F pop ds ; (0x1f)
00007C0A 6C insb ; "l"
00007C0B 126F16 adc ch,[bx+0x16] ; (0x12) | "o" | (0x16)
00007C0E 2CFC sub al,0xfc ; "," | (0xfc)
00007C10 20F0 and al,dh ; " " | (0xf0)
00007C12 4D dec bp ; "M"
00007C13 4B dec bx ; (0x4b)
00007C14 7941 jns 0x7c57 ; "y" | (0x41)
00007C16 4F dec di ; "O"
00007C17 40 inc ax ; (0x40)
00007C18 53 push bx ; "S"
00007C19 4F dec di ; (0x4f)
00007C1A 214C07 and [si+0x7],cx ; "!" | (0x4c) | "Beep"
;------------------------------------------------------;
; * 代 码 段 * ;
;------------------------------------------------------;
00007C1D B80006 mov ax,0x600 ; ┓
00007C20 BB0007 mov bx,0x700 ; ┃
00007C23 B90000 mov cx,0x0 ; ┣ 清屏子程序
00007C26 BA4F18 mov dx,0x184f ; ┃
00007C29 CD10 int 0x10 ; ┛
00007C2B C3 ret ; 子程序无参数返回
00007C2C B8037C mov ax,0x7c03 ; ┓
00007C2F 89C5 mov bp,ax ; ┃
00007C31 B90E00 mov cx,0xe ; ┃
00007C34 B80313 mov ax,0x1303 ; ┣ 字符串显示子程序
00007C37 BB0000 mov bx,0x0 ; ┃
00007C3A BA0000 mov dx,0x0 ; ┃
00007C3D CD10 int 0x10 ; ┛
00007C3F C3 ret ; 子程序无参数返回
00007C40 8CC8 mov ax,cs ; ┓
00007C42 8ED8 mov ds,ax ; ┣ 段寄存器初始化
00007C44 8EC0 mov es,ax ; ┛
00007C46 E8D4FF call 0x7c1d ; 跳转的指令是"E8 D4FF" (地址偏移是FFD4, 向前
; 跳44D/0x2CH个字节)
00007C49 E8E0FF call 0x7c2c ; 跳转的指令是"E8 E0FF" (地址偏移是FFE0, 向前
; 跳32D/0x20H个字节)
00007C4C EBFE jmp short 0x7c4c ; 主程序进入无限循环
; 跳转的指令是"E8 FE" (地址偏移是00FE, 向前
; 跳2D个字节, 进入死循环)
;------------------------------------------------------;
; * 下面是错误的反汇编 —— 引导区填充段及结束标志 * ;
;------------------------------------------------------;
00007C4E 0000 add [bx+si],al
00007C50 0000 add [bx+si],al
00007C52 0000 add [bx+si],al
00007C54 0000 add [bx+si],al
00007C56 0000 add [bx+si],al
00007C58 0000 add [bx+si],al
00007C5A 0000 add [bx+si],al
00007C5C 0000 add [bx+si],al
00007C5E 0000 add [bx+si],al
00007C60 0000 add [bx+si],al
00007C62 0000 add [bx+si],al
00007C64 0000 add [bx+si],al
00007C66 0000 add [bx+si],al
00007C68 0000 add [bx+si],al
00007C6A 0000 add [bx+si],al
00007C6C 0000 add [bx+si],al
00007C6E 0000 add [bx+si],al
00007C70 0000 add [bx+si],al
00007C72 0000 add [bx+si],al
00007C74 0000 add [bx+si],al
00007C76 0000 add [bx+si],al
00007C78 0000 add [bx+si],al
00007C7A 0000 add [bx+si],al
00007C7C 0000 add [bx+si],al
00007C7E 0000 add [bx+si],al
00007C80 0000 add [bx+si],al
00007C82 0000 add [bx+si],al
00007C84 0000 add [bx+si],al
00007C86 0000 add [bx+si],al
00007C88 0000 add [bx+si],al
00007C8A 0000 add [bx+si],al
00007C8C 0000 add [bx+si],al
00007C8E 0000 add [bx+si],al
00007C90 0000 add [bx+si],al
00007C92 0000 add [bx+si],al
00007C94 0000 add [bx+si],al
00007C96 0000 add [bx+si],al
00007C98 0000 add [bx+si],al
00007C9A 0000 add [bx+si],al
00007C9C 0000 add [bx+si],al
00007C9E 0000 add [bx+si],al
00007CA0 0000 add [bx+si],al
00007CA2 0000 add [bx+si],al
00007CA4 0000 add [bx+si],al
00007CA6 0000 add [bx+si],al
00007CA8 0000 add [bx+si],al
00007CAA 0000 add [bx+si],al
00007CAC 0000 add [bx+si],al
00007CAE 0000 add [bx+si],al
00007CB0 0000 add [bx+si],al
00007CB2 0000 add [bx+si],al
00007CB4 0000 add [bx+si],al
00007CB6 0000 add [bx+si],al
00007CB8 0000 add [bx+si],al
00007CBA 0000 add [bx+si],al
00007CBC 0000 add [bx+si],al
00007CBE 0000 add [bx+si],al
00007CC0 0000 add [bx+si],al
00007CC2 0000 add [bx+si],al
00007CC4 0000 add [bx+si],al
00007CC6 0000 add [bx+si],al
00007CC8 0000 add [bx+si],al
00007CCA 0000 add [bx+si],al
00007CCC 0000 add [bx+si],al
00007CCE 0000 add [bx+si],al
00007CD0 0000 add [bx+si],al
00007CD2 0000 add [bx+si],al
00007CD4 0000 add [bx+si],al
00007CD6 0000 add [bx+si],al
00007CD8 0000 add [bx+si],al
00007CDA 0000 add [bx+si],al
00007CDC 0000 add [bx+si],al
00007CDE 0000 add [bx+si],al
00007CE0 0000 add [bx+si],al
00007CE2 0000 add [bx+si],al
00007CE4 0000 add [bx+si],al
00007CE6 0000 add [bx+si],al
00007CE8 0000 add [bx+si],al
00007CEA 0000 add [bx+si],al
00007CEC 0000 add [bx+si],al
00007CEE 0000 add [bx+si],al
00007CF0 0000 add [bx+si],al
00007CF2 0000 add [bx+si],al
00007CF4 0000 add [bx+si],al
00007CF6 0000 add [bx+si],al
00007CF8 0000 add [bx+si],al
00007CFA 0000 add [bx+si],al
00007CFC 0000 add [bx+si],al
00007CFE 0000 add [bx+si],al
00007D00 0000 add [bx+si],al
00007D02 0000 add [bx+si],al
00007D04 0000 add [bx+si],al
00007D06 0000 add [bx+si],al
00007D08 0000 add [bx+si],al
00007D0A 0000 add [bx+si],al
00007D0C 0000 add [bx+si],al
00007D0E 0000 add [bx+si],al
00007D10 0000 add [bx+si],al
00007D12 0000 add [bx+si],al
00007D14 0000 add [bx+si],al
00007D16 0000 add [bx+si],al
00007D18 0000 add [bx+si],al
00007D1A 0000 add [bx+si],al
00007D1C 0000 add [bx+si],al
00007D1E 0000 add [bx+si],al
00007D20 0000 add [bx+si],al
00007D22 0000 add [bx+si],al
00007D24 0000 add [bx+si],al
00007D26 0000 add [bx+si],al
00007D28 0000 add [bx+si],al
00007D2A 0000 add [bx+si],al
00007D2C 0000 add [bx+si],al
00007D2E 0000 add [bx+si],al
00007D30 0000 add [bx+si],al
00007D32 0000 add [bx+si],al
00007D34 0000 add [bx+si],al
00007D36 0000 add [bx+si],al
00007D38 0000 add [bx+si],al
00007D3A 0000 add [bx+si],al
00007D3C 0000 add [bx+si],al
00007D3E 0000 add [bx+si],al
00007D40 0000 add [bx+si],al
00007D42 0000 add [bx+si],al
00007D44 0000 add [bx+si],al
00007D46 0000 add [bx+si],al
00007D48 0000 add [bx+si],al
00007D4A 0000 add [bx+si],al
00007D4C 0000 add [bx+si],al
00007D4E 0000 add [bx+si],al
00007D50 0000 add [bx+si],al
00007D52 0000 add [bx+si],al
00007D54 0000 add [bx+si],al
00007D56 0000 add [bx+si],al
00007D58 0000 add [bx+si],al
00007D5A 0000 add [bx+si],al
00007D5C 0000 add [bx+si],al
00007D5E 0000 add [bx+si],al
00007D60 0000 add [bx+si],al
00007D62 0000 add [bx+si],al
00007D64 0000 add [bx+si],al
00007D66 0000 add [bx+si],al
00007D68 0000 add [bx+si],al
00007D6A 0000 add [bx+si],al
00007D6C 0000 add [bx+si],al
00007D6E 0000 add [bx+si],al
00007D70 0000 add [bx+si],al
00007D72 0000 add [bx+si],al
00007D74 0000 add [bx+si],al
00007D76 0000 add [bx+si],al
00007D78 0000 add [bx+si],al
00007D7A 0000 add [bx+si],al
00007D7C 0000 add [bx+si],al
00007D7E 0000 add [bx+si],al
00007D80 0000 add [bx+si],al
00007D82 0000 add [bx+si],al
00007D84 0000 add [bx+si],al
00007D86 0000 add [bx+si],al
00007D88 0000 add [bx+si],al
00007D8A 0000 add [bx+si],al
00007D8C 0000 add [bx+si],al
00007D8E 0000 add [bx+si],al
00007D90 0000 add [bx+si],al
00007D92 0000 add [bx+si],al
00007D94 0000 add [bx+si],al
00007D96 0000 add [bx+si],al
00007D98 0000 add [bx+si],al
00007D9A 0000 add [bx+si],al
00007D9C 0000 add [bx+si],al
00007D9E 0000 add [bx+si],al
00007DA0 0000 add [bx+si],al
00007DA2 0000 add [bx+si],al
00007DA4 0000 add [bx+si],al
00007DA6 0000 add [bx+si],al
00007DA8 0000 add [bx+si],al
00007DAA 0000 add [bx+si],al
00007DAC 0000 add [bx+si],al
00007DAE 0000 add [bx+si],al
00007DB0 0000 add [bx+si],al
00007DB2 0000 add [bx+si],al
00007DB4 0000 add [bx+si],al
00007DB6 0000 add [bx+si],al
00007DB8 0000 add [bx+si],al
00007DBA 0000 add [bx+si],al
00007DBC 0000 add [bx+si],al
00007DBE 0000 add [bx+si],al
00007DC0 0000 add [bx+si],al
00007DC2 0000 add [bx+si],al
00007DC4 0000 add [bx+si],al
00007DC6 0000 add [bx+si],al
00007DC8 0000 add [bx+si],al
00007DCA 0000 add [bx+si],al
00007DCC 0000 add [bx+si],al
00007DCE 0000 add [bx+si],al
00007DD0 0000 add [bx+si],al
00007DD2 0000 add [bx+si],al
00007DD4 0000 add [bx+si],al
00007DD6 0000 add [bx+si],al
00007DD8 0000 add [bx+si],al
00007DDA 0000 add [bx+si],al
00007DDC 0000 add [bx+si],al
00007DDE 0000 add [bx+si],al
00007DE0 0000 add [bx+si],al
00007DE2 0000 add [bx+si],al
00007DE4 0000 add [bx+si],al
00007DE6 0000 add [bx+si],al
00007DE8 0000 add [bx+si],al
00007DEA 0000 add [bx+si],al
00007DEC 0000 add [bx+si],al
00007DEE 0000 add [bx+si],al
00007DF0 0000 add [bx+si],al
00007DF2 0000 add [bx+si],al
00007DF4 0000 add [bx+si],al
00007DF6 0000 add [bx+si],al
00007DF8 0000 add [bx+si],al
00007DFA 0000 add [bx+si],al
00007DFC 0000 add [bx+si],al
00007DFE 55 push bp ; 引导扇区结束标志位1
00007DFF AA stosb ; 引导扇区结束标志位2
; ---8<--------------- [Cut Here] --------------->8--- ;
; .: keenjoy95 2007 :. ;
; .: keenjoy95_at_gmail_dot_com :. ;
; ! NO rights reserved ! ;
; ---------------------------------------------------- ;
[附 : 常见的 BIOS int 10号中断-13号功能调用的写法]
--------------------------------------------------
下面是代码片断,字符串 "Hello, MyOS world!" 具有统一的颜色熟悉0x0c(黑底浅红字)。
BootMessage:
db "Hello, MyOS world!" ; 待显示字符串信息
DisplayString:
mov ax, BootMessage ; 取字符串数据(段)的首地址
mov bp, ax ; ES:BP 赋值为待显示字符串的首地址 (BIOS INT 10h 定义参数)
mov cx, 18 ; CX 赋值为字符串长度(此处为固定值) (BIOS INT 10h 定义参数)
mov ax, 01301h ; AH 赋值为功能号13h(显示字符串) (BIOS INT 10h 定义参数)
; AL 输出模式参数赋值为01h (BIOS INT 10h 定义参数)
; ---------------------------------------------------
; 第 0 位 : 在输出之后更新光标位置
; 第 1 位 : 字符串包含交替的字符和属性
;
mov bx, 000ch ; BH 页号赋值为0 (BIOS INT 10h 定义参数)
; BL 属性赋值为黑底浅红字(属性字BL使用的前提为AL的高位置0)
; ---------------------------------------------------
; 16位色彩编码表 (D7 D6 D5 D4为背景色,D3 D2 D1 D0为前景色)
; ┏━━━━━━━━━━━┳━━━━━━━━━━━┓
; ┃ 0 0 0 0 黑 ┃ 1 0 0 0 灰 ┃
; ┃ 0 0 0 1 蓝 ┃ 1 0 0 1 浅蓝 ┃
; ┃ 0 0 1 0 绿 ┃ 1 0 1 0 浅绿 ┃
; ┃ 0 0 1 1 青 ┃ 1 0 1 1 浅青 ┃
; ┃ 0 1 0 0 红 ┃ 1 1 0 0 浅红 ┃
; ┃ 0 1 0 1 品红 ┃ 1 1 0 1 浅品红 ┃
; ┃ 0 1 1 0 棕 ┃ 1 1 1 0 黄 ┃
; ┃ 0 1 1 1 灰白 ┃ 1 1 1 1 白 ┃
; ┗━━━━━━━━━━━┻━━━━━━━━━━━┛
;
mov dx, 0000h ; DL 赋值为字符串显示的起始行 / 列号 (BIOS INT 10h 定义参数)
int 10h ; BIOS 10h号中断-13h号功能 (字符串屏显功能调用)
ret ; 子程序无参数返回