「这是我参与11月更文挑战的第12天,活动详情查看:2021最后一次更文挑战」。
内中断进阶
我们利用中断码段可以调用系统的功能,也就是被系统封装好的子程序
中断既然能够引导cpu临时去执行子程序,那么势必是更改了cs:ip的值,也就是在内存中存放了这个子程序的入口指令地址,通过int关键字找出来并跳转。这里有两个先决条件,一个是子程序必须提前编写好存放在内存中,二是将入口地址存放在内存的某个位置
当程序执行到int指令时,根据中断码计算出程序入口所在的物理地址,然后然后取出来赋值给cs:ip
那么怎么通过中断码计算呢?
比如 int 0h 会从0000:0000这个地址开始找出四个字节数据,由高地址往低地址分别为段地址和偏移地址
由于每个中断码需要占用四个字节空间,因此int 2H 从0000:0004开始找,以此类推
公式为:
IP=中断码*4
CS=中断码*4+2
配合咱们之前学的call指令 int 9h 可以用以下指令替代:
int 9h
;相当于一下三行代码
mov ax,0000H
mov ds,ax
call dword ptr ds:[9h*4]
编写自定义中断
-
编写子程序
child: mov ax,3322H retf -
将子程序入口地址值存放到中断码对应的内存位置
code segment start: call write mov ah,4cH int 21h ;=======子程序====== child: mov ax,3322H retf endd: nop ;=======子程序====== ;=======将子程序入口地址写入内存====== write: ;子程序所在的段地址 mov ax,cs ;子程序所在的偏移地址 mov bx,child mov cx,0000H mov es,cx mov es:[9h*4],bx mov es:[9h*4+2],ax ret code ends end start -
使用中断码调用子程序
code segment start: call write ;测试中断 int 9H mov ah,4cH int 21h ;=======子程序====== child: mov ax,3322H retf endd: nop ;=======子程序====== ;=======将子程序入口地址写入内存====== write: ;子程序所在的段地址 mov ax,cs ;子程序所在的偏移地址 mov bx,child mov cx,0000H mov es,cx mov es:[9h*4],bx mov es:[9h*4+2],ax ret code ends end start
音乐播放
声音由震动产生,不同频率对应不同的声音,也就是音高
单个音高的声音不能叫音乐,只能叫音频,
而音乐是由不同时长的不同音高组合而成,比如100Hz的声音持续1秒紧接着200Hz的声音持续半秒,如此反复循环,那么在听感上就是一首音乐
在音乐演奏的世界里,为了表示音高,一般采用记谱的方式来代替频率,从而方便音乐家们交流,但是对于计算机而言,计算机不能识别简谱也不能识别五线谱
计算机的发声原理
电信号----->驱动------->扬声器
示例代码
data segment
;音高
freq dw 262,262,262,196
dw 330,330,330,262
dw 262,330,392,392
dw 349,330,294
dw 294,330,349,349
dw 330,294,330,262
dw 262,330,294,196
dw 247,294,262,-1
;时长
time dw 3 dup(12,12,25,25),12,12,50
dw 3 dup(12,12,25,25),12,12,50
data ends
stack segment
db 100H dup(0)
stack ends
code segment
start:
;主程序
mov ax,stack
mov ss,ax
mov sp,100H
mov ax,data
mov ds,ax
lea si,freq
lea di,time
play:
mov dx,[si]
cmp dx,-1
je end_play
call sound
add si,2
add di,2
jmp play
end_play:
mov ah,4cH
int 21H
sound:
push ax
push dx
push cx
;定时器的设置
mov al,0b6h
out 43H,al
mov dx,12H
mov ax,34dcH
div word ptr[si]
out 42h,al
mov al,ah
out 42h,al
;设置8255芯片,控制扬声器开关
in al,61h
mov ah,al
or al ,3
out 61h,al
;延时一定的时长
mov dx,[di]
wait1:
mov cx,28000
delay:
nop
loop delay
dec dx
jnz wait1
;恢复扬声器端口原值
mov al,ah
out 61h,al
pop cx
pop dx
pop ax
ret
code ends
end start