📌 汇编语言是很多相关课程(如数据结构、操作系统、微机原理)的重要基础。但仅仅从课程的角度出发就太片面了,其实学习汇编语言可以深入理解计算机底层工作原理,提升代码效率,尤其在嵌入式系统和性能优化方面有重要作用。此外,它在逆向工程和安全领域不可或缺,帮助分析软件运行机制并增强漏洞修复能力。 本专栏的汇编语言学习章节主要是依据王爽老师的《汇编语言》来写的,和书中一样为了使学习的过程容易展开,我们采用以8086CPU为中央处理器的PC机来进行学习。
下面,我们将安装一个新的int 9中断例程,使得原int 9中断例程的功能得到扩展。
任务:安装一个新的int 9中断例程
功能:在DOS下,按F1键后改变当前屏幕的显示颜色,其他的键照常处理。
怎么改变屏幕的颜色呢?
学习win 32 的朋友立马百度:有相应的函数吗?
其实,我们认真考虑下原理应该不难:改变从B800H开始的4000个字中的所有奇地址单元中的内容,当前屏幕的显示颜色即发生改变。
程序如下:
mov ax,0b800h
mov es,ax
mov bx,1
mov cx,2000
s: inc byte ptr es:[bx]
add bx,2
loop s
我们可以调用原int 9中断处理程序,来处理其他的键盘输入。
因为在编写的新int 9中断例程中要调用原int 9中断例程,所以,要保存原int 9中断例程的入口地址。
保存在哪里?
显然不能保存在安装程序中,因为安装程序返回后地址将丢失。
我们因此又将目标锁定在0:200单元处。
这个问题在前面己经详细讨论过。
我们可将新的int 9中断例程安装在0:204 处。
完整的程序如下:
assume cs:code
stack segment
db 128 dup (0)
stack ends
code segment
start:
mov ax,stack
mov ss,ax
mov sp,128
push cs
pop ds
mov ax,0
mov es,ax
mov si,offset int9 ;设置ds:si指向源地址
mov di,204h ;设置es:di指向目的地址
mov cx,offset int9end - offset int9 ;设置cx为传输长度
cld ;设置传输方向为正
rep movsb
push es:[9*4]
pop es:[200h]
push es:[9*4+2]
pop es:[202h]
cli
mov word ptr es:[9*4],204h
mov word ptr es:[9*4+2],0
sti
mov ax,4c00h
int 21h
int9:
push ax
push bx
push cx
push es
in al,60h
pushf
call dword ptr cs:[200h] ;当此中断例程执行时(CS)=0
cmp al,3bh ;F1的扫描码为3bh
jne int9ret
mov ax,0b800h
mov es,ax
mov bx,1
mov cx,2000
s:
inc byte ptr es:[bx]
add bx,2
loop s
int9ret:
pop es
pop cx
pop bx
pop ax
iret
int9end:
nop
code ends
end start
这一章中,我们通过对键盘输入的处理,讲解了CPU对外设输入的通常处理方法,即:
❗注意:端口和中断机制,是CPU 进行I/O的基础。
我们对8086CPU 的指令系统进行一下总结。
大家若要详细了解8086 指令系统中的各个指令的用法 ,可以查看有关的指令手册。
8086CPU 提供以下几大类指令:
比如:mov、push、pop、pushf、popf、xchg等都是数据传送指令,这些指令实现寄存器和内存、寄存器和寄存器之间的单个数据传送。
比如:add、sub、adc、sbb、inc、dec、cmp、imul、idiv、aaa等都是算术运算指令,这些指令实现寄存器和内存中的数据的算数运算。
它们的执行结果影响标志寄存器的:sf、zf、of、cf、pf、af位。
比如:and、or、not、xor、test、shl、shr、sal、sar、rol、ror、rcl、rcr 等都是逻辑指令。
除了not指令外,它们的执行结果都影响标志寄存器的相关标志位。
可以修改IP ,或同时修改CS 和IP 的指令统称为转移指令。
转移指令分为以下几类:
这些指令对标志寄存器或其他处理机状态进行设置,比如:cld、std、cli、sti、nop、clc、cmc、stc、hlt、wait、esc、lock等都是处理机控制指令。
这些指令对内存中的批量数据进行处理。
比如:movsb、movsw、cmps、scas、lods、stos等。
若要使用这些指令方便地进行批量数据的处理,则需要和rep、repe、repne等前缀指令配合使用。