汇编语言程序设计复习大纲
一.基础知识点
- 数制转换
- 汇编指令、机器指令的区别,伪指令作用
- 地址总线、数据总线、控制总线基本概念
- CPU字长、寻址能力、存储空间
- RAM、ROM各自特点
- 常用寄存器(AX、BX、CX、DS、SS、SP、SI、DI、AL、AH...)
- 段的概念,段地址,偏移地址
- 8086CPU物理地址构成及获取
- 内存访问[bx],[bx+idata],[bx+si],[bx+si+idata]
- 内存中数据存放格式
- 栈的概念、操作方式
- 汇编语言程序设计基础流程:编写、编译、连接、执行
- Word ptr 、byte ptr用法
- 常用标志位含义
- 中断处理流程
二、指令系统(常用指令写法,分析运行结果)
- 常用伪指令:segment,ends,assume,end,db,dw,dup
- mov用法
- jmp指令
- add,adc,inc,sub,div,mul指令
- push,pop指令
- loop指令
- and,or指令
- jcxz,cmp指令
- call,ret指令
三,简单程序设计
- 连续区域数据转移
- 大小写转换
- 区分代码段、数据段、堆栈段的简单程序设计
四、调试
- 调试工具
- 常用调试命令
数制转换
- 数码 ,数码指的是某一个进制里面所拥有的具体数值,例如八进制的数码是:0,1,2,3,4,5,6,7;
- 基数,基数指的是某一个进制数码的个数,例如十六进制的基数是16;
- 位权,位权指的是某一个进制里面各个数字所在位置的大小(其数字的价值),例如十六进制的1101,第一个1的位权是8,第二个0的位权是4,第三个1的位权是2,第四个1的位权是1;
- 计数规则,计数规则指的是某个进制本身的运算所要遵守的规则,例如二进制的规则是逢二进一,16进制的规则是逢十六进一;
二进制,八进制,十六进制与十进制的转换:
二进制转换为十进制,就是求二进制的各个位置的位权之和。例如1011(B)就是8+0+2+1=11(N);
八进制转换为十进制,就是求八进制的各个位置的位权之和。例如476(O)就是4*8^2+7*8^1+6*8^0=318(N);
十六进制转换为十进制,就是求十六进制各个位置的位权之和。例如AF17(H)就是11*16^3+16*16^2+1*16^1+7*16^0=44823(N);
十进制与二进制,八进制,十六进制的转换:
十进制与其他进制的转换分为整数部分和小数部分。
- 整数部分:用十进制数除以某一进制的基数,取余数为结果的最低位,得出的商继续除以某一进制的基数,去余数为结果的次地位。直到最后的商为零,得出的余数为结果的最高位。
- 小数部分:用十进制小数部分乘以某一进制的基数,得出来的整数为最高位,得出的积继续乘以某一进制的基数,直到小数部分为零。
- 例如十进制转换为二进制,23.11(N)整数部分就是23/2=11....1,这里的1作为结果最低位;11/2=5.....1,这里的1作为结果次地位;5/2=2......1,这里的1作为次次地位;2/2=1.....0,这里的0作为次次次地位;1/2=0.....1,这里的商为0,不用继续除了。整数部分结果为10111(B);小数部分就是0.11*2=0.22;0.22*2=0.44;0.44*2=0.88;0.88*2=1.76,这里的1作为结果的最高位;0.76*2=1.53,这里的1作为次高位;0.52*2=1.04,这里的1作为次次高位,答案非常长,不一一举例。小数部分结果为0.00011100001010001111010111000010100011110101110000101001(B) 总的结果为10111.00011100001010001111010111000010100011110101110000101001(B)
二进制与八进制和十六进制之间的转换:
二进制与八进制和十六进制之间的转换满足(23)(24)原则。
- 二进制转换为八进制,只需要将二进制数三位三位划分,最高位不足的补0.得出来的数就是八进制数。例如10111001(B)就是10/111/001x先进行三位三位划分,第一位缺一位,所以要补0,得010/111/001,结果是2/7/1也就是271(O)。
- 二进制转换为16进制,只需要将二进制数四位四位划分,最高位不足时补0,得出来的数就是16进制数。例如10111001(B)就是1011/1001先进行四位四位划分,结果就是11/9,也就是B9(H)
八进制和十六进制与二进制之间的转换:
八进制和十六进制与二进制之间的转换满足(23)(24)原则。
- 八进制转换为二进制,只需要将八进制数每一位转换为三位的二进制数,然后再串联起来就可以了。例如:36(O)就是3/6=>011/110,也就是011110;
- 16进制转换为二进制,只需要将十六进制每一位转换为四位的二进制数,然后再串联起来就可以了。例如BE4(H)就是B/E/4=>11/14/4=>1011/11110/0100,也就是101111010100(B)
汇编指令,机器指令,伪指令的区别:
- 机器指令指的是机器能够直接识别的二进制代码
- 汇编指令指的是一段有意义的二进制代码,比机器指令容易看,有助记符
- 伪指令指的是一段封装起来的汇编指令
地址总线、数据总线、控制总线:
- 地址总线指的是计算机内部连接的地址线
- 数据总线指的是计算机内部连接的数据线
- 控制总线指的是计算机内部连接的控制线
CPU字长、寻址能力、存储空间:
- CPU字长指的是CPU在单位时间内一次能够处理的二进制位数,例如32位CPU,一次处理能够处理32位二进制数,字长为32位。
- 寻址能力一般与地址总线有关,地址总线有n条,则有2^n个地址,寻址能力就是2^n。
- 存储空间就是物理地址的集合,也就是存储容量大小,例如256G内容。
RAM、ROM各自特点:
- RAM指是可擦写的存储体,电脑上可称作运行内存,断电之后数据不会保存
- ROM指的是只读存储器,电脑上可称作硬盘,断电之后数据仍旧保存
常用寄存器:
- 通用寄存器
- 数据寄存器,AX(AH、AL)、BX(BH、BL)、CX(CH、CL)、DX(DH、DL)
- 变址寄存器,SI(源地址)、DI(目的地址)
- 指针寄存器,SP(堆栈指针)、BP(基址指针)
- 特殊寄存器
- FLAG 标志寄存器
- ZF(判断是否为零,运行结果为0时ZF为1)
- CF (进位时最高位的进位值大小)
- SF (运行结果的符号,符号为负数时置1)
- OF (溢出标识符,当溢出时置1)
- AF (辅助进位符号,运算时第三位的进位值)
- PF (为机器可能出错时做的检验符号,当结果的中的1为偶数个时,PF置1)
- DF (在串指令中控制方向,当DF置1时,按高到低方向,当对方置0时,按低到高方向)
- TF (陷阱标志,当TF置1时,每一步运算之后都产生陷阱,由计算机系统控制。当TF置0时,不产生陷阱,由CPU控制)
- IF (用于控制可屏蔽信号装置,当IF置1时,响应8086CPU的中断请求)
- IP 指令指针
- 段寄存器
- CS 代码段寄存器
- SS 堆栈段寄存器
- DS 数据段寄存器
- ES 附加段寄存器
段的概念,段地址,偏移地址:
- 段地址指的是在存储器中被划分为许多段的段首地址。例如有20根地址线,寻址能力为1MB的地址分为十段,则第一段为0-1024KB,段地址为0000H,偏移地址为0-1024kb(偏移量),例如:
- 段地址0088H加上偏移量22H。就是将段地址左移四位,再与偏移地址相加。就是00880H+22H=008A2H(H)。
- 在8086CPU中,有20个地址线,所以直接寻址能力是1MB,但是通用寄存器基本都是16位,所以要算出20位的物理地址,就需要将16位的段地址加上偏移地址得出20位的物理地址。
8086CPU物理地址构成及获取:
- 8086CPU外部有20条地址总线,寻址能力为1MB,8086CPU内部芯片是16位地址线,寻址能力是64KB,所以8086CPU内部用两个十六位相加得出20位物理地址。8086CPU内部物理地址的获取方式是(段地址*16+偏移地址=物理地址),这里的乘以16也就是段地址左移四位。
- 内存本来没有划分段,但是8086CPU特殊的物理地址获取方式,使得可以通过分段地址加偏移地址来使用。
内存访问[bx],[bx+idata],[bx+si],[bx+si+idata],[bp],[bp+idata],[bp+si],[bp+di],[bp+si+idata]:
- 在内存当中,可以在【....】中进行内存寻址的,只有这四种寄存器:【bx】,[bp]、[si]、[di];
- l例如 mov ax,[bx],
- mov ax,[bp],
- mov ax,[si],
- mov ax,[di],
- 如果是组合,则只可以存在这种形式:[bx+si],[bx+di],{bp+si],[bp+di]
- 例如 mov ax,[bx+si],
- mov ax,[bx+di],
- mov ax,[bp+si],
- mov ax,[bp+di].
- 如果加上数据,则只可以存在这种形式:[bx+idata],[bx+si+idata],{bx+di+idata],[bp+idata],[bp+si+idata],[bp+di+idata]
- 在使用bp时如果没有指定段地址,则默认在ss中,例如:
- mov ax ,[bp],就是ax=(ss*16)+bp)
- mov ax,[bp+idata],就是ax=((ss*16)+bp+idata)
内存中数据存放格式:
- 内存中数据的存放是从低地址到高地址存放的。例如存放1678H。则是低地址先存放低八位的78,再到高地址存放高八位的16.所以是 78(低八位) 低地址
- 16(高八位) 高地址
栈的概念、操作方式:
- 栈是一段特殊的内存空间,它的规则是先进后出,后进先出。
- 一般来说,SS:SP始终指向栈顶,8086CPU提供了处理栈的指令,push和pop,但是不会管栈的大小,可能会有溢出越界。
- push操作:
- 先将SP=SP-2;将栈顶指向第两个单元的位置
- 再将寄存器中的数据存入新的SS:SP位置中
- pop操作:
- 先将SS:SP中的数据取出
- 再将SP=SP+2,将栈指针指向新的栈顶
- push和pop指令也可以对寄存器和内存空间进行操作。例如:
- push [ax],pop[ax]
- push [0],pop[2]
- push和pop只进行字操作
汇编语言程序设计基础流程:编写、编译、连接、执行:
- 基础语法:
assune CS :XXX XXX segment mov ax,2 add ax,ax segment ends end
使用ASAM编译,使用link.exe连接,执行
Word ptr 、byte ptr用法:
- word ptr和byte ptr指的是在内存中指明是对字操作还是对字节操作。
- 如果有寄存器,则不需要word ptr和byte ptr指明,例如:
- mov ax ,2是对字进行操作 mov al,2是对字节进行操作
- 如果没有寄存器,则需要ptr指明,因为8086CPU可以处理字和字节两个数据,指明为word ptr时,操作的是两个单元,指明为byte ptr时,操作的是一个单元。例如:
- mov word ptr[20],2,就是操作两个单元,即SS*16+20和SS*16+20+1这两个单元
中断处理流程:
- 取得中断码类型N
- pushf,将标志寄存器中的值存入栈中,因为之后的中断处理会用到标志寄存器
- TF=0,IF=0,将第八位TF和第九位IF值0
- push CS
- push IP
- IP=(N*4) CS=(N*4)+2
- 完成最后一步后,CPU开始执行程序员编写的中断程
中断处理程序的编写:
- 保存用过的寄存器
- 中断处理
- 恢复用过的寄存器
- 用iret指令返回
常用伪指令:segment,ends,assume,end,db,dw,dup:
- segment用于声明一个段名,例如 segment CS:XXX
- ends用于表示segment定义的段结束,end表示程序结束
- assume表示告诉机器哪一个段和哪一个段寄存器相对应
- db可以用来定义,不过db表示一个字节,dw表示一个字,有两个字节。表示的范围也不同,db的范围是0-255,dw的范围是0-65535,dd表示四个字节。
- dup表示重复定义。例如db 8 dup(2).表示定义8个2,相当于db 2,2,2,2,2,2,2,2
mov用法:
- mov指令可以用来传送数据,而且可以不破坏源数据。
- mov指令不会影响标志位
- mov指令的操作数不可以是立即数和段寄存器。不允许存储单元到存储单元之间的传送,也不允许段寄存器到段寄存器之间的传送,也不允许目的地址是存储单元,不允许立即数到段寄存器
- mov指令允许的传送石:
- 寄存器到寄存器
- 立即数到寄存器
- 立即数到存储单元
- 寄存器到存储单元
- 存储单元到寄存器
- 从寄存器或者存储单元到除了CS以外的段寄存器
- 从段寄存器到寄存器或者存储单元
jmp指令:
- jmp指令指的是无条件的进行转移
- jmp +16位寄存器,例如jmp ax .,用ax的值作为跳转值,跳转到ax中
- jmp short sign ,例如:jmp short s,段内短转移,跳转到s中,位移量不超过128位。
- jmp near ptr sign,例如:jmp near ptr s,段内近转移,跳转到s中,位移量可以很大,32767位
- jmp far ptr sign,例如:jmp far ptr s,段间转移,跳转到其他段中
- jmp +段地址:偏移地址,例如:jmp 2000H:20H,跳转到2000H段偏移量为20H的地方去
add,adc,inc,sub,div,mul指令:
- add指令是加法,例如 add ax,[20H]
- adc指令是带进位的加法指令,要加上符号标志位的CF的进位,例如adc ax,1.表示ax=ax+1+CF
- sub指令是带借位的减法指令,要加上符号标志位的CF的借位,例如sub ax,1表示ax=ax-1-CF
- mul指令是乘法指令,在两个数都是8位时:
- 一个数放在al中,结果放在ax中。比如,mul byte ptr ds:0,结果是ax=al*(ds*16+0)
- 当两个数都是16位时:
- 一个数放在ax中,结果低八位放在ax中,高八位放在dx中。比如,mul word ptr ds:0,结果是低八位ax=ax*(ds*16+0),高八位dx=ax*(ds*16+0)
- div指令是除数指令,在除数为8位时,被除数是16位,此时:
- 除数放在寄存器或者存储单元中,被除数放在ax中,结果商放在al中,余数放在ah中。比如,10001/100,10001需要两个寄存器,所以被除数是32位,所以除数要用16位。
- 在除数为16位时,被除数是32位,被除数低八位存放在ax中,高八位存放在dx中,结果的商存放在ax中,余数存放在dx中
- inc,加1指令
- dec,减1指令
push,pop指令:
- push指令格式:
- SP=SP-2
- 从寄存器或者存储单元传送数据到新的SS:SP中
- pop指令格式:
- 从SS:SP中将数据取出
- SP=SP+2
loop指令:
- 循环指令,用一串代码来说明:
assume CS :code
code segment
mov ax,2
mov cx,10//循环次数
s:add ax,ax
loop s
mov ax,4c00H//这两段是用来返回原值,没什么关系
int 21h//
code ends
end
and,or指令:
- and指令,两者都是1时取1,不同的取0。例如:al:10011011H
- ah:01101101H
- 结果是: 00001001H
- or指令,当有一个为1时则取1.例如:al:10011011H
- ah:01101101H
- 结果是:11111111H
jcxz,cmp指令:
- jcxz的全程是jmp if cx equals zero ,当(cx==0)时,就跳转到标号sign那里。
- cmp相当于减法指令,例如:cmp 32,23就是32-23.但是不保存结果,只是影响标志符,让其他受标志符影响的指令执行
call,ret指令:
- call指令,条用其他程序,ret指令返回程序,call和ret两者结合可以实现模块化程序设计。
- call相当于:push IP
- jmp
- ret相当于:pop IP
简单程序设计
连续区域数据转移:
大小写转换:
assume cs:codesg,ds:datasg
datasg segment
db 'BaSiC'
db 'iNfOrMaTiOn'
datasg ends
codesg segment
start: mov ax,datasg
mov ds,ax
mov bx,0
mov cx=5
s: mov al,[bx]
and al,11011111B
mov [bx],al
inc bx
loop s
mov bx,5
mov cx=11
s0: mov al,[bx]
or al,001000000B
mov [bx],al
inc bx
loop s0
mov ax,4c00H
int 21H
codesg ends
end start
区分代码段、数据段、堆栈段的简单程序设计:
常用调试命令:
- d(dump),显示内存单元的命令。格式为:-d -d[地址] -d[范围]
- e(enter)修改内存字节。格式为:-e [地址] [内容表] ,例如- e ds:100 20abc 又或者e 100,然后直接修改
- r(register)显示和修改寄存器。格式为 -r,可以显示寄存器 又或者-r + 寄存器名 ,可以修改寄存器内容
- rf显示和修改标志位状态。格式为-rf 后面就可以修改寄存器状态了
- g(go)运行命令。格式为:-g
- t(trace)跟踪命令。格式为-t[地址】,单条命令 。又或者-t[地址][值] ,多条命令
- a(assemble)逐行汇编。格式为-a[地址]
- u(unassemble)反汇编。格式为-u[地址]
- n(name)命名命令。格式为-n[文件标识符][文件标识符]
- l(load)读盘。格式是-L 地址 驱动器 扇区号 扇区数 又或者-L 地址
- w(write)读盘。格式是-w 地址 驱动器 扇区号 扇区数
- q(quite)退出。格式为-q
DEBUG调试过程:
- 编写源代码XXX.asm文件
- 在debug中键入masmXXX.asm
- 生成XXX.obj文件
- 在debug中键入linkXXX.obj
- 生成XXX.exe可执行文件
- 在debug中键入XXX.exe
- 用U命令和T命令调试