第6章 汇编语言
6.1 实方式执行环境
6.2 源程序和语句
6.3 操作数表示
6.4 伪指令语句和变量
6.5 段声明和段间转移
6.6 目标文件和段模式
6.7 宏
汇编语言!
汇编语言!
回顾
.汇编语言
.
汇编语言是一种程序设计语言,是机器语言的符号化
。
.
汇编语言
的
语句主要是
汇编格式指令和伪指令
。
.
把用汇编语言编写的程序称为
汇编语言源程序
,或称为
汇
编源程序
,或简称为
源程序
。
.
把汇编源程序翻译成目标程序的
过程
称为
汇编
。
.
完成汇编工作的
工具
或程序叫做
汇编程序
。
.汇编语言是一种程序设计语言,是机器语言的符号化。
.汇编语言的语句主要是汇编格式指令和伪指令。
.把用汇编语言编写的程序称为汇编语言源程序,或称为汇
编源程序,或简称为源程序。
.把汇编源程序翻译成目标程序的过程称为汇编。
.完成汇编工作的工具或程序叫做汇编程序。
汇编
语言!
汇编
语言!
回顾
.
汇编和汇编程序
.汇编和汇编程序
汇编
汇编语言
源程序
目标程序
汇编器
NASM
6.2 源程序和语句
6.2.1 汇编语言源程序
6.2.2 语句及其格式
汇编
汇编语言
源程序
目标程序
汇编器
NASM
伪指令
伪指令
6.2.1 汇编语言源程序
.演示程序dp61.asm
显示输出“Hello world!”
segment
text
;
命名段
text
org
100H
;
段内偏移从
100H
开始计算
;
MOV
AX, CS
MOV
DS, AX
;
使数据段与代码段相同
MOV
DX, hello
;DX=hello
的段内偏移
MOV
AH, 9
INT
21H
;
显示
hello
开始的字符串(以
$
结尾)
;
MOV
AH, 4CH
INT
21H
;
返回操作系统
;
hello
db
"Hello world
!", 0DH, 0AH, '$'
segment text ;命名段text
org 100H ;段内偏移从100H开始计算
;
MOV AX, CS
MOV DS, AX ;使数据段与代码段相同
MOV DX, hello ;DX=hello的段内偏移
MOV AH, 9
INT 21H ;显示hello开始的字符串(以$结尾)
;
MOV AH, 4CH
INT 21H ;返回操作系统
;
hello db "Hello world!", 0DH, 0AH, '$'
指示
指示
指示
指示
操作系统
功能调用
操作系统功能调用
.系统功能调用
.
系统功能类似于子程序。可以认为
系统功能
是由操作系
统提供的子程序。
.
调用系统功能,类似于调用子程序,有
出入口
参数。
.
采用编号的方式
,不采用子程序名称的方式。
.
这里操作系统是
DOS
(或者说
由
Windows
提供的
DOS
环境
)。
.
编号
为
9
号的
系统功能是显示输出
字符串。入口
参数为字
符串首地址,
DS
含有段值,
DX
含有偏移
。
.
编号为
4CH
号的系统功能是结束程序运行,返回
DOS
。
.系统功能类似于子程序。可以认为系统功能是由操作系
统提供的子程序。
.调用系统功能,类似于调用子程序,有出入口参数。
.采用编号的方式,不采用子程序名称的方式。
.这里操作系统是DOS(或者说由Windows提供的DOS环境)。
.编号为9号的系统功能是显示输出字符串。入口参数为字
符串首地址,DS含有段值,DX含有偏移。
.编号为4CH号的系统功能是结束程序运行,返回DOS。
6.2.1 汇编语言源程序
.系统功能调用
.
采用编号的方式
,不采用子程序名称的方式。
.
这里操作系统是
DOS
(或者说
由
Windows
提供的
DOS
环境
)。
.
调用系统功能的方法:
.
根据相应的功能,准备好
相应的
参数
.
寄存器
AH
含有功能
编号
.
执行调用指令
INT 21H
.采用编号的方式,不采用子程序名称的方式。
.这里操作系统是DOS(或者说由Windows提供的DOS环境)。
.调用系统功能的方法:
.根据相应的功能,准备好相应的参数
.寄存器AH含有功能编号
.执行调用指令 INT 21H
这是一条软中断指令,
在第
7
章介绍该指令
这是一条软中断指令,
在第7章介绍该指令
6.2.1 汇编语言源程序
.系统功能调用
MOV
DX, hello
;
准备参数
MOV
AH,
9 ;9
号功能
INT
21H
;
调用
;
MOV
AH,
4CH ;4CH
号功能
INT
21H
;
调用
MOV DX, hello ;准备参数
MOV AH, 9 ;9号功能
INT 21H ;调用
;
MOV AH, 4CH ;4CH号功能
INT 21H ;调用
.
演示系统功能调用
.演示系统功能调用
显示字符串
显示字符串
结束程序返回操作系统
结束程序返回操作系统
6.2.1 汇编语言源程序
.汇编
.
使用汇编器
NASM
利用汇编器
NASM
,生成纯二进制代码文件(
COM
类型的可
执行程序)的方法:
nasm
dp61.asm
-
f
bin
-
o
hello.com
.使用汇编器NASM
利用汇编器NASM,生成纯二进制代码文件(COM类型的可
执行程序)的方法:
nasm dp61.asm -f bin -o hello.com
命令名称
命令名称 源程序文件名
源程序文件名 目标
文件名
目标文件名
格式项
格式项 输出
项
输出项
纯二进制格式
纯二进制格式
6.2.1 汇编语言源程序
.演示程序dp62.asm
接受用户按一个键,
以2位十六进制数的形式显示所按键的ASCII码
.
流程:
.
设置堆栈段和数据段
.
接受用户按键
.
转换成
ASCII
码串,并显示
.
结束程序
.流程:
.设置堆栈段和数据段
.接受用户按键
.转换成ASCII码串,并显示
.结束程序
6.2.1 汇编语言源程序
.演示程序dp62.asm
segment
code ;
定义段
code
..
start
: ;
启动标号
MOV
AX, stack
MOV
SS, AX ;
设置堆栈段寄存器
MOV
SP,
stacktop
;
设置堆栈顶
;
MOV
AX, data
MOV
DS, AX ;
设置数据段寄存器
;
segment code ;定义段code
..start: ;启动标号
MOV AX, stack
MOV SS, AX ;设置堆栈段寄存器
MOV SP, stacktop ;设置堆栈顶
;
MOV AX, data
MOV DS, AX ;设置数据段寄存器
;
指示
指示
开始地址
开始地址
定义一个代码段(段名称code)
设置堆栈段和数据段
设置堆栈段和数据段
6.2.1 汇编语言源程序
.演示程序dp62.asm
MOV
DX, prompt
CALL
PrintStr
;
显示提示信息
;
MOV
AH, 1
INT
21H
;
MOV
BL, AL
;
临时保存所按键
;
MOV
DX, newline
CALL
PrintStr
;
调用子程序输出回车
换行
MOV DX, prompt
CALL PrintStr ;显示提示信息
;
MOV AH, 1
INT 21H
;
MOV BL, AL ;临时保存所按键
;
MOV DX, newline
CALL PrintStr ;调用子程序输出回车换行
1
号系统功能
接受用户按键
AL
含所得字符的
ASCII
码
1号系统功能
接受用户按键
AL含所得字符的ASCII码
接受用户按键
6.2.1 汇编语言源程序
.演示程序dp62.asm
MOV
AL, BL
;
恢复所按键的码值
SHR
AL, 4
CALL
ToASCII
;
把高
4
位转对应
ASCII
码
MOV
[result], AL
;
保存
MOV
AL, BL
CALL
ToASCII
;
把低
4
位转对应
ASCII
码
MOV
[result+1], AL
;
保存到
;
MOV
DX, result
CALL
PrintStr
;
调用
子程序输出回车
换行
;
MOV
AH, 4CH
INT 21H
MOV AL, BL ;恢复所按键的码值
SHR AL, 4
CALL ToASCII ;把高4位转对应ASCII码
MOV [result], AL ;保存
MOV AL, BL
CALL ToASCII ;把低4位转对应ASCII码
MOV [result+1], AL ;保存到
;
MOV DX, result
CALL PrintStr ;调用子程序输出回车换行
;
MOV AH, 4CH
INT 21H
调用
4CH
号系统
功能
结束程序的运行
调用4CH号系统功能
结束程序的运行
转换成ASCII码串,并显示
6.2.1 汇编语言源程序
.演示程序dp62.asm
PrintStr
:
;
子程序入口
PUSH
BX
;
保护寄存器
BX
MOV
BX, DX
LAB1
:
MOV
DL, [BX]
;
取出待显示字符
INC
BX
;
指向下一个
CMP
DL, '$'
;
结束符吗?
JZ
LAB2
;
遇到结束符,结束
MOV
AH, 2
INT
21H
;
显示该字符
JMP
LAB1
;
继续
LAB2
:
POP
BX
;
恢复寄存器
BX
RET
PrintStr: ;子程序入口
PUSH BX ;保护寄存器BX
MOV BX, DX
LAB1:
MOV DL, [BX] ;取出待显示字符
INC BX ;指向下一个
CMP DL, '$' ;结束符吗?
JZ LAB2 ;遇到结束符,结束
MOV AH, 2
INT 21H ;显示该字符
JMP LAB1 ;继续
LAB2:
POP BX ;恢复寄存器BX
RET
调用
2
号系统
功能
显示一个字符
调用2号系统功能
显示一个字符
子程序:显示输出指定的字符串
6.2.1 汇编语言源程序
.演示程序dp62.asm
;
把低
4
位转成对应十六进制数
ASCII
码
ToASCII
:
;
子程序入口
AND
AL, 0FH
ADD
AL, '0'
CMP
AL, '9'
JBE
LAB3
ADD
AL, 7
LAB3
:
RET
;把低4位转成对应十六进制数ASCII码
ToASCII: ;子程序入口
AND AL, 0FH
ADD AL, '0'
CMP AL, '9'
JBE LAB3
ADD AL, 7
LAB3:
RET
子程序ToASCII
6.2.1 汇编语言源程序
.演示程序dp62.asm(数据段)
segment
data ;
定义段
data
prompt
db
"Press a key: ",'$'
newline
db
0DH,0AH,'$'
result
db
0,0 ;
存放十六进制数
ASCII
码
db
'H',0DH,0AH,'$' ;
结果字符串后半
部分
segment data ;定义段data
prompt db "Press a key: ",'$'
newline db 0DH,0AH,'$'
result db 0,0 ;存放十六进制数ASCII码
db 'H',0DH,0AH,'$' ;结果字符串后半部分
伪指令
伪指令
指示
指示
定义一个数据段(段名称data)
6.2.1 汇编语言源程序
.演示程序dp62.asm(堆栈段)
segment
stack
stack
;
定义堆栈段
resb
1024
;
安排
1024
字节
stacktop
:
segment stack stack ;定义堆栈段
resb 1024 ;安排1024字节
stacktop:
伪指令
伪指令
指示
指示
定义一个堆栈段(段名称stack)
6.2.1 汇编语言源程序
6.2.2 语句及其格式
.语句的种类
.
汇编语言(
NASM
)有
四种类型的
语句:
.
指令语句
.
伪指令语句
.
宏指令语句
.
指示语句
.汇编语言(NASM)有四种类型的语句:
.指令语句
.伪指令语句
.宏指令语句
.指示语句
分别对应
指令、伪指令、宏指令和指示
.语句的种类
.
指令语句
就是表示汇编格式指令的语句,也就是表示符
号化的机器指令的语句
。
用
符号表示的机器指令被称为
汇编格式的指令
。汇编器
在对源程序进行汇编时,把指
令语句翻译成机器指令
。
.指令语句就是表示汇编格式指令的语句,也就是表示符
号化的机器指令的语句。用符号表示的机器指令被称为
汇编格式的指令。汇编器在对源程序进行汇编时,把指
令语句翻译成机器指令。
6.2.2 语句及其格式
.语句的种类
.
伪指令语句
就是表示伪指令的语句
。
.
伪指令
并非真正符号化的机器指令。
对处理器而言,伪
指令不是指令,但对汇编器而言,它却是指令
。
伪指令
主要用于定义变量,预留存储单元
。
.伪指令语句就是表示伪指令的语句。
.伪指令并非真正符号化的机器指令。对处理器而言,伪
指令不是指令,但对汇编器而言,它却是指令。伪指令
主要用于定义变量,预留存储单元。
prompt
db
"
Press a key:
", '$'
newline
db
0DH, 0AH, '$'
result
db
0, 0
resb
1024
prompt db "Press a key: ", '$'
newline db 0DH, 0AH, '$'
result db 0, 0
resb 1024
6.2.2 语句及其格式
伪指令
伪指令
定义数据
安排空间
定义数据
安排空间
.语句的种类
.
宏指令
语句
表示宏指令。宏指令也被简称为宏,与高级
语言中宏的概念相同,就是代表一个代码片段的标识符。
宏指令在使用之前要先声明。
.
指示
(
directive
)也常被称为汇编器指令或汇编指令,
它指示汇编器怎样进行汇编,如何生成目标代码。为了
避免与汇编格式指令相混淆,所以把它称为“指示”
。
.宏指令语句表示宏指令。宏指令也被简称为宏,与高级
语言中宏的概念相同,就是代表一个代码片段的标识符。
宏指令在使用之前要先声明。
.指示(directive)也常被称为汇编器指令或汇编指令,
它指示汇编器怎样进行汇编,如何生成目标代码。为了
避免与汇编格式指令相混淆,所以把它称为“指示”。
6.2.2 语句及其格式
.语句的格式
.
指令语句
的
格式
[
标号:
] [
指令助记符
] [
操作数表
]
[;
注释
]
.指令语句的格式
[标号:] [指令助记符] [操作数表] [;注释]
指令助记符与操作数
表示具体的指令
注释以分号引导
标号之后带一个冒号
可以没有标号和注释
可以只有注释
可以只有标号
可以没有标号和注释
可以只有注释
可以只有标号
6.2.2 语句及其格式
.语句的格式
.
指令语句
的
格式
[
标号:
] [
指令助记符
] [
操作数表
]
[;
注释
]
.指令语句的格式
[标号:] [指令助记符] [操作数表] [;注释]
操作数的形式也与具体的指令有关,
可以是常数或数值表达式、寄存器(寄存器名)
或者存储单元(有效地址)
6.2.2 语句及其格式
.语句的格式
.
伪指令语句
的
格式
[
名字
] [
伪
指令定义符
]
[
参
数表
]
[;
注释
]
.伪指令语句的格式
[名字] [伪指令定义符] [参数表] [;注释]
伪指令定义符规定了伪指令的功能 名字之后一般不带冒号
参数表与伪指令
有关,
可以没有名字,可以没有注释
参数表与伪指令有关,
可以没有名字,可以没有注释
有时参数是常数(数值表达式),
有时参数是一般的符号,
有时是具有特殊意义的记号。
6.2.2 语句及其格式
.语句的格式
字母大小写敏感
标号和名字要尽量起得有意义
标号和名字要尽量起得有意义
.
标识符
由
字母、数字及一些特定
字符
组
成
.标识符由字母、数字及一些特定字符组成
-
$ # @ ~ . ?
特定字符:
- $ # @ ~ . ?
字母
. _ ?
标识符首字符只能是:字母 . _ ?
6.2.2 语句及其格式
6.3 操作数表示
.
指令的操作数通常在寄存器或者存储单元中,有时也会
是立即数
。
.
在
NASM
的汇编格式指令
中
:
.
通用寄存器
和段寄存器都直接用寄存器名
表示
.
立即
数就是常数
,可以有
多种表示
形式
.
存储单元
的表示就是存储器寻址方式的表示,也就
是有效地址的
表示
.指令的操作数通常在寄存器或者存储单元中,有时也会
是立即数。
.在NASM的汇编格式指令中:
.通用寄存器和段寄存器都直接用寄存器名表示
.立即数就是常数,可以有多种表示形式
.存储单元的表示就是存储器寻址方式的表示,也就
是有效地址的表示
6.3 操作数表示
6.3.1 常数
6.3.2 数值表达式
6.3.3 有效地址
6.3.4 数据类型说明
.整数
.
在没有特别标记时,一个整数由十进制表示
。
.
可以
采用十六进制、八进制和二进制形式表示整数
。
.
后缀
H
表示十六进制数,后缀
Q
或
O
表示八进制数,后
缀
B
表示二进制数。当然也可以用后缀
D
表示
十进制数。
.
为了
避免与普通标识符混淆,十六进制数应以数字开头,
如果以字母开头,应该再冠以数字
0
。还可以采用
C
风格
的前缀
0x
表示十六进制数。
. 在没有特别标记时,一个整数由十进制表示。
.可以采用十六进制、八进制和二进制形式表示整数。
.后缀H表示十六进制数,后缀Q或O表示八进制数,后
缀B表示二进制数。当然也可以用后缀D表示十进制数。
.为了避免与普通标识符混淆,十六进制数应以数字开头,
如果以字母开头,应该再冠以数字0。还可以采用C风格
的前缀0x表示十六进制数。
四
种不同类型的常数
:
整数
、字符、字符串和
浮点数
四种不同类型的常数:
整数、字符、字符串和浮点数
6.3.1 常数
6.3.1 常数
.整数
如下说明
多种整数的表示
形式:
MOV
AX, 168
;
十进制表示
MOV
AX, 0168
;
仍然
表示十进制数
MOV
AX, 168
d
;
后缀
D
,代表十进制数
MOV
AX,
0
A8
h
;
后缀
H
,代表十六进制数
MOV
AX, 10101000
B
;
后缀
B
,代表二进制数
MOV
AX, 250
Q
;
后缀
Q
,代表八进制数
MOV
AX, 250
O
;
后缀
O
,代表八进制数
MOV
AX,
0x
A8
;
前缀
0x
,代表十六进制数
如下说明多种整数的表示形式:
MOV AX, 168 ;十进制表示
MOV AX, 0168 ;仍然表示十进制数
MOV AX, 168d ;后缀D,代表十进制数
MOV AX, 0A8h ;后缀H,代表十六进制数
MOV AX, 10101000B ;后缀B,代表二进制数
MOV AX, 250Q ;后缀Q,代表八进制数
MOV AX, 250O ;后缀O,代表八进制数
MOV AX, 0xA8 ;前缀0x,代表十六进制数
汇编器
NASM
将生成完全相同的代码
汇编器NASM将生成完全相同的代码
.整数
如下说明
多种整数表示形式的
使用
特点
:
OR
AX, 8080
H
AND
BL, 0F0
H
TEST
BL, 00110100
B
OR
AL, 11001010
B
如下说明多种整数表示形式的使用特点:
OR AX, 8080H
AND BL, 0F0H
TEST BL, 00110100B
OR AL, 11001010B
6.3.1 常数
.字符
.
字符常数是一对单引号(
或双引号
)之间的若干个字符
。
.
每个
字符表示一个字节(
8
个二进制位),可以认为字符
的值是对应
ASCII
码值
。
.
在
表示
32
位数据时,包含在一对引号中的字符常数最多
可以由
4
个字符组成
。
.
对于
由多个字符组成的字符常数,在存储时出现在前面的
字符占用低地址存储单元。这样,按照“高高低低”存储规
则,出现在前面的字符代表了数值的低位。
. 字符常数是一对单引号(或双引号)之间的若干个字符。
.每个字符表示一个字节(8个二进制位),可以认为字符
的值是对应ASCII码值。
.在表示32位数据时,包含在一对引号中的字符常数最多
可以由4个字符组成。
.对于由多个字符组成的字符常数,在存储时出现在前面的
字符占用低地址存储单元。这样,按照“高高低低”存储规
则,出现在前面的字符代表了数值的低位。
6.3.1 常数
.字符
如下说明
字符常数的表示及其值
:
MOV
AL, 'a'
;
AL=61H
MOV
AX, 'a'
;
AX=0061H
MOV
AX, '
ab
'
;
AX=6261H
MOV
EAX, '
abcd
'
;
EAX=64636261H
MOV
BX, '
abcd
'
;
BX=6261H
如下说明字符常数的表示及其值:
MOV AL, 'a' ;AL=61H
MOV AX, 'a' ;AX=0061H
MOV AX, 'ab' ;AX=6261H
MOV EAX, 'abcd' ;EAX=64636261H
MOV BX, 'abcd' ;BX=6261H
该字符常数太大,汇编器NASM会给出警告,
并抛弃高位部分。
6.3.1 常数
.字符
如下说明
表示字符常数时
单引号和双引号的
互换
:
MOV
AL, '
"
'
;
AL=22H
MOV
AL, "
'
"
;
AL=27H
MOV
BL, "A"
;
BL=41H
MOV
BX, "AB"
;
BX=4241H
如下说明表示字符常数时单引号和双引号的互换:
MOV AL, '"' ;AL=22H
MOV AL, "'" ;AL=27H
MOV BL, "A" ;BL=41H
MOV BX, "AB" ;BX=4241H
6.3.1 常数
.字符串
.
字符串常数与字符常数很相近,但是字符串常数可以含有
更多的字符。
.字符串常数与字符常数很相近,但是字符串常数可以含有
更多的字符。
6.3.1 常数
6.3.2 数值表达式
.表达式
.
由
运算符和括号把常数、记号和标识符等连接起来的式子,
被称为
表达式
。
.
所谓
数值表达式
是指在汇编过程中能够由汇编器计算出具
体数值的
表达式。
.
组成
数值表达式的各部分必须在汇编时就能完全确定
。
.由运算符和括号把常数、记号和标识符等连接起来的式子,
被称为表达式。
.所谓数值表达式是指在汇编过程中能够由汇编器计算出具
体数值的表达式。
.组成数值表达式的各部分必须在汇编时就能完全确定。
表达式的概念与
C
语言中是
一样的
表达式的概念与C语言中是一样的
.运算符
运算符及其优先级
运算符及其优先级
优先级
优先级
运算符
运算符
运算说明
运算说明
运算对象个数
运算对象个数
7
7
|
|
按位或
(
类似指令
OR
)
按位或(类似指令OR)
2
2
6
6
^
^
按位异或
(
类似指令
XOR
)
按位异或(类似指令XOR)
2
2
5
5
&
&
按位与
(
类似指令
AND
)
按位与(类似指令AND)
2
2
4
4
<<
<<
逻辑左移
(
类似指令
SHL
)
逻辑左移(类似指令SHL)
2
2
>>
>>
逻辑右移
(
类似指令
SHR
)
逻辑右移(类似指令SHR)
2
2
3
3
+
+
加运算
加运算
2
2
-
-
减运算
减运算
2
2
2
2
*
*
乘
乘
2
2
/
/
无符号除
无符号除
2
2
//
//
有符号除
有符号除
2
2
%
%
无符号模
无符号模
2
2
%%
%%
有符号模
有符号模
2
2
1
1
+
+
加号
加号
1
1
-
-
负号
负号
1
1
~
~
按位取反
(
类似指令
NOT
)
按位取反(类似指令NOT)
1
1
!
!
逻辑否
逻辑否
1
1
seg
seg
获得段值
获得段值
1
1
6.3.2 数值表达式
.表达式
如下演示
运算符的使用
:
MOV
AL, 01000111B
|
00100000B
;
AL=67H
MOV
AL, 01101000B
&
11011111B
;
AL=48H
MOV
AL, 03H
<<
4
;
AL=30H
MOV
AL, 80H
>>
6
;
AL=02H
MOV
AL,
~
00000001B
;
AL=FEH
MOV
AL,
!
1
;
AL=00H
MOV
AL,
-
1
;
AL=FFH
如下演示运算符的使用:
MOV AL, 01000111B | 00100000B ;AL=67H
MOV AL, 01101000B & 11011111B ;AL=48H
MOV AL, 03H << 4 ;AL=30H
MOV AL, 80H >> 6 ;AL=02H
MOV AL, ~ 00000001B ;AL=FEH
MOV AL, ! 1 ;AL=00H
MOV AL, -1 ;AL=FFH
6.3.2 数值表达式
6.3.3 有效地址
.有效地址
.
有效地址
给出存储单元,有效地址的表示就是存储器操
作数的表示。
.
NASM
支持
32
位存储器寻址方式
,也支持
16
位存储器寻址
方式。
.有效地址给出存储单元,有效地址的表示就是存储器操
作数的表示。
.NASM支持32位存储器寻址方式,也支持16位存储器寻址
方式。
.有效地址
MOV
AL, [BX]
MOV
AX, [SI+3]
MOV
AX, [BX+DI
-
5]
MOV
AX, [ECX]
MOV
AX, [ESI+EBX]
MOV
AX, [EDX*4+ESI+8]
MOV AL, [BX]
MOV AX, [SI+3]
MOV AX, [BX+DI-5]
MOV AX, [ECX]
MOV AX, [ESI+EBX]
MOV AX, [EDX*4+ESI+8]
如下指令
说明
有效地址的
表示:
如下指令说明有效地址的表示:
6.3.3 有效地址
.有效地址
MOV
AX, [
wordvar
] ;
直接寻址
MOV
AX, [wordvar+2] ;
直接寻址
MOV
AX, [wordvar
-
3] ;
直接寻址
MOV
AX, [
wordvar+BX
] ;
寄存器相对寻址
MOV
AX, [
SI+wordvar
] ;
寄存器相对寻址
MOV
AX, [
BX+DI+wordvar
] ;
相对基址变址寻址
MOV AX, [wordvar] ;直接寻址
MOV AX, [wordvar+2] ;直接寻址
MOV AX, [wordvar-3] ;直接寻址
MOV AX, [wordvar+BX] ;寄存器相对寻址
MOV AX, [SI+wordvar] ;寄存器相对寻址
MOV AX, [BX+DI+wordvar] ;相对基址变址寻址
设
变量
wordvar
是一
个字存储单元:
wordvar
DW 1234H
设变量wordvar是一个字存储单元:
wordvar DW 1234H
表示
存储单元有效地址的表达式
只能出现在方括号中
。
标号或名字
,当它们表示存储单元内容时,也必须出现在方括号中
。
这
一点与有些汇编器不同
。
表示存储单元有效地址的表达式只能出现在方括号中。
标号或名字,当它们表示存储单元内容时,也必须出现在方括号中。
这一点与有些汇编器不同。
6.3.3 有效地址
.有效地址
MOV
DL, [
ES:
bytevar
] ;
直接寻址
MOV
DL, [
GS:
BX+bytevar
] ;
寄存器相对寻址
MOV DL, [ES:bytevar] ;直接寻址
MOV DL, [GS:BX+bytevar] ;寄存器相对寻址
如下指令说明段超越前缀的表示,其中标识符
bytevar
是一个变量
名:
如下指令说明段超越前缀的表示,其中标识符
bytevar是一个变量名:
段超越前缀也出现
在
方括号中
。
这
一点与有些汇编器不同
。
段超越前缀也出现在方括号中。
这一点与有些汇编器不同。
6.3.3 有效地址
6.3.4 数据类型说明
.数据类型说明的背景
.
大部分
情况下,能够根据存放操作数的寄存器来确定操
作数的类型(尺寸)
。
.
但类似如下指令
,
操作数类型
不明确,
NASM
会报告错误:
MOV [BX], 1
ADD [DI+3], 5
SUB [ESI+ECX*4], 6
.
汇编器
NASM
提供了
BYTE
、
WORD
、
DWORD
等关键字,用于
说明操作数的类型(尺寸)。
把这些关键词称之为类型
符
。
.大部分情况下,能够根据存放操作数的寄存器来确定操
作数的类型(尺寸)。
.但类似如下指令,操作数类型不明确,NASM会报告错误:
MOV [BX], 1
ADD [DI+3], 5
SUB [ESI+ECX*4], 6
.汇编器NASM提供了BYTE、WORD、DWORD等关键字,用于
说明操作数的类型(尺寸)。把这些关键词称之为类型
符。
在
VC2010
的嵌入汇编中,
或生成
的汇编格式目标代码中
,
“
BYTE PTR”
、“
WORD PTR”
和“
WORD PTR”
指定操作数的类型。
在VC2010的嵌入汇编中,或生成的汇编格式目标代码中,
“BYTE PTR”、“WORD PTR”和“WORD PTR”指定操作数的类型。
.数据类型说明示例
MOV
DWORD
[BX], 1 ;
双字
ADD
BYTE
[DI+3], 5 ;
字节
SUB
WORD
[ESI+ECX*4], 6 ;
字
;
MOV
[BX],
DWORD
1 ;
双字
ADD
[DI+3],
BYTE
5 ;
字节
SUB
[ESI+ECX*4],
WORD
6 ;
字
MOV DWORD [BX], 1 ;双字
ADD BYTE [DI+3], 5 ;字节
SUB WORD [ESI+ECX*4], 6 ;字
;
MOV [BX], DWORD 1 ;双字
ADD [DI+3], BYTE 5 ;字节
SUB [ESI+ECX*4], WORD 6 ;字
如下演示
指定操作数的类型
:
如下演示指定操作数的类型:
在NASM中,省略了“PTR”
6.3.4 数据类型说明
.数据类型说明示例
INC
BYTE
[BX] ;
字节
DEC
WORD
[ECX
-
8] ;
字
INC
DWORD
[0100H] ;
双字
;
PUSH
DWORD
99AAH ;
双字
PUSH
DWORD
12345678H ;
双字
PUSH
WORD
99H ;
字
INC BYTE [BX] ;字节
DEC WORD [ECX-8] ;字
INC DWORD [0100H] ;双字
;
PUSH DWORD 99AAH ;双字
PUSH DWORD 12345678H ;双字
PUSH WORD 99H ;字
如下演示
指定操作数的类型
:
如下演示指定操作数的类型:
对于把立即数压入堆栈的
PUSH
指令,在
16
位代码中默认的操作数是字,在
32
位代码中默认的操作数是双字,所以需要明确操作数
类型
由于
PUSH
指令的操作数至少是
16
位的,所以不能使用类型符
BYTE
对于把立即数压入堆栈的PUSH指令,在16位代码中默认的操作数是字,在
32位代码中默认的操作数是双字,所以需要明确操作数类型
由于PUSH指令的操作数至少是16位的,所以不能使用类型符BYTE
6.3.4 数据类型说明
6.4 伪指令语句和变量
伪指令语句主要有
数据定义语句
和
存储单元定义语句
,
前者
定义初始化的数据项,后者定义未初始化的
数据项
。
伪指令语句主要有数据定义语句和存储单元定义语句,
前者定义初始化的数据项,后者定义未初始化的数据项。
.
伪指令语句
就是表示伪指令的语句
。
.
伪指令
并非真正符号化的机器指令。对处理器而言,伪指
令不是指令,但对汇编器而言,它却是指令
。
.
伪指令
主要用于定义变量,预留存储单元
。
.伪指令语句就是表示伪指令的语句。
.伪指令并非真正符号化的机器指令。对处理器而言,伪指
令不是指令,但对汇编器而言,它却是指令。
.伪指令主要用于定义变量,预留存储单元。
6.4 伪指令语句和变量
6.4.1 数据定义语句
6.4.2 存储单元定义语句
6.4.3 常数符号声明语句
6.4.4 演示举例
伪指令语句主要有
数据定义语句
和
存储单元定义语句
,
前者
定义初始化的数据项,后者定义未初始化的数据项
伪指令语句主要有数据定义语句和存储单元定义语句,
前者定义初始化的数据项,后者定义未初始化的数据项
6.4.1 数据定义语句
.数据定义语句格式
[
名字
]
DB
参数表
;
定义字节数据项
[
名字
]
DW
参数表
;
定义字数据项
[
名字
]
DD
参数表
;
定义双字数据项
[名字] DB 参数表 ;定义字节数据项
[名字] DW 参数表 ;定义字数据项
[名字] DD 参数表 ;定义双字数据项
数据
定义语句是常用的伪指令语句。
通过
数据定义语句可为数据项分配存储单元,并根据需要设置其初值
。
还
可用名字(标识符)代表
数据项。
数据定义语句是常用的伪指令语句。
通过数据定义语句可为数据项分配存储单元,并根据需要设置其初值。
还可用名字(标识符)代表数据项。
DB、DW或DD分别是伪指令符。
第一个字母D的含义是“定义”,第二个字母代表了数据类型,分别
是字节(Byte)、字(Word)和双字(DoubleWord)。
.定义数据语句示例
result
db
0, 0 ;
定义
2
个字节,字节值为
0
db
'H', 0DH, 0AH, '$' ;
定义
4
个字节
wvar
dw
-
1 ;
定义
1
个字,值为
FFFFH
dd
5, 17 ;
定义
2
个双字
result db 0, 0 ;定义2个字节,字节值为0
db 'H', 0DH, 0AH, '$' ;定义4个字节
wvar dw -1 ;定义1个字,值为FFFFH
dd 5, 17 ;定义2个双字
如下伪指令演示数据定义语句的使用:
如下伪指令演示数据定义语句的使用:
名字代表语句所定义的若干数据项中,第一个数据项对应
存储单元的有效地址
名字是可选的,如果使用名字,那么它就代表存储单元的有效地址。
确切地说,名字代表语句所定义的若干数据项中,第一个数据项对应
存储单元的有效地址。
6.4.1 数据定义语句
.定义数据语句示例
bvar
db
2+3*4, 0xc3 >> 4 ;
定义
2
个字节,分别是
0EH
和
0CH
vector
dd
(0xABCD<<16)+ 0x1234 ;
定义
1
个双字
=0ABCD1234H
dw
-
1 ;
定义
1
个字
=0FFFFH
bvar db 2+3*4, 0xc3 >> 4 ;定义2个字节,分别是0EH和0CH
vector dd (0xABCD<<16)+ 0x1234 ;定义1个双字=0ABCD1234H
dw -1 ;定义1个字=0FFFFH
如下伪指令演示数据定义语句的使用:
如下伪指令演示数据定义语句的使用:
数据项的初值还可以是数值表达式。
6.4.1 数据定义语句
.存储单元初始化
wordvar
dw
1234H, 55H
dvar
dd
99H
abcstr
db
'A', 'B', 0DH, 0AH, '$'
wordvar dw 1234H, 55H
dvar dd 99H
abcstr db 'A', 'B', 0DH, 0AH, '$'
汇编器
NASM
按照数据定义语句给出的初值,初
始化相关存储单元。而且,为多条紧挨着的数
据定义语句,分配连续的内存单元。
汇编器NASM按照数据定义语句给出的初值,初
始化相关存储单元。而且,为多条紧挨着的数
据定义语句,分配连续的内存单元。
字符是对应的ASCII码值。
采用“高高低低”规则存储
...高地址
wordvar240A0D42410000009900551234...低地址
abcstrdvar
6.4.1 数据定义语句
.存储单元初始化
db
'hello' ;
一个字符串等价于如下
db
'h', 'e', 'l', 'l', 'o' ;
多个字符
;
dd
'
ninechars
'
;
字符串
作为双字数据项
dd
'nine', 'char', 's' ;
相当于
3
个双字
db
'
ninechars
', 0, 0, 0 ;
实际就是这样子
db 'hello' ;一个字符串等价于如下
db 'h', 'e', 'l', 'l', 'o' ;多个字符
;
dd 'ninechars' ;字符串作为双字数据项
dd 'nine', 'char', 's' ;相当于3个双字
db 'ninechars', 0, 0, 0 ;实际就是这样子
等价
等价
6.4.1 数据定义语句
.初始化的变量
warray
dw
4455H, 6677H, 8899H
sum
dd
0
warray dw 4455H, 6677H, 8899H
sum dd 0
.
在
数据定义语句中定义的数据项占用存储单元,可以把
它看作为变量
。
.
在
定义语句中的名字相当于变量名
。类似于高级语言,
通过变量名,可以访问变量,本质上是存取对应的存储
单元。
.在数据定义语句中定义的数据项占用存储单元,可以把
它看作为变量。
.在定义语句中的名字相当于变量名。类似于高级语言,
通过变量名,可以访问变量,本质上是存取对应的存储
单元。
如下
数据定义语句,定义
3
个字变量和
1
个双字
变量:
如下数据定义语句,定义3个字变量和1个双字变量:
6.4.1 数据定义语句
.初始化的变量
warray
dw
4455H, 6677H, 8899H
sum
dd
0
;
------------------------
MOV
AX, [
warray
]
MOV
DX, 0
ADD
AX, [
warray+2
]
ADC
DX, 0
ADD
AX, [
warray+4
]
ADC
DX, 0
MOV
[
sum
], AX
MOV
[
sum+2
], DX
warray dw 4455H, 6677H, 8899H
sum dd 0
;------------------------
MOV AX, [warray]
MOV DX, 0
ADD AX, [warray+2]
ADC DX, 0
ADD AX, [warray+4]
ADC DX, 0
MOV [sum], AX
MOV [sum+2], DX
设有如下数据定义语句,定义
3
个字变量和
1
个双字变量
,
计算
3
个无符号字变量之和,并存放到双字变量
中。
设有如下数据定义语句,定义3个字变量和1个双字变量,
计算3个无符号字变量之和,并存放到双字变量中。
NASM并不发出警告
6.4.1 数据定义语句
.初始化的变量
warray
dw
4455H, 6677H, 8899H
sum
dd
0
;
------------------------
MOV
SI,
warray
;
把变量有效地址送到
SI
MOVZX
EAX, WORD [SI]
MOVZX
EDX, WORD [SI+2]
ADD
EAX, EDX
MOVZX
EDX, WORD [SI+4]
ADD
EAX, EDX
MOV
[
sum
], EAX ;
把
EAX
送到
sum
单元
warray dw 4455H, 6677H, 8899H
sum dd 0
;------------------------
MOV SI, warray ;把变量有效地址送到SI
MOVZX EAX, WORD [SI]
MOVZX EDX, WORD [SI+2]
ADD EAX, EDX
MOVZX EDX, WORD [SI+4]
ADD EAX, EDX
MOV [sum], EAX ;把EAX送到sum单元
计算
3
个无符号字变量之和,并存放到双字变量
中。
另一种实现方法:
计算3个无符号字变量之和,并存放到双字变量中。
另一种实现方法:
把变量有效地址送到SI
把EAX的内容送到sum单元
6.4.1 数据定义语句
6.4.2 存储单元定义语句
.定义存储单元语句格式
[
名字
]
RESB
项数
;
预留字节存储单元
[
名字
]
RESW
项数
;
预留字存储单元
[
名字
]
RESD
项数
;
预留双字存储单元
[名字] RESB 项数 ;预留字节存储单元
[名字] RESW 项数 ;预留字存储单元
[名字] RESD 项数 ;预留双字存储单元
存储单元
定义
语句是
伪指令语句。
利用
存储单元定义语句可以分配存储单元,但没有初始化
。可用
名字代表存储
单元。如果把这样的存储单元视作为变量,那么就是没有初始化的变量。
存储单元定义语句是伪指令语句。
利用存储单元定义语句可以分配存储单元,但没有初始化。可用名字代表存储
单元。如果把这样的存储单元视作为变量,那么就是没有初始化的变量。
“项数”表示要定义的存储单元个数,可以是一个数值表达式。
RESB、RESW或RESD分别是伪指令符。RES的含义是“预留”,
其后字母代表存储单元类型,字节(Byte)、字(Word)和双字
(DoubleWord)。
名字可选,
代表预留
存储单元
的首地址
.定义存储单元
buffer
resb
128 ;
预留
128
个字节
wordtab
resw
4 ;
预留
4
个字
farptr
resd
1 ;
预留
1
个双字
buffer resb 128 ;预留128个字节
wordtab resw 4 ;预留4个字
farptr resd 1 ;预留1个双字
如下伪指令演示存储单元定义语句的
使用:
如下伪指令演示存储单元定义语句的使用:
6.4.2 存储单元定义语句
.定义存储单元
abuff
resb
32*2 ;
预留
64
个字节
wtable
resw
3+5 ;
预留
8
个字
abuff resb 32*2 ;预留64个字节
wtable resw 3+5 ;预留8个字
如下伪指令演示存储单元定义语句的
使用:
如下伪指令演示存储单元定义语句的使用:
“项数”可以是一个数值表达式,
但必须是马上可以计算出结果的表达式。
6.4.2 存储单元定义语句
6.4.3 常数符号声明语句
.常数符号声明语句格式
符号名
EQU
数值表达式
符号名 EQU 数值表达式
汇编过程中,NASM会计算出数值表达式的值,
然后符号就代表计算结果。在随后的程序中,就
可以使用该符号代替这个表达式。
COUNT
equ
5+3*2 ;COUNT
代表
11
MIN
equ
8 ;MIN
代表
8
MAX
equ
MIN + COUNT + 20 ;MAX
代表
39
COUNT equ 5+3*2 ;COUNT代表11
MIN equ 8 ;MIN代表8
MAX equ MIN + COUNT + 20 ;MAX代表39
.常数符号声明语句格式
hello
db
"Hello,world!", 0DH, 0AH, '$' ;15
个字节
hello2
: ;
安排一个标号
MESLEN
equ
hello2
–
hello
;MESLEN
代表
15
dcount
dd
MESLEN ;
定义双字,初始值为
MESLEN
buffer
resb
MESLEN ;
保留
MESLEN
个字节
hello db "Hello,world!", 0DH, 0AH, '$' ;15个字节
hello2: ;安排一个标号
MESLEN equ hello2 – hello ;MESLEN代表15
dcount dd MESLEN ;定义双字,初始值为MESLEN
buffer resb MESLEN ;保留MESLEN个字节
演示
常数符号声明伪指令的使用:
演示常数符号声明伪指令的使用:
6.4.3 常数符号声明语句
.常数符号声明语句格式
hello
db
"Hello,world!", 0DH, 0AH, '$' ;15
个字节
hello2
: ;
安排一个标号
MESLEN
equ
hello2
–
hello
;MESLEN
代表
15
dcount
dd
MESLEN ;
定义双字,初始值为
MESLEN
buffer
resb
MESLEN ;
保留
MESLEN
个字节
hello db "Hello,world!", 0DH, 0AH, '$' ;15个字节
hello2: ;安排一个标号
MESLEN equ hello2 – hello ;MESLEN代表15
dcount dd MESLEN ;定义双字,初始值为MESLEN
buffer resb MESLEN ;保留MESLEN个字节
演示
常数符号声明伪指令的使用:
演示常数符号声明伪指令的使用:
MOV
ESI,
hello
MOV
EDI,
buffer
CLD
MOV
ECX,
MESLEN
;ECX=
字符串
hello
长度
REP
MOVSB
MOV ESI, hello
MOV EDI, buffer
CLD
MOV ECX, MESLEN ;ECX=字符串hello长度
REP MOVSB
名字本身代表对应存储单元的有效地址,
这是取得有效地址
符号表示常数
6.4.3 常数符号声明语句
.两个特别的记号
.
汇编器
NASM
支持在表达式中出现两个特别的记号,即
'
$
'
和
'
$$
'
。
.
利用
这两个记号,可以方便地获得当前位置值
。
.
$
代表它所在源代码行的指令或者数据在段内的偏移
,或者就是当
前位置在段内的偏移。
.汇编器NASM支持在表达式中出现两个特别的记号,即'$'和'$$'。
.利用这两个记号,可以方便地获得当前位置值。
.$代表它所在源代码行的指令或者数据在段内的偏移,或者就是当
前位置在段内的偏移。
jmp
$
jmp $
无限循环
message
db "asdfjkl;"
STRLEN
equ
$
-
message
resb 16
-
(
STRLEN
% 16)
message db "asdfjkl;"
STRLEN equ $ - message
resb 16 - (STRLEN % 16)
如下伪指令使得
message
占用的字节数是
16
的倍数:
如下伪指令使得message占用的字节数是16的倍数:
6.4.3 常数符号声明语句
6.4.4 演示举例
.示例程序dp63.asm
.
流程:
.
接受
用户从键盘输入的某存储单元地址的段值
;
.
接受
用户从键盘输入的某存储单元地址的偏移
;
.
取出
对应存储单元的字节数据,并显示输出。
.
说明:
.
由
用户从键盘分别输入段值和偏移,来指定存储单元,段值和
偏移都采用十六进制表示
。
.
显示
输出的指定存储单元的内容,采用二进制表示
。
.流程:
.接受用户从键盘输入的某存储单元地址的段值;
.接受用户从键盘输入的某存储单元地址的偏移;
.取出对应存储单元的字节数据,并显示输出。
.说明:
.由用户从键盘分别输入段值和偏移,来指定存储单元,段值和
偏移都采用十六进制表示。
.显示输出的指定存储单元的内容,采用二进制表示。
编写一个控制台应用程序,显示指定内存单元的内容。
编写一个控制台应用程序,显示指定内存单元的内容。
.示例程序dp63.asm
segment
code
;
段
code
org 100H ;
起始偏移
100H
begin
:
MOV AX, CS ;
使得数据段与代码段相同
MOV DS, AX ;DS = CS
;
MOV DX, mess1 ;DX = mess1
的偏移
CALL
EchoMess
;
显示输出提示信息
mess1
MOV DX, buffer ;DX = buffer
的偏移
CALL
GetHex
;
由键盘输入一个十六进制数
MOV [
addrSeg
], AX ;
保存,作为指定存储单元的段值
CALL
NewLine
;
形成回车
换行
;
MOV
DX, mess2 ;DX = mess2
的偏移
CALL
EchoMess
;
显示输出提示信息
mess2
MOV DX, buffer ;DX = buffer
的偏移
CALL
GetHex
;
由键盘输入一个十六进制数
MOV [
addrDisp
], AX ;
保存,作为指定存储单元的偏移
CALL
NewLine
;
形成回车换行
segment code ;段code
org 100H ;起始偏移100H
begin:
MOV AX, CS ;使得数据段与代码段相同
MOV DS, AX ;DS = CS
;
MOV DX, mess1 ;DX = mess1的偏移
CALL EchoMess ;显示输出提示信息mess1
MOV DX, buffer ;DX = buffer的偏移
CALL GetHex ;由键盘输入一个十六进制数
MOV [addrSeg], AX ;保存,作为指定存储单元的段值
CALL NewLine ;形成回车换行
;
MOV DX, mess2 ;DX = mess2的偏移
CALL EchoMess ;显示输出提示信息mess2
MOV DX, buffer ;DX = buffer的偏移
CALL GetHex ;由键盘输入一个十六进制数
MOV [addrDisp], AX ;保存,作为指定存储单元的偏移
CALL NewLine ;形成回车换行
获得所指定存储单元的段值
获得所指定存储单元的偏移
6.4.4 演示举例
.示例程序dp63.asm
MOV
ES, [
addrSeg
] ;
取出段值,送到
ES
MOV
BX, [
addrDisp
] ;
取出偏移,送到
BX
MOV
AL, [ES:BX] ;
取出指定存储单元之字节值
CALL
EchoBin
;
按二进制方式显示
;
MOV
AH, 4CH
INT
21H ;
结束程序,返回操作系统
MOV ES, [addrSeg] ;取出段值,送到ES
MOV BX, [addrDisp] ;取出偏移,送到BX
MOV AL, [ES:BX] ;取出指定存储单元之字节值
CALL EchoBin ;按二进制方式显示
;
MOV AH, 4CH
INT 21H ;结束程序,返回操作系统
取得指定存储单元的内容;
显示输出。
6.4.4 演示举例
.示例程序dp63.asm
;
常量声明部分
BUFFLEN
equ
4
;
数据部分
mess1
db
"Segment(
xxxxH
): ",0 ;
提示字符串
mess2
db
"Offset(
xxxxH
): ",0 ;
提示字符串
buffer
db
BUFFLEN ;
输入缓冲区长度
resb
BUFFLEN ;
输入缓冲区
addrSeg
dw
0
;
存放指定的存储单元段值
addrDisp
dw
0
;
存放指定的存储单元偏移
;常量声明部分
BUFFLEN equ 4
;数据部分
mess1 db "Segment(xxxxH): ",0 ;提示字符串
mess2 db "Offset(xxxxH): ",0 ;提示字符串
buffer db BUFFLEN ;输入缓冲区长度
resb BUFFLEN ;输入缓冲区
addrSeg dw 0 ;存放指定的存储单元段值
addrDisp dw 0 ;存放指定的存储单元偏移
常量声明
数据定义
常量声明
数据定义
6.4.4 演示举例
.示例程序dp63.asm
;
功
能:接受由键盘输入的十六进制数,并转换成二进制值
;
入口参数:
DS:DX =
用于存放字符串缓存区的开始地址
;
(首字节含有实际的缓冲区有效长度)
;
出口参数:
AX =
二进制值(由字符串转换所得)
;
说
明:不考虑非法输入,实际输入字符数应是缓冲区字节
数
GetHex
:
PUSH SI ;
保护寄存器
PUSH BX
。。。。。。
。。。。。。
POP
BX ;
恢复被保护寄存器
POP SI
RET ;
返回
;功 能:接受由键盘输入的十六进制数,并转换成二进制值
;入口参数:DS:DX = 用于存放字符串缓存区的开始地址
; (首字节含有实际的缓冲区有效长度)
;出口参数:AX = 二进制值(由字符串转换所得)
;说 明:不考虑非法输入,实际输入字符数应是缓冲区字节数
GetHex:
PUSH SI ;保护寄存器
PUSH BX
。。。。。。
。。。。。。
POP BX ;恢复被保护寄存器
POP SI
RET ;返回
子程序:
GetHex
子程序:GetHex
接受键盘输入的十六进制数字串
将十六进制数字串其转换成值
6.4.4 演示举例
.示例程序dp63.asm
MOV
SI, DX ;SI =
缓冲区地址
XOR CX, CX ;
MOV CL, [SI] ;CX =
缓冲区长度
LEA BX, [SI+1] ;BX =
存放字符的缓冲区首地址
LL1@GetHex
:
;==
接受键盘输入的十六进制数字符串
CALL
GetChar
;
取得一个字符
MOV
[BX], AL ;
依次保存
INC
BX
LOOP
LL1@GetHex ;
继续
;
;==
转换成
数值
MOV SI, DX ;SI = 缓冲区地址
XOR CX, CX ;
MOV CL, [SI] ;CX = 缓冲区长度
LEA BX, [SI+1] ;BX = 存放字符的缓冲区首地址
LL1@GetHex: ;==接受键盘输入的十六进制数字符串
CALL GetChar ;取得一个字符
MOV [BX], AL ;依次保存
INC BX
LOOP LL1@GetHex ;继续
; ;==转换成数值
接受键盘输入的十六进制数字串
6.4.4 演示举例
.示例程序dp63.asm
MOV
CL, [SI] ;CX =
缓冲区长度
LEA
BX, [SI+1] ;BX =
存放字符的缓冲区首地址
XOR
DX, DX ;DX = 0
LL2@GetHex
:
MOV
AL, [BX] ;
依次取得一个字符
INC
BX
CALL
ToBin
;
转换成字符对应的数值
SHL
DX, 4 ;
准备合并
OR
DL, AL ;
合并到一起
LOOP
LL2@GetHex ;
继续
MOV
AX, DX ;AX =
返回值(转换结果)
;
MOV CL, [SI] ;CX = 缓冲区长度
LEA BX, [SI+1] ;BX = 存放字符的缓冲区首地址
XOR DX, DX ;DX = 0
LL2@GetHex:
MOV AL, [BX] ;依次取得一个字符
INC BX
CALL ToBin ;转换成字符对应的数值
SHL DX, 4 ;准备合并
OR DL, AL ;合并到一起
LOOP LL2@GetHex ;继续
MOV AX, DX ;AX = 返回值(转换结果)
;
将十六进制数字串其转换成值
6.4.4 演示举例
.示例程序dp63.asm
;
子程序名:
ToBin
;
功
能:把一位十六进制数字符转换成对应的二进制数值
;
入口参数:
AL =
十六进制数字符
;
出口参数:
AL =
对应二进制数值
;
说
明:如非十六进制数字符,返回
0
ToBin
:
CMP AL, '0'
JB
LL2@ToBin
CMP
AL, '9'
JA
LL1@ToBin
SUB
AL, '0'
;
把‘
0’
-
‘9’
的字符转成对应数值
RET
;子程序名:ToBin
;功 能:把一位十六进制数字符转换成对应的二进制数值
;入口参数:AL = 十六进制数字符
;出口参数:AL = 对应二进制数值
;说 明:如非十六进制数字符,返回0
ToBin:
CMP AL, '0'
JB LL2@ToBin
CMP AL, '9'
JA LL1@ToBin
SUB AL, '0' ;把‘0’-‘9’的字符转成对应数值
RET
子程序:
ToBin
子程序:ToBin
6.4.4 演示举例
.示例程序dp63.asm
LL1@ToBin
:
AND
AL, 11011111B ;
可能小写字母转成大写字母
CMP
AL, 'A'
JB
LL2@ToBin
CMP
AL, 'F'
JA
LL2@ToBin
SUB
AL, 'A'
-
10 ;
把
'A'
-
'F'
的字符转成对应数值
RET
LL2@ToBin
:
MOV
AL, 0 ;
无效字符,缺省值
RET ;
返回
LL1@ToBin:
AND AL, 11011111B ;可能小写字母转成大写字母
CMP AL, 'A'
JB LL2@ToBin
CMP AL, 'F'
JA LL2@ToBin
SUB AL, 'A' - 10 ;把'A'-'F'的字符转成对应数值
RET
LL2@ToBin:
MOV AL, 0 ;无效字符,缺省值
RET ;返回
子程序:
ToBin
子程序:ToBin
6.4.4 演示举例
.示例程序dp63.asm
;
子程序名:
EchoBin
;
功
能:二进制数形式显示
8
位二进制值
;
入口参数:
AL =
二进制数
;
出口参数:无
EchoBin
:
MOV DH, AL
MOV
CX, 8 ;8
位二进制,循环
8
次
LL1@EchoBin
:
RCL
DH, 1 ;
依次移出一位到进位标志
CF
MOV
DL, '0' ;
假设是
0
ADC
DL, 0 ;
考虑实际值
CALL
PutChar
;
显示一个字符
LOOP
LL1@EchoBin ;
继续
RET
;子程序名:EchoBin
;功 能:二进制数形式显示8位二进制值
;入口参数:AL = 二进制数
;出口参数:无
EchoBin:
MOV DH, AL
MOV CX, 8 ;8位二进制,循环8次
LL1@EchoBin:
RCL DH, 1 ;依次移出一位到进位标志CF
MOV DL, '0' ;假设是0
ADC DL, 0 ;考虑实际值
CALL PutChar ;显示一个字符
LOOP LL1@EchoBin ;继续
RET
子程序:
EchoBin
子程序:EchoBin
6.4.4 演示举例
.示例程序dp63.asm
;
功
能:显示字符串
;
入口参数:
DS:DX =
字符串首地址
;
出口参数:无
;
说
明:字符串以
0
作为结束标志
EchoMess
:
PUSH
BX ;
保护寄存器
BX
MOV
BX, DX
LL1@EchoMess
:
MOV
DL, [BX] ;
取出待显示字符
INC
BX ;
依次
OR
DL, DL ;
是否结束符?
JZ
LL2@EchoMess ;
是,转结束
CALL
PutChar
;
否,显示之
JMP
SHORT LL1@EchoMess ;
继续
LL2@EchoMess
:
POP
BX ;
恢复寄存器
BX
RET
;
返回
;功 能:显示字符串
;入口参数:DS:DX = 字符串首地址
;出口参数:无
;说 明:字符串以0作为结束标志
EchoMess:
PUSH BX ; 保护寄存器BX
MOV BX, DX
LL1@EchoMess:
MOV DL, [BX] ;取出待显示字符
INC BX ;依次
OR DL, DL ;是否结束符?
JZ LL2@EchoMess ;是,转结束
CALL PutChar ;否,显示之
JMP SHORT LL1@EchoMess ;继续
LL2@EchoMess:
POP BX ;恢复寄存器BX
RET ;返回
子程序:
EchoMess
子程序:EchoMess
6.4.4 演示举例
.示例程序dp63.asm
;
子程序名:
NewLine
;
功
能:显示输出回车换行
;
出入参数:无
NewLine
:
MOV
AH, 2 ;2
号系统功能
MOV
DL, 0DH ;
回车符
INT
21H ;
显示输出回车
MOV
DL, 0AH ;
换行符
INT
21H ;
显示输出换行
RET
;
返回
;子程序名:NewLine
;功 能:显示输出回车换行
;出入参数:无
NewLine:
MOV AH, 2 ;2号系统功能
MOV DL, 0DH ;回车符
INT 21H ;显示输出回车
MOV DL, 0AH ;换行符
INT 21H ;显示输出换行
RET ;返回
子程序:
NewLine
子程序:NewLine
6.4.4 演示举例
.示例程序dp63.asm
;
子程序名:
GetChar
;
功
能:从键盘读一个键
;
入口参数:无
;
出口参数:
AL =
所读键的
ASCII
码
GetChar
:
MOV
AH,1
INT
21H ;
调用
1
号系统功能键盘输入
RET
;子程序名:GetChar
;功 能:从键盘读一个键
;入口参数:无
;出口参数:AL = 所读键的ASCII码
GetChar:
MOV AH,1
INT 21H ;调用1号系统功能键盘输入
RET
子程序:
GetChar
子程序:GetChar
6.4.4 演示举例
.示例程序dp63.asm
;
子程序名:
PutChar
;
功
能:显示输出一个字符
;
入口参数:
DL =
显示输出字符
ASCII
码
;
出口参数:无
PutChar
:
MOV
AH,2
INT
21H
;
调用
2
号系统功能显示输出
RET
;子程序名:PutChar
;功 能:显示输出一个字符
;入口参数:DL = 显示输出字符ASCII码
;出口参数:无
PutChar:
MOV AH,2
INT 21H ;调用2号系统功能显示输出
RET
子程序:
PutChar
子程序:PutChar
6.4.4 演示举例