一、debug的使用,模拟8086的情况
d 7c0:0,查段地址为7c0,偏移地址为0的内存中的数据,是十六进制表示的数
d 9000:0,查段地址为9000,偏移地址为0的内存中的数据,是十六进制表示的数
r,会显示所有寄存器中的值,比如ax,bx,cx,dx,cs,ip等
r cs,根据提示可以调整cs寄存器的值
a 1000:0 ,根据提示,可以从1000:0处开始输入汇编指令,比如mov ax,1c9aH,或者mov ax,126
e 1000:0000 01 02 03 04,表示将01 02 03 04顺序填入1000:0000表示的内存处
u 1000:0,可以查1000:0内存处的数据及其对应汇编指令
t,执行cs:ip寄存器所指的指令
g 0012,从cs:ip执行到cs:0012处,中间不停顿
p ,遇到loop循环,则一次把所有循环执行完再退出。
二、各寄存器的作用
1、ax,bx等一般寄存器,可暂存数据
2、cs,ip
下一条要执行的指令存储在cs为段地址,ip为偏移地址的内存中
3、ds
数据段寄存器,比如mov al,[0],表示将ds:0这个内存中的数字传入al中。
要将内存10000H中的数传入al中,则应该这样:
mov ax,1000
mov ds,ax ,因为不能直接mov ds,1000
mov al,[0],寄存器al若为16位,则内存中有一个字要移入al,要是为32位,则内存中有2个字要移入al
mov bl,[ax],将ds:ax表示的内存的字节传入bl寄存器中
mov bx,[ax],将ds:ax表示的内存的字传入bx寄存器中
4、ss,sp
ss存储堆栈段的段地址,sp存储堆栈段的偏移地址,push和pop指令涉及到的内存就是ss:sp指向的内存
5、cx 计数寄存器
主要是存储循环程序要循环执行的次数。存放程序在内存中的长度?
6、注意段寄存器cs,ds,ss均不能直接将数据输入。
7、在mov ax,[si+di]这个[。。。]省略号只能填入如下四个寄存器:bx,si,di,bp,其余的比如ax,cx,dx均是错误的,要是ss,cs,ds,更是错误的。
在[。。。]中使用bp,则段地址默认为ss,显性指示段地址除外。
三、内存相关部分参见二
1、
a、mov al,[ax],其中的al指明是字节操作,即一次只移动一个字节的内存
mov ax,[0],其中的ax指明是字操作,即一次移动一个字的内存
b、若没有寄存器,则可以使用word ptr标明是字操作,这是在masm中的用法,比如 inc word ptr ds:[0]
用byte ptr标明这是字节操作,这是在masm中的用法,比如 inc byte ptr ds:[0]
c、push [1000H],不用指明,直接进行字操作
四、各种指令
1、mov,移动,比如mov ds,ax将ax中的数据移入ds中
2、add,加法,比如add ax,bx,将bx中的值与ax中的值相加并存入ax中
3、sub,减法,比如sub ax,bx,将ax中的值减去bx中的值并存入ax中
4、push,入栈,比如push ax,将ax寄存器中的值压入堆栈ss:sp指向的内存当中,并把sp的值改为sp-2(这是在8086当中,因为ax是16位寄存器,而内存单元为8位,因此一个寄存器的值要用两个内存
单元来存放)
5、pop,出栈,比如pop ax,将ss:sp指向的内存的值送入ax中,并把sp的值改为sp+2
pop [0],将ss:sp内存中的数据弹出到ds:0内存中,注意pop操作是字为单位的操作
6、注意push和pop指令中的超栈的界限问题
7、inc bx将bx中的值加1。
8、dec bx将bx中的值减1。和inc bx正好相反。
五、microsoft asm格式下的各种命令:
0、一个程序要编译运行的基本架构:
assume cs:code
code segment
start: ....
mov ax,4c00H
int 21H
code ends
end
这几行是基本的,不然程序无法编译运行。
1、程序完后要输入
mov ax,4c00H
int 21H
帮助程序返回。
2、利用loop实现循环
mov cx,11,将cx寄存器值置为11
s:add ax,ax,执行ax=ax+1
add bx,bx,执行bx=bx+1
loop s,执行cx=cx-1,cx==0,则往下,cx!=0,则转到s标记的内存地址中继续执行
3、在汇编程序中,数据不能由字母开头,故
mov ax,FFFFH不合法,要改为mov ax,0FFFFH
4、debug中 mov ax,[0]表示将ds:[0]内存中的值送入ax中
在masm汇编源程序中, mov ax,[0],表示将0送入ax中
在源程序中可修改为:mov ax,ds:[0]或者mov ax,[bx]或者 mov ax,cs:[0]这里的cs,ds就是显示的指定段寄存器,一般默认段寄存器为ds
5、end start在masm中表示汇编程序在start指定的地方开始执行,要是end d,则表示在masm中汇编程序在d标号指定的地方开始执行
6、如果某个地址的段地址是ds,偏移地址是bx+200,则要将这个位置的数据传到ax中,可以这样:
mov ax,[bx+200]或者mov ax,200[bx]或者mov ax,[bx].200
偏移地址也可以改为bx+si或者bx+di,此时的格式:
mov ax,[bx+si]或者mov ax,[bx][si]
偏移地址也可以为sb+si+200,此时的格式为
mov ax,[bx+si+200];mov ax,[200+bx+si];mov ax,200[bx][si];mov ax,[bx].200[si];mov ax,[bx][si].200均可
7、除法指令div
div byte ptr es:[0],该指令的结果:(al) = (ax)/((es)16+0)的商,(ah) = (ax)/((es)16+0)的余数
div word ptr [bx+si+8],该指令的结果:(ax) = [(dx)10000H+(ax])/((ds)16+bx+si+8)的商,(dx) = [(dx)10000H+(ax])/((ds)16+bx+si+8)的余数
div bx,该指令的结果:(ax) = [(dx)10000H+(ax])/(bx)的商,(dx) = [(dx)10000H+(ax])/(bx)的余数
8、jmp指令
a、jmp short 标号:段内短转移,只能在一个段内转移,并且转移的距离范围是-128~127
jmp near ptr 标号:段内近转移,转移距离为-32768~32767
jmp far ptr 标号:段间转移,far ptr指明了指令用标号的段地址和偏移地址修改CS和IP。
jmp 16位寄存器:其中IP地址放在16位寄存器中。
jmp word ptr 内存单元地址:其中内存单元地址存放的是IP的值。假如ds:[0]这个内存单元值为0123H,则jmp word ptr ds:[0]表示下一条指令执行地址为
cs:0123H
jmp dword ptr 内存单元地址:其中内存单元地址存放着2个字,高地址为CS,低地址为IP。比如:
mov ax,0123H
mov ds:[0],ax
mov word ptr ds:2,0
jmp dword ptr ds:[0] 执行后,(CS)=0,(IP)=0123H
9、jcxz指令
这是有条件转移指令,所有的有条件转移指令都是短转移,即在段内转移。该指令对IP的修改范围为:-128~127
jcxz 标号:如果(cs)=0,则转到标号处开始执行,否则顺序向下执行。
10、loop指令
这是循环指令,所有的循环指令都是短转移,即在段内转移。该指令对IP的修改范围为:-128~127
loop 标号:(cx)=(cx)-1,如果(cs)!=0,则转到标号处开始执行,否则顺序向下执行。此处转移条件和jcxz正好相反。
11、ret和retf指令
ret指令后,(ip)= (sp),(cs)不变,然后(sp) = (sp ) +2,该指令实现近转移,即弹出堆栈sp中的值作为ip的值
retf 指令后,(ip)= (sp),(cs)= (sp)+2,然后(sp) = (sp)+4,即先弹出ip的值,再弹出cs的值,即保存时先push cs,再push ip,该指令实现远转移
12、call指令
call 标号:把本指令(指call 标号)下一条指令的ip压入sp,并转到标号处执行。段内近转移,转移距离为-32768~32767
call far ptr 标号:把本指令(指call far ptr 标号)下一条指令的cs压入sp,然后把本指令下一条指令的ip压入sp,然后转到标号处执行
call 16位寄存器:把本指令(指call 16位寄存器)下一条指令的ip压入sp,然后转到寄存器所指的ip处执行。
call word ptr 内存单元地址:把本指令(指call word ptr 内存单元地址)下一条指令的ip压入sp,然后转到内存单元地址所指的ip处执行。
call dword ptr 内存单元地址:把本指令(指call dword ptr 内存单元地址)下一条指令的cs、ip先后压入sp,然后转到内存单元地址所指的cs、ip处执行,其中内存低地址处的值做为IP的值,高地址处的值作为CS。
13、call和ret指令合用实现子程序调用
call s;调用子程序s
s:
ret ;返回到call s后面的指令继续执行
14、子程序调用中的参数及返回值
当参数或者返回值只有1个或者2个时,可以把参数及返回值放到寄存器当中,但是当参数及返回值有N个时,则把批量数据放到内存中,然后把它们所在内存空间的首地址放在寄存器中
,然后传递给需要的子程序或者主程序。当然也可以用堆栈来传递参数及结果。
15、mul指令
mul bl,mul byte ptr ds:[0],表示进行的是8位乘法,其中乘数放在al中,被乘数放在bl或者内存单元中,结果放在ax中
mul bx,mul word ptr ss:[0],表示进行的是16位乘法,其中乘数放在ax中,被乘数放在bx或者内存单元中,结果存放方式为:
高位放在dx中,低位放在ax中,其值为dx×16+ax
16、伪指令
a、db 1 该数据在内存中表示为01H
dw 1 该数据在内存中表示为0001H
dd 1 该数据在内存中表示为00000001H
b、dup
db 3 dup ('abc','ABC'),表示定义了一段内存:abcABCabcABCabcABC,共18个字节
dd 2 dup (1),表示定义了一段内存,0000000100000001H,共32个字节
dd 重复的次数 dup (重复的双字型数据),db,dw可以类推
c、offset
offset start,取得start这个标号处的偏移地址。
d、assume
assume cs:code,用assume定义一个代码段,其中代码段名字叫code
六、as86格式下的各种命令
1、entry start在as86中表示汇编程序在start标号指定的地方开始执行,entry d在as86中表示汇编程序在d标号指定的地方开始执行
entry d
d: mov ax,#0x18
七、其它问题
1、在汇编中不用判别字母对应ASCII码的大小就可以转变大小写的方法
a)、大写变成小写
or al,00100000b,将al中的字母变成了小写
and al,11011111b,将al中的字母变成了大写 2、彩色字符模式缓冲区相关内容 a)、原理 内存空间中,B8000H~BFFFFH共32KB(byte,用十进制表示)的空间是80×25彩色字符模式缓冲区,向该内存空间写入数据会立即显示在显示器上。 (32KB的计算方式:FFFFH-8000H+1=8000H,8000H=32768D,32768/1024=32,即B8000H~BFFFFH表示32K个内存单元,由于8086模式汇编的内存单元是 字节,因此该缓冲区就表示32KB) 该模式下一屏显示80×25=2000个字符,由于1个字符要表示ASCII码和颜色等属性,分别用1个字节表示,则1个字符需要2个字节,故一屏则需要4000字节, 因此该缓冲区能显示8屏32000个字节即32K字节。显示器可以显示任意一页的内容,一般情况下显示第0页的内容。 具体情况见彩色字符模式缓冲区表格
b)、
2、彩色字符模式缓冲区属性字节格式:7 6 5 4 3 2 1 0
含义:BL R G B I R G B
闪烁 背 景 高亮 前 景
比如要配置绿色则是:00000010B=02H,绿底红色:00100100B=24H,白底蓝色:闪烁绿色:10000010B=82h
3、子程序的编写
子程序开始:子程序中使用的寄存器入栈;保护主程序的寄存器内容用
子程序内容
子程序中使用的寄存器出栈
返回(ret、retf)
王爽asm.pdf看到204页