8086汇编语言学习笔记

默认分类 · 2009-02-04

一、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页

汇编
Theme Jasmine by Kent Liao