- 一、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标号指定的地方开始执行
- 7、如果某个地址的段地址是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均可
- 8、除法指令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)的余数
- 9、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
- 10、jcxz指令
- 这是有条件转移指令,所有的有条件转移指令都是短转移,即在段内转移。该指令对IP的修改范围为:-128~127
- jcxz 标号:如果(cs)=0,则转到标号处开始执行,否则顺序向下执行。
- 11、loop指令
- 这是循环指令,所有的循环指令都是短转移,即在段内转移。该指令对IP的修改范围为:-128~127
- loop 标号:(cx)=(cx)-1,如果(cs)!=0,则转到标号处开始执行,否则顺序向下执行。此处转移条件和jcxz正好相反。
- 12、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,该指令实现远转移
- 13、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。
- 14、call和ret指令合用实现子程序调用
- call s;调用子程序s
- .
- .
- .
- s: .
- .
- .
- ret ;返回到call s后面的指令继续执行
- 15、子程序调用中的参数及返回值
- 当参数或者返回值只有1个或者2个时,可以把参数及返回值放到寄存器当中,但是当参数及返回值有N个时,则把批量数据放到内存中,然后把它们所在内存空间的首地址放在寄存器中
- ,然后传递给需要的子程序或者主程序。当然也可以用堆栈来传递参数及结果。
- 16、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
- 17、伪指令
- 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
- e、
- 六、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页