dosbox-0.73-3.conf
# 挂载驱动器(将放汇编程序、编译工具文件夹挂载到一个虚拟盘)
mount F: D:\am
# 添加系统临时变量(此时的 F: 代表的是E:\Assembly)
set PATH=%PATH%;F:\MASM;
# 转到 F:
F:
# 进入ASM文件夹
cd F:\ASM
1)mount F: D:\am
mount——是挂载命令语句
F:——是虚拟盘,可以是已存在的盘C:/D:/E:,也可以是不存在的盘F:/G:/H:等
D:\am——汇编程序、编译工具文件夹
结果:F: 代表的是D:\am
(2)set PATH=%PATH%;F:\MASM;
将 MASM 文件中的编译程序添加至临时系统变量中,打开软件就添加,关闭就没有了。
相当于 set PATH=%PATH%;D:\am\MASM;,但是DOSBox软件只能读取只是你挂载的虚拟盘,不能这么写。
(3)F:
转到挂载的 F: 盘
(4)cd F:\ASM
进入ASM文件夹。
相当于cd D:\am\MASM,但是DOSBox软件只能读取只是你挂载的虚拟盘,不能这么写。
windowresolution=original
output=surface
修改为:
windowresolution=1280x800 # 这个是小写字母 x
output=opengl
STACK SEGMENT PARA 'STACK' ;定义堆栈段,段名为 STACK(可以取其他的)
DB 100 DUP('?') ;分配堆栈的大小,设置为100字节,以?填充
STACK ENDS ;堆栈段结束
DATA SEGMENT ;定义数据段,段名为 DATA (可以取其他的)
STRING DB 'HELLO!','$' ;定义字符串数据
DATA ENDS
CODE SEGMENT ;定义代码段,段名为 CODE (可以取其他的)
ASSUME CS:CODE, DS:DATA, SS:STACK ;特别重要,将 CS、DS、SS 指向定义的段
START: MOV AX, DATA ;程序开始的地方
MOV DS, AX
MOV AX, STACK
MOV SS, AX
LEA DX, STRING
MOV AH, 09H
INT 21H
MOV AH, 4CH
INT 21H
CODE ENDS
END START ;程序结束的地方
masm hello.asm
link hello.obj
debug hello.exe
R
命令:查看、改变CPU寄存器的内容
格式: -r [寄存器]
功能:显示和修改CPU中寄存器内容和状态标志值
-r
: 显示所有寄存器的内容
-r ax
: 显示某个寄存器的内容
-r f
: 显示和修改状态标志值
欲修改IF、AF、CF及PF标志,可在显示的各状态标志值之后输入diaccype
D
命令:显示存储单元
采用的是二进制数的十六进制表示,可读性比较差
格式:
-d [地址]
-d [地址范围]
① 显示代码段存储单元的内容
-d cs:0000
显示代码段中从0000H开始的128个字节单元的内容
② 按指定地址显示存储单元的内容。
-d ds:0000
显示数据段中从0000H开始的128个字节单元的内容
③ 按指定地址范围显示存储单元的内容。
-d ds: 0000 003f
如果第一次使用D命令时,没有指定地址或地址范围,则显示代码段的内容; 其后没有指定地址或地址范围的D命令,将在上一次显示内容的基础上,显示其后128个单元的内容。
代码段中偏移地址0000H到000fH的16个存储单元中存放的数据值,对应关系是0000H单元存储的值为F6H,0001H单元存储的值为2DH……,000fH单元存储的值为76H。
……-……v…… 表示上述存储单元中的数据为ASCII码时,在屏幕的显示,如果该数值为控制字符或者不可显示的字符,则以 . 表示。
U
命令:反汇编命令格式:
-u [地址]
-u [地址范围]
功能:对指定地址或地址范围的目标代码进行反汇编在EXAMPLE.EXE程序未执行时使用D命令查看数据段内容,得到的数据段DS寄存器的值为13E1H,使用U命令反汇编后查看指令时,系统为程序分配的数据段DS寄存器的值为13F1H,同样都是系统分配的数据段,为什么两者相差了256个单元呢?
原因是磁盘上的EXE文件包括两部分:一部分为装入模块,另一部分为“重定位信息”。DEBUG调试器在载入EXAMPLE.EXE程序到内存时,这两部分均调入内存,在完成对装入模块的重定位后,重定位信息即被丢弃,然后再在同一内存块的用户程序上方(低地址处)偏移地址为00H~FFH的单元自动生成一个有256个字节的数据块,该数据块被称为“程序段前缀”(Program SegmentPrifix,简称PSP)。载入程序时,系统自动给DS,ES,FS和GS赋值,令DS=ES=存放PSP的段基址,FS=GS=0,CS:IP=用户程序的启动地址,然后系统将控制权交给用户程序
用户必须注意系统给DS,ES段寄存器所赋的初值并不等于用户程序数据段、附加数据段的段基址,由于PSP的存在,两者相差了256个字节,因此用户程序一开始就必须对DS进行初始化(程序中如使用ES段,也必须初始化)
G
命令:执行命令
格式:-g [=地址1][地址2]
功能:从地址1开始执行程序,一直执行到地址2。
若程序能够正确地执行结束,屏幕将显示当前寄存器的执行结果及后一条将要执行的指令。这时用户可以查看寄存器中的数据变化情况,也可以使用D命令查看各个段的信息。用户可以使用两种方法来确定地址1和地址2的具体值:其一,在汇编时,产生LST文件,用文本编辑器查看*.LST文件;其二,在DEBUG中,使用U命令查看程序。例如:在EXAMPLE.ASM程序中,最后一条指令是INT21H,该指令的地址为0018H,故可以使用命令:g=00000018
E
命令:改变内存中的内容
格式1:-E地址 [数据表]
功能:用给定的数据表来替代指定范围的存储单元内容。
格式2:-E地址
功能:逐个单元相继修改存储单元内容。
T
: 单步执行命令
格式:-t [指令数]
功能:执行一条或多条指令。每执行一次,则显示所有寄存器内容和状态标志值。
如果不指定指令数,则执行当前CS:IP指定地址的一条指令。显示这条指令执行后所有寄存器内容、状态标志值,并显示后一条将要执行的指令。如果指定指令数,则从当前CS:IP指定地址开始执行指定数目的指令,并显示每一条指令执行后的结果。
T命令执行指令时,如果指令中涉及到数据段,则DEBUG调试器自动显示该数据段中相应单元的数值。
Flags 中的状态标志的状态表示符号
G
命令:跳转指令
P
命令:直接执行完不是单步执行
DEBUG [[drive:][path]filename [testfile-parameters]]
DEBUG调试器可选参数中
[drive:]:表示被装载文件所在的驱动器
[path]:表示被装载文件所在的文件夹
filename:表示被装载文件名称
[testfile-parameters]:表示调试参数
注:[]表示可选项
该提示信息指出,具体DEBUG调试器命令可在运行DEBUG调试器后输入?得到显示。
格式2: -?
功能:显示DEBUG调试器命令。该命令可以显示命令的具体内容和参数
q
命令: 退出命令将汇编语言源程序编译成目标程序的加工程序称为汇编程序。这一加工过程称为汇编。
汇编程序与汇编语言程序是两个不同的概念。汇编程序是用来将汇编语言程序编译成机器代码的工具;汇编语言程序是用户根据实际需要编写的程序。
汇编语言示例程序:
NAME EXAMPLE
DSEG SEGMENT
DATA1 DB 4 DUP(1), 10H,11,0AH,0,0BH
SUM DB ?
COUNT EQU 9
DSEG ENDS
SSEG SEGMENT
STACK DB 100H DUP(?)
SSEG ENDS
CSEG SEGMENT
ASSUME CS:CSEG,DS: DSEG,SS:SSEG
START:
MOV AX, DSEG
MOV DS,AX
XOR AL,AL; AL 清零
MOV CX,COUTN; 设置循环操作的次数
LEA SI,DATA1; SI指向数据区的起始位置
LOOP1: ADD AL,[SI];将SI所指的数据加到AL中
INC SI;SI指向下一个字节
LOOP LOOP1;CX减1计数,减去1后不为0则跳转至LOOP1标号处
MOV SUM,AL;将DATA1 中的9个字节之和送变量SUM
MOV AH,4CH
INT 21H; 返回DOS
CSEG ENDS
ENDS START
(1)汇编语言程序采用以SEGMENT和ENDS定义的段结构,一个汇编语言程序由若干个段组成。
(2)段中包含两种语句:指令语句,即前面介绍的指令,以及伪指令语句,简称伪指令。
(3)语句中包含若干元素:标识符,保留字,表达式等。
① 段超越前缀:
该运算符用于给变量、标号或地址表达式临时指定一个段属性,其格式为 段寄存器名:地址表达式
或段名:地址表达式
MOV AL, ES:[1000H] ; 以(ES)作为段地址,以1000H作为偏移地址
MOV AL, [1000H] ;以(DS)作为段地址,以1000H作为偏移地址送AL (段地址的属性默认为DS,当使用超越前缀时,会改变段的属性)
② 类型运算符PTR
该运算符用于给变量、标号或地址表达式临时指定一个类型。其格式为: 类型PTR地址表达式
MOV WORD PTR[2000H],0 ; 将偏移地址为2000H的字单元,即2000H和2001H两字节清0。
③ 定义类型运算符THIS
该运算符具有与PTR类似的功能,可用于指定某个变量、标号或地址表达式的类型,但在具体用法上有区别。其格式为标识符EQU THIS类型
① 取段地址运算符SEG
该运算符产生其后的变量或标号所在段的段地址。
MOV AX, SEG DATA1;将DATA1所在段的段地址送AX
② 取偏移地址运算符OFFSET
该运算符产生其后的变量或标号的偏移地址
MOV BX, OFFSET DATA1; 将变量DATA1的偏移地址送BX
③ 取类型运算符TYPE
该运算符产生其后的变量或标号的类型值。
④ 取变量单元数运算LENGTH
该运算符产生其后变量所包含的单元个数。该运算的结果根据该变量定义伪指令中第一个表达式的形式而定。若第一个表达式为重复子句“n DUP(数值表达式)”,则LENGTH运算的结果为重复因子n;否则结果为1。伪指令中“n DUP(数值表达式)”等同于将括号中的表达式重复n次。
⑤ 取变量总字节数运算符SIZE
该运算符产生其后变量所包含的总字节数。
EQU
伪指令标识符EQU
COUNT EQU 9; 定义一个符号常量,使之等同于9
ADDR EQU ES: [BX][SI]; 使得ADDR等同于地址表达式ES: [BX][SI]
=
伪指令count =9
count=count+1
注意:EQU、 = 伪指令仅仅是对程序中某些符号进行等价说明,并不实际分配存储单元,因此,用EQU、 = 伪指令定义的符号不占存储单元
DB
伪指令[变量] DB一个或多个表达式
。DATA1 DB 0,45H,0FFH,?
DATA2 DB 'HELLO!'
DATA3 DB 10,2DUP(2DUP(1,2),3)
《易错点》
其数据在内存中的表示如下图:
先定义的数字存放在低字节,字符串按照字节由低到高依次存放。(“HELLO”中H对应低字节)
DW
伪指令[变量] DW
一个或多个表达式。《易错点》
ARRAYW DW -1,1234H,2 DUP(-32768)
ADDR DW ARRAYW +2
STRING DW 'EH','LL',!O'
其数据在内存中的表示如下图:
数据中低位对低位,高位对高位
字符串中高位对应高位,地位对应地位(“EH”中E对应高地址)
DD
伪指令除上述3种变量定义伪指令外,还有3字变量定义伪指令(DF伪指令)、4字变量定义伪指令(DQ伪指令)和10字节变量定义伪指令(DT伪指令)。
段定义伪指令指示汇编程序如何按段组织程序和使用存储器。
SEGMENT
和ENDS
伪指令格式:段名SEGMENT [定位方式][组合方式][ ‘类别’]ASSUME
伪指令格式:ASSUME段寄存器:段名 [,段寄存器:段名…]
注意:ASSUME伪指令只是告知汇编程序有关段寄存器将被设定为哪个段的段地址,而段寄存器必须通过指令来设定具体值。
例如:示例程序中在使用上述ASSUME伪指令后,通过如下指令给DS设定具体值。
MOV AX,DSEG
MOV DS,AX
ORG
伪指令在程序设计中,常把具有某种功能的程序段设计成一个过程。80x86宏汇编语言用于过程定义的伪指令的格式为
过程名 PROC [NEAR 或 FAR]
; 过程体
过程名 ENDP
其中过程名由程序员指定,且起始处和结束处的过程名一致。过程体为过程内的指令和伪指令序列。定义一个近过程时,参数NEAR可省略
这类指令一般放在程序的起始位置,用来通知汇编程序以下程序中使用哪一种指令集
数据传送指令用于寄存器、存储器或输入/输出端口之间传送数据或地址
MOV目的操作数,源操作数
MOV AX,BX; AX<-(BX) 将BX的内容送到AX中
MOV CL,80H;CL<- 80H
MOV AL,[2000H]; 将EA为2000H(段地址取DS的值)单元的值送到AL中
说明:
PUSH 源操作数
POP 目的操作数
说明:
XCHG 目的操作数, 源操作数
XLAT
说明: 这是一条专门用于AL 和字节表中某一存储单元之间进行数据传送的指令。字节表的首地址在BX中,根据AL设置偏移地址,就可以将该单元的内容送到AL中。
IN 累加器 端口地址
【例1】
IN AX,16H; 从端口16H输入一个字到AX中
【例2】
MOV DX, 280H
IN AL,DX; 从端口280H输入一个字节到AL
说明: 该指令以及后述的OUT指令时专用于累加器和I/O端口之间进行数据传送的指令。
OUT端口地址,累加器
LEA目的操作数,源操作数
【例】
MOV BX, 0408H
MOV SI,2000H
LEA BP,[BX+SI+6] ; 将240EH 送BP
LDS 目的操作数,源操作数
LES 目的操作数,源操作数
说明:
参与算数运算的二进制数可以是单字节或者双字节数,也可以时无符号或者有符号数
(×表示根据操作结果设置标志;-表示标志不确定;空白表示标志不受影响)
ADD 目的操作数, 源操作数
否则PF=0。
6. CF运算时最高位产生进位时,即字节运算结果超出无符号数的范围(0~ 255),字运算的结果超出字无符号数的表达范围(0~65535) 时,CF=1; 否则CF=0。 在把操作数视为无符号数时,可通过该标志了解结果是否溢出。
【例】 ADD AL, BL
设(AL)=0A4H,(BL)=5CH,则指令执行后,(AL)=0,OF=0,SF=0,ZF=1,AF=1,PF=1,CF=1
当把相关数据视为有符号数,从OF=0可知相加结果未溢出,也即AL的内容“0”就是两个有符号数0A4H(-01011100B)和5CH(+01011100B)之和。
当把相关数据视为无符号数,从CF=1可知相加结果产生进位也即“100000000B”就是两个无符号数0A4H(10100100B)和5CH(01011100B)之和。
说明:源操作数和目的操作数类型必须一致,即同为字节或同为字,且两者不能同为存储器操作数(这一点适用于所有双操作数的算术运算指令)。
【例】
MOV DX, 2000H
MOV AX, 8A04H
ADD AX,9D00H
ADC DX, 45H
此程序段实现多字节数20008A04H与459D00H的相加。DX存放有被加数的高两字节,AX存放有被加数的低两字节。ADD指令实现两数低两字节的相加,相加后(AX)=2704H,CF=1(相加结果超过两个字节)。ADC指令实现两数高两字节的相加,且将CF(即低两字节相加产生的进位)加至DX,使DX内容为2046H。
INC 目的操作数
【例】
MOV SI, 2000H
MOV AL,[SI]
INC SI
ADD AL,[SI] ; (AL) 为2000H单元和2001单元内容之和。
SBB 目的操作数, 源操作数
SBB 目的操作数, 源操作数
DEC 目的操作数
NEG目的操作数
CMP 目的操作数,源操作数
MUL 源操作数
【例】
MUL CL; AL,CL 中的无符号数之积送AX
MUL [SI] 为错误指令,原因在于计算机无法识别源操作数是字节操作数还是字操作数;
MUL WORD PTR [SI]; AX中的无符号数与SI所指单元的无符号数相乘,乘积送DX和AX。
IMUL源操作数
例:
MOV AL, OFCH; -4 送 AL
MOV CL, 1FH; +31送CL
IMUL CL; (AL)与(CL)之积-124送AX,即(AL)=84H,(AH)=FFH。此时,CF=OF=0, 标志着(AH) 是(AL)的符号扩展。
DIV源操作数
MOV AX, 1001H; 4097送AX;
MOV CL,20H; 32 送CL;
DIV CL; (AX)与(CL) 相除,商128送AL, 余数1送AH。即(AL)=80H, (AH)=01H
IDIV 源操作数
例如:
MOV CX,4
IDIV CX; 若已知DX,AX中放有4001H, 则该指令执行后,(AX)=1000H,(DX)=0001H
若已知DX,AX中放有-4001H, 则该指令执行后,(AX)=F000H(即-1000H),(DX)=FFFFH(即-1)
CBW
【例1】
MOV AL,76H; +76H 送AL;
CBW ; 0076送AX,即+0076送AX。
【例2】
MOV AL,98H; -68H送AL;
CBW; FF98H送AX, 即-0068H送AX
CWD
前面所述的算术运算都是针对二进制数,但人们最为常用的却是十进制数。在用计算机进行算术运算时,可以先将操作数做十→二进制转换,然后做二进制数算术运算,再将结果做二→十进制转换。为了便于十进制数的运算,8086/8088系统还提供了一组十进制数算术运算调整指令,该类指令在4.1 中有详细的介绍。
(×表示根据操作结果设置标志;-表示标志不确定;空白表示标志不受影响。)
NOT目的操作数
【例】
MOV AX,0
NOT AX; 使得(AX)为FFFFH
AND
格式:AND 目的操作数,源操作数
作用:将目的操作数和源操作数按位相与,结果送目的操作数。该指令常用于屏蔽目的操作数的某些位,即使得目的操作数的某些位置置为0,其余保持不变。
OR
格式:OR目的操作数,源操作数
作用: 将目的操作数与源操作数按位相或,结果送目的操作数。该指令常用于使得目的操作数的某些位置为1,其余位保持不变。
XOR
格式:XOR 目的操作数,源操作数
作用:将目的操作数与源操作数按位做异或操作,结果送目的操作数。该指令常用于判断两个数中的哪些位不同,或用于改变指定位的状态。
TEST
格式:TEST 目的操作数,源操作数
作用:与AND指令基本相同,唯一的区别是:目的操作数保持不变。该指令常用于检测某种条件是否满足,但又不希望改变目的操作数的场合。
TEST AL,01H; 可用此指令检测AL最低位的状态。若AL最低位为0,则两个操作数按位相与的结果为0,从而ZF=1; 若AL的最低位为1,则结果为1, 从而ZF=0。
说明:逻辑运算指令中两个操作数不能同为存储器操作数。
移位指令包括算数移位指令,逻辑移位指令,循环移位指令。这些指令只有目的操作数而无源操作数,并在指令中给出移位的位数。而且此位数只能用1或者CL表示。
算数移位指令(SAL,SAR)用于有符号数,而逻辑移位指令(SHR, SHL)用于无符号数。操作数的左移意味着小数点的相对右移。
SHL/SAL 目的操作数,计数
【例1】
MOV AL,16H
SHL AL,1; 使得(AL)即00010110B左移一位。移位后,(AL)=00101100B,是原值的两倍。
【例2】
MOV BH,OEEH
MOV CL,2
SAL BH,CL; 使BH中的有符号数11101110B(-18)左移两位, 变成10111000B(-72),是原值的4倍。
SHR
格式:SHR 目的操作数,计数
作用:将目的操作数右移若干位。每右移一位,高位均补0, 最低位送CF。 该指令可以方便的实现无符号数除以 2 n 2^n 2n的运算。
SAR
格式:SHR 目的操作数, 计数
作用:将目的操作数右移若干位,高位均保持不变 ,最低位送CF.
ROL
格式:ROL 目的操作数,计数
作用:将目的操作数循环左移若干位。每左移一位,左移的最高位送给最低位和CF。
ROR
格式:ROR 目的操作数,计数
作用: 将目的操作数循环右移若干位,每右移一位,右移前的最低位送最高位和CF。
RCL
格式:RCL 目的操作数,计数
作用: 将目的操作数连通CF循环左移若干位。每左移一位,左移前的最高位送至CF, 左移前的CF送最低位。
RCR
格式:RCR 目的操作数,计数
作用:将目的操作数连同CF循环右移若干位。每右移一位,右移前的CF送最高位,右移前的最低位送CF。
《汇编语言程序设计》丁辉主编