汇编学习笔记(11)int指令和端口

格式

int指令也是一种内中断指令,int指令的格式为int n,n是中断类型码。也就是说,使用int指令可以调用任意的中断例程,例如我们可以显示的调用0号中断例程,还记得在汇编学习笔记(10)中我们自己定义了除法溢出的例程么,我们在这里直接调用看看

 1 assume cs:codesg

 2 

 3 codesg segment

 4     

 5 start:  

 6     mov ax,0b800h

 7     mov es,ax

 8     mov byte ptr es:[11*160+40*2],'h'

 9     int 0

10 

11 codesg ends

12 

13 end start

 

成了,perfect!

汇编学习笔记(11)int指令和端口

既然可以随时随地的调用中断例程,那么就可以借助中断例程来完成一些系统必须的子程序,下面是书上的例子,当次搬运工

 1 ;编写7ch号中断例程,计算word型数据的平方

 2 assume cs:codesg

 3 

 4 codesg segment

 5     

 6 start:  

 7     ;ds:si指向sqr

 8     mov ax,cs

 9     mov ds,ax

10     mov si,offset sqr

11     ;es:di指向0000:01e0

12     mov ax,0000

13     mov es,ax

14     mov di,01e0h

15     ;安装

16     mov cx,offset sqrend-offset sqr

17     cld

18     rep movsb

19     ;设置中断向量表

20     mov ax,0000

21     mov es,ax

22     mov word ptr es:[7ch*4],01e0h

23     mov word ptr es:[7ch*4+2],0

24     mov ax,8888

25     int 7ch 

26     

27     mov ax,4c00h

28     int 21h

29 sqr:

30     mul ax

31     iret

32 sqrend:

33     nop

34     

35 codesg ends

36 

37 end start

 

汇编学习笔记(11)int指令和端口

 1 ;编写7ch号中断例程,将字符串全部转换为大写

 2 assume cs:codesg,ds:data

 3 data segment

 4     db 'h',0

 5 data ends

 6 codesg segment

 7     

 8 start:  

 9     ;ds:si指向sqr

10     mov ax,cs

11     mov ds,ax

12     mov si,offset upper

13     ;es:di指向0000:01e0

14     mov ax,0000

15     mov es,ax

16     mov di,01e0h

17     ;安装

18     mov cx,offset upperend-offset upper

19     cld

20     rep movsb

21     ;设置中断向量表

22     mov ax,0000

23     mov es,ax

24     mov word ptr es:[7ch*4],01e0h

25     mov word ptr es:[7ch*4+2],0

26     mov ax,data

27     mov ds,ax

28     mov si,0

29     mov cl,11

30     ;显示原始字符串

31     call display

32     ;调用中断程序

33     int 7ch

34     ;大写

35     call upper 

36     mov cl,12

37     ;显示改写后的字符串

38     call display

39     

40     mov ax,4c00h

41     int 21h

42 upper:

43     push cx

44     push si

45 change:

46     mov cl,[si]

47     mov ch,0

48     jcxz s0

49     and byte ptr [si],11011111b

50     inc si

51     jmp short change

52 s0: 

53     pop si

54     pop cx

55     iret

56 upperend:

57     nop

58     

59 display:

60     push ax

61     push es

62     push di

63     push si

64     push cx

65     mov ax,0b800h

66     mov es,ax

67     mov ax,160

68     mul cl

69     add ax,80

70     mov di,ax

71     mov ch,0

72 s1:

73     mov cl,ds:[si]

74     jcxz ok

75     mov byte ptr es:[di],cl

76     add di,2

77     inc si

78     jmp short s1

79 ok:

80     pop cx

81     pop si

82     pop di

83     pop es

84     pop ax

85     ret

86 codesg ends

87 

88 end start

 

中断例程实现loop指令

中断例程实现loop指令需要完成以下功能:

1.(cx)=(cx)-1
  2.如果(cx)!=0,循环执行,否则向下继续执行

为了完成上述的两种功能,显然中断例程必须获取cs和ip的值。因调用中断例程是现将cs、ip入栈,所以只需将ip的值减去循环体的长度就可以了

 1 assume cs:code

 2 

 3 code segment

 4 

 5 start:

 6     mov ax,cs

 7     mov ds,ax

 8     mov si,offset looper

 9     mov ax,01e0h

10     mov es,ax

11     mov di,0

12     mov cx,offset l-offset looper

13     cld

14     rep movsb

15     mov ax,0

16     mov es,ax

17     mov word ptr es:[7ch*4],01e0h

18     mov word ptr es:[7ch*4+2],0

19     mov ax,0b800h

20     mov es,ax

21     mov di,12*160

22     mov bx,offset s-offset send

23     mov cx,80

24 s:

25     mov byte ptr es:[di],'!'

26     add di,2

27     int 7ch

28 send:

29     nop

30     mov ax,4c00h

31     int 21h

32     

33 looper:

34     push bp

35     mov bp,sp

36     dec cx

37     jcxz loopend

38     add [bp+2],bx   

39 loopend:

40     pop bp

41     iret

42 l:

43     nop

44 code ends

45 

46 end start

 

BIOS提供的中断例程

BIOS提供了很多中断例程以供调用,下面举个显示字符串的例子,int 10h例程中的9号子程序

 1 assume cs:code

 2 

 3 code segment

 4 

 5 start:

 6     mov ah,2

 7     mov bh,0

 8     mov dh,5

 9     mov dl,12

10     int 10h

11     

12     mov ah,9

13     mov al,'a'

14     mov bl,11001010b

15     mov bh,0

16     mov cx,3

17     int 10h

18     mov ax,4c00h

19     int 21h

20 code ends

21 

22 end start

 

端口的读写

端口的读写只有两种指令和寄存器可以使用

  • in 读入指令,in al 读入8位数据;in ax 读入16位数据
  • out 写入指令,out al 对端口写入8位数据;out ax写入16位数据

CMOS RAM芯片

CMOS芯片包含两个端口70h和71h,70h是地址端口,71h是数据端口,从CMOS RAM中读取2号单元内容程序如下

 1 assume cs:code

 2 

 3 code segment

 4 

 5 start:

 6     mov al,2

 7     out 70h,al ;表示要读取2号单元

 8     in al,71h;读取2号单元内容

 9     

10     mov ax,4c00h

11     int 21h

12 code ends

13 

14 end start

 

写入的是这样

 1 assume cs:code

 2 

 3 code segment

 4 

 5 start:

 6     mov al,2

 7     out 70h,al ;表示要写入2号单元

 8     mov al,0

 9     out 71h,al;写入0

10     

11     mov ax,4c00h

12     int 21h

13 code ends

14 

15 end start

 

shl和shr指令

shl是逻辑左移指令,shr是逻辑右移指令。左移的最低位和右移的最高位都用0补充,并将移出的最后一位写入CF中,不论左移还是右移,都是从最低位开始的。

mov al,10010000
  shl al,1
  shr al,1

左移后(al)=00100000 CF=1,右移后(al)=00010000 CF=0.左移一位相当于x=x*2,右移一位相当于x=x/2.

显示时间

 1 assume cs:code,ds:data

 2 

 3 data segment

 4     db 'yy/mm/dd hh:mm:ss','$'

 5     index db 9,8,7,4,2,0

 6 data ends

 7 

 8 code segment

 9 

10 start:

11     mov ax,data

12     mov ds,ax

13     mov si,0

14     mov di,0

15     mov cx,6

16 s:

17     push cx

18     ;获取需要读取的端口地址

19     mov al,index[si]

20     out 70h,al

21     in al,71h

22     

23     mov ah,al

24     mov cl,4

25     ;取得十位

26     shr ah,cl

27     ;个位

28     and al,00001111b

29     ;转为字符

30     add ah,30h

31     add al,30h

32     

33     mov ds:[di],ah

34     mov ds:[di+1],al

35     

36     inc si

37     add di,3

38     

39     pop cx

40     loop s

41     ;光标显示位置

42     mov ah,2

43     mov bh,0

44     mov dh,10

45     mov dl,40

46     int 10h

47     ;显示ds:dx指向的字符串

48     mov ax,data

49     mov ds,ax

50     mov dx,0

51     mov ah,9

52     int 21h

53 

54     

55     mov ax,4c00h

56     int 21h

57 code ends

58 

59 end start

 

汇编学习笔记(11)int指令和端口

你可能感兴趣的:(学习笔记)