汇编语言程序设计复习大纲

一.基础知识点

  • 数制转换
  • 汇编指令、机器指令的区别,伪指令作用
  • 地址总线、数据总线、控制总线基本概念
  • 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指的是只读存储器,电脑上可称作硬盘,断电之后数据仍旧保存

常用寄存器:

  1. 通用寄存器
  • 数据寄存器,AX(AH、AL)、BX(BH、BL)、CX(CH、CL)、DX(DH、DL)
  • 变址寄存器,SI(源地址)、DI(目的地址)
  • 指针寄存器,SP(堆栈指针)、BP(基址指针)
  1. 特殊寄存器
  • 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 指令指针
  1. 段寄存器
  • 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这两个单元

中断处理流程:

  1. 取得中断码类型N
  2. pushf,将标志寄存器中的值存入栈中,因为之后的中断处理会用到标志寄存器
  3. TF=0,IF=0,将第八位TF和第九位IF值0
  4. push CS
  5. push IP 
  6. IP=(N*4) CS=(N*4)+2
  7. 完成最后一步后,CPU开始执行程序员编写的中断程

中断处理程序的编写:

  1. 保存用过的寄存器
  2. 中断处理
  3. 恢复用过的寄存器
  4. 用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指令允许的传送石:
  1. 寄存器到寄存器
  2. 立即数到寄存器
  3. 立即数到存储单元
  4. 寄存器到存储单元
  5. 存储单元到寄存器
  6. 从寄存器或者存储单元到除了CS以外的段寄存器
  7. 从段寄存器到寄存器或者存储单元

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位时:
  1. 一个数放在al中,结果放在ax中。比如,mul byte ptr ds:0,结果是ax=al*(ds*16+0)
  2. 当两个数都是16位时:
  3. 一个数放在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调试过程:

  1. 编写源代码XXX.asm文件
  2. 在debug中键入masmXXX.asm
  3. 生成XXX.obj文件
  4. 在debug中键入linkXXX.obj
  5. 生成XXX.exe可执行文件
  6. 在debug中键入XXX.exe
  7. 用U命令和T命令调试