作为汇编语言的课程笔记,方便之后的复习与查阅
本篇为课程第十次课内容
硬指令:使CPU产生动作、并在程序执行时才处理的语句
执行性语句——由硬指令构成的语句,它通常对应一条机器指令,出现在程序的代码段中,格式:
标号: 硬指令助记符 操作数,操作数 ;注释
again: mov dx, offset string ;注释
伪指令(Directive)——不产生CPU动作、在程序执行前由汇编程序处理的说明性语句
伪指令与具体的处理器类型无关,但与汇编程序的版本有关
说明性语句——由伪指令构成的语句,它通常指示汇编程序如何汇编源程序:
名字 伪指令助记符 参数,参数,… ;注释
string db ‘Hello,world’ ;注释
DB
就是伪指令变量定义(Define)伪指令为变量申请固定长度的存储空间,并可同时将相应的存储单元初始化
变量定义伪指令要放在.exit
后,end
之前,因为它不是可执行的语句
变量名为用户自定义标识符,表示初值表首元素的逻辑地址;用这个符号表示地址,常称为符号地址。设置变量名是为了方便存取它指示的存储单元。变量名可以没有。这种情况,汇编程序将直接为初值表分配空间。
初值表是用逗号分隔的参数
主要由数值常数、表达式或?
、DUP
组成
?
——表示初值不确定,即未赋初值BUFFER DB ?
DUP
——表示重复初值DUP
的格式为:重复次数 DUP(重复参数)
BUFFER DB 10 dup(0)
BUFFER DB 10 dup(?)
DB
——定义字节伪指令
DW
——定义字伪指令
DD
——定义双字伪指令
DF——定义3字伪指令
DQ——定义4字伪指令
DT——定义10字节伪指令
重点掌握前三个
DB
伪指令用于分配一个或多个字节单元,并可以将它们初始化为指定值
初值表中每个数据一定是字节量(Byte),存放一个8位数据:
X db 'a',-5
db 2 dup(100),? ;第二行没有带名字,默认由x往下继续进行内存分配
Y db 'ABC'
初值表中每个数据一定是字量(Word),一个字单元可用于存放任何16位数据:
count dw 8000h,?,'AB' ; A在高地址处
maxint equ 64h ; equ是等价的意思,表示之后maxint就是64h
number dw maxint
array dw maxint dup(0)
初值表中每个数据是一个32位的双字量(Double Word):
vardd DD 0,?,12345678h
farpoint DD 00400078h
PTR
操作符使名字或标号具有指定的类型
BYTE
/WORD
/DWORD
/FWORD/QWORD/TBYTEmov byte ptr [2000H],10H
使用PTR
操作符,可以临时改变名字或标号的类型
NUM1和NUM2单元中各存放着一个双字无符号数,编制程序计算两数之和,将结果存于SUM双字单元中,进位保存到FSUM字节单元中
.model tiny
.code
.startup
mov ax,word ptr num1 ;处理低16位
add ax,word ptr num2
mov word ptr sum,ax ;保存低16位
mov ax,word ptr num1+2 ;处理高16位
adc ax,word ptr num2+2
mov word ptr sum+2,ax ;保存高16位
mov dx,0 ;最高进位
rcl dl,1
mov fsum,dl ;保存进位
.exit 0
num1 dd 82348567H
num2 dd 87658321H
sum dd ?
fsum db ?
end
也可以用串操作
ddvarw为一个32位的数据12ab56cdH,编程将其整个循环左移4位(使用顺序结构)得到 2ab56cd1H
.model tiny
.code
.startup
mov ax,word ptr ddvar ;低16位
mov dx,word ptr ddvar+2 ;高16位
mov cl , 4
mov bh , dh ;保存高8位到BH
mov bl , ah ;保存低8位到BL
shl dx , cl ;高16位左移 4位
shl ax , cl ;低16位左移 4位
shr bh , cl ;高8位右移4位,高4位到bh中
shr bl , cl ;低8位右移 4位,低4位到bl中
or dl , bl ;原低4位转到高4位
or al, bh ;原高4位转到低4位
.exit 0
ddvar dd 12ab56cdh
end
用查表法,实现一个8位二进制数(00-0FH)转换为ASCII码显示
.model tiny
.code
.startup
mov bx,offset ASCII ;BX指向ASCII码表
mov al,hex ;AL取得一位16进制数,
and al,0fh ;只有低4位是有效的,高4位清0
xlat ; 换码:AL←DS:[BX+AL]
mov dl,al ;入口参数:DL←AL
mov ah,2 ;02号DOS功能调用
int 21h ;显示一个ASCII码字符
.exit 0
ASCII db 30h,31h,32h,33h,34h,35h
db 36h,37h,38h,39h ;0~9的ASCII码
db 41h,42h,43h,44h,45h,46h ;A~F的ASCII码
hex db 0bh ;任意设定了一个待转换的1位16进制数
end
CMP
、TEST
等执行后形成的状态标志Jcc
和JMP
可以实现分支控制比较两个数大小:在DATA1和DATA2单元中各有一个16位二进制无符号数,找出其中较小的数,存于MIN单元中
.model tiny
.code
.startup
mov ax,data1
cmp ax,data2
jb next
mov ax,data2 ;CF=0
next:
mov min,ax ;存结果
.exit 0
data1 dw 2000h
data2 dw 3f80h
min dw ?
end
判断变量var中的值,若为正数,在result中存入1;为负数,在result中存入-1;为零,在result中存入0
.model tiny
.code
.startup
mov ax,var
cmp ax,0
jz zero ;等于0
jg great ;大于0
mov ax,0ffffh ;小于0
jmp ext
zero: mov ax,0
jmp next
great: mov ax,0001h
next: mov result,ax
.exit 0
var dw 8001h
result dw 0
end
(了解即可)
需要在数据段事先安排一个按顺序排列的转移地址表。因为转移地址为16位偏移地址,所以表地址偏移量需要加2(type=2)调整。可用JMP
指令的变址寻址,或寄存器间接寻址,或基址变址寻址方式来实现跳跃表法的程序
Table dw disp1,disp2,disp3,disp4,disp5,disp6,disp7,disp8
.model tiny
.code
.startup
start1:
mov dx,offset msg ;9号功能显示字符串
mov ah,9
int 21h
mov ah,1 ;1号功能获取用户输入
int 21h
cmp al,'1' ;输入不是1~8,则跳转回去
jb start1
cmp al,'8'
ja start1
and ax,000fh ;设置地址偏移
dec ax
shl ax,1 ;因为是双字,所以地址偏移需要用shl来乘2
mov bx,ax
jmp table[bx]
start2:
mov ah,9
int 21h
.exit 0
disp1:
mov dx,offset msg1
jmp start2
disp2:
mov dx,offset msg2
jmp start2
……
disp7:
mov dx,offset msg7
jmp start2
disp8:
mov dx,offset msg8
jmp start2
Msg db 'Input Number(1~8):',0dh,0ah,'$'
Msg1 db 'Chapter 1!',0dh,0ah,'$'
Msg2 db 'Chapter 2!',0dh,0ah,'$'
Msg3 db 'Chapter 3!',0dh,0ah,'$'
Msg4 db 'Chapter 4!',0dh,0ah,'$'
Msg5 db 'Chapter 5!',0dh,0ah,'$'
Msg6 db 'Chapter6!',0dh,0ah,'$'
Msg7 db 'Chapter 7!',0dh,0ah,'$'
Msg8 db 'Chapter 8!',0dh,0ah,'$'
Table dw disp1,disp2,disp3,disp4,
dw disp5,disp6,disp7,disp8
end
例1: 求1+2+3+…+100的和,存在sum字单元
.model tiny
.code
.startup
xor ax,ax ;被加数AX清0
mov cx,100
again:
add ax,cx ;从100,99,...,2,1倒序累加
loop again
mov sum,ax ;将累加和送入指定单元
.exit 0
sum dw ?
end
例2:把BX
中的数以十六进制的形式显示在屏幕上。比如BX
=8F6AH,屏幕显示 8F6AH
这个例子要重点理解
bx
中数据转成ascii码 mov ch, 4 ;循环4次
rotate:
mov cl, 4 ;每次移位4位
rol bx, cl
mov al, bl ;只取bx低4位
and al, 0fh
add al, 30h ;’0’-’9’ ASCII 30H-39H
cmp al, 3ah
jl printit ;有符号数的比较
add al, 7h ;’A’-’F’ ASCII 41H-46H
printit:
mov dl, al
mov ah, 2
int 21h
dec ch
jnz rotate
例3:在数据段中从buffer单元开始存放10个16位二进制有符号数,把其中最大数找出来存于MAX单元中
.model tiny
.code
.startup
mov bx,offset buffer
mov cx,10
mov ax,[bx]
circle:
inc bx ;16位,地址一次要加2
inc bx
cmp ax,[bx]
jge next
mov ax,[bx]
next:
loop circle
mov max,ax
.exit 0
buffer dw -100,3000,-1,22,8000h
dw 9232,0,-3632,-3144,6322
max dw ?
end