【疑问】DOS调用会修改AL寄存器的值?

  • 代码部分image-20220812115824403
  • debugimage-20220812115614391

图中可见,在上下两句代码指令之间,并没有对al进行任何操作,可是在经过09h号dos功能调用之后,al中的值却发生了改变。

解决:

应该是没有定义堆栈段的缘故

汇编语言大作业

image-20220810164610514

程序片段

等待用户输入指令

image-20220810165859761

跳转表法实现多分支程序

image-20220810170049916

几个ASCII码

按键 ASCII码
回车 0DH
换行 0AH
空格 20H
ESC 1BH
$ 24H

相关DOS命令

程序框架相关DOS命令

01H等待用户从键盘输入一个字符,回显,检测ctrl+break

image-20220810165527942

07H等待用户从键盘输入一个字符,不回显,不检测ctrl+break

image-20220810170228527

08H等待用户从键盘输入一个字符,不回显,检测ctrl+break

image-20220810170339157

02H向屏幕输出一个字符

image-20220810170748947

06H控制台输入输出

image-20220810172607014

09H向屏幕输出一串字符

image-20220810173320786

字符串末尾用$符号

0A从键盘输入一串字符

image-20220810174256580

键盘输入缓冲区的定义规则

image-20220810174632512

第四问相关DOS命令

2DH时间设置

image-20220810160005849

image-20220810160117622

2CH时间获取

image-20220810160411169

相关BIOS命令

BIOS(Basic input/output system)固化在 ROM 中,包括 I/O 设备的处理程序和许多常用的例行程序。

对用户程序来说,可由特定指令 INT n(n 为中断号)通过软终端的方式调用。不管 DOS 是否装入系统,这些调用可以直接控制 I/O 设备。

00H设置显示器,清屏

image-20220810163621943

  • BL中设置分页,一共有四页,一般用第0页,可以实现分屏功能。

02H设置光标位置

字符模式的光标位置,列是x,行是y

image-20220810163847716

1
2
3
4
mov dx, 0100h  ; DH=row 1, DL=column 0
mov bh, 0 ; display page
mov ah, 02h ; SetCursor
int 10h

第三问解法

  • 用0AH号DOS命令依次接收用户键入的数字,注意把ASCII码转换成数值
  • 用0AH号DOS命令统计到的用户键入字符数,作为用户输入数值的位数,利用位置加权法计算结果。
  • image-20220812122042134

汇编09h输出乱码

必须要在程序开始时初始化ds寄存器

1
2
3
;初始化ds寄存器
mov ax,data
mov ds,ax

汇编子程序调用问题

image-20220811135427091

子程序无论定义在了什么位置,程序走到这个位置之后,都会自动调用一次子程序。

汇编断点子程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
assume cs:code

stack segment
db 30h dup(0)
stack ends

code segment
start:
mov ax,3
mov bx,1
mov cx,5
s0:
add ax,bx
call breakPoint ;在此处设置断点暂停
loop s0
mov ax,4c00h
int 21h


breakPoint:
push bx ;bx压栈,保护起来
pushf ;psw压栈
pop bx ;上一条保存的psw内容弹出到bx
or bh,3 ;TF、IF置1,开中断,单步调试
push bx ;bx压栈
popf ;上一条压栈的bx内容弹出到psw
pop bx ;最开始压栈的bx弹出,恢复数据
ret ;退出子程序

ASCII大小写转换

大写转小写:|20h

小写转大写:&0DFh

汇编基址变址寻址格式

MOV AL,BXMOV AL,[BX+SI]

汇编语言中loop指令

要注意cx中保存的是循环次数,循环次数保存在cx中。

DOS命令0AH

1
2
3
keybuf1        db 0ffh
db ?
keybuf1content db 0ffh dup(?)

这是定义最多能输入255个字符,但包括最后的回车字符(所以有效输入字符为254个),因为最后一个字节存放回车字符,所以不必担心向最后一个字节写入$时会发生溢出。

ASCII字符型数字转整型数字

ASCII码字符型数字转换为整型数字:字符型数字 - ‘0’ 或者 字符型数字 - 48

DOS窗口输出存储单元中的十六进制数

程序流程图

拆十六位数程序流程图

汇编代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
mov    cx,keybuf3sortedcount               ;把要转换的字符串中有几位数字给cx
lea bp,keybuf3sorted ;原字符串首址给bp
mov si,0000h ;原字符串偏移量给si
lea bx,keybuf3ascii ;目的字符串首址给bx
mov di,0000h ;目的字符串偏移量给di

nexthandleascii:
mov al,ds:[si][bp] ;原字符串中取出一位给al
mov ah,al ;al赋值给ah,经过操作之后,ah保存十六进制数高位,al保存低位
and al,0fh
and ah,0f0h
push cx ;cx压栈,因为后边对al逻辑移位,需要用cl
mov cl,4 ;设置右移四位
shr ah,cl ;右移四位
pop cx ;cx出栈
cmp al,10 ;如果大于十,是字母表示
jb isnum
sub al,10
add al,61h
jmp handleah
isnum:
add al,30h
jmp handleah
handleah:
cmp ah,10
jb isnumah
sub ah,10
add ah,61h
jmp handleover
isnumah:
add ah,30h
handleover:
mov [bx][di],ah ;目的字符串中写入一个高位数字
inc di ;目的字符串偏移量加一
mov [bx][di],al ;目的字符串写入低位数字
inc di
mov byte ptr [bx][di],',' ;写入完整数字之后写逗号
inc di ;目的字符串偏移量加一
inc si ;原字符串偏移量加一
loop nexthandleascii