本文为汇编语言考试复习整理 →_→

寄存器

通用寄存器(General Purpose Registers)均可以拆成2个8位寄存器使用,如AX寄存器可以拆成AL(低位)、AH(高位)使用

Types Registers Full Name Function
General Purpose Registers AX Accumulator Register 存储数据;乘除法;中断指令;不能用作偏移地址索引
BX Base Register 偏移地址索引(默认段地址为DS)
CX Counter Register 循环计数;不能用作偏移地址索引
DX Data Register 存储数据;乘除法;不能用作偏移地址索引
Segment Registers CS Code Segment 代码段的段地址
DS Data Segment 数据段的段地址
SS Stack Segment 栈段的段地址
ES Extra Segment 额外段的段地址
Special Purpose Registers SP Stack Pointer 栈段的偏移地址;不能用作偏移地址索引
BP Base Pointer 偏移地址索引(默认段地址为SS)
IP Instruction Pointer 代码段的偏移地址
SI Source Index 串传送指令源地址;源偏移地址索引
DI Destination Index 串传送指令目的地址;目的偏移地址索引
Flag Register PSW Program Status Word 存储相关指令的执行结果

更多内容可参考 :point_right: https://www.geeksforgeeks.org/types-of-registers-in-8086-microprocessor/

标志寄存器

flag-register.png
Flag Register
PSW Full Name 1
ZF Zero Flag 计算结果为0
PF Parity Flag 计算结果二进制有偶数个1
SF Sign Flag 计算结果为负
CF Carry Flag 当作无符号数计算,结果存在进位溢出
OF Overflow Flag 当作有符号数计算,结果存在溢出
AF Auxiliary Carry Flag 计算过程是否存在进位
DF Directional Flag 串传送方向从高到低
IF Interrupt Flag 接受中断
TF Trap Flag 单步执行

更多内容可参考 :point_right: https://www.geeksforgeeks.org/flag-register-8086-microprocessor/

寻址

16位的寄存器,20位的地址总线。CPU 向地址总线发送物理地址前需先计算出来,计算方式如下:

物理地址(20位) = 段地址 x 10H + 偏移地址

所以,可能存在不同段地址和偏移地址指向一个物理地址的情况。

内存单元

在 DEBUG.EXE 中,内存单元按照低地址到高地址的方式显示,每两个紧邻的数表示一个字节(Byte),每行显示16个字节。

memory-in-debug.png
DEBUG.EXE中的内存单元显示

上图中,如果DS寄存器(Data Segment)为076C,则指令 mov ax,[0] 将使AX寄存器被赋值为十六进制的C88C。(C8在高地址,所以在高位;8C在低地址,所以在低位)

此外,内存单元存储地址时,段地址存储于高地址,偏移地址存储于低地址。

指令语法

1. mov ax,0f500h

解释:将十六进制的f500(最后的 h 表示十六进制;数值的第一位是字母 f 所以需要加上 0 )赋值给AX寄存器

段寄存器(CS、DS、SS、ES)不能直接赋值数据,需要通过寄存器(段寄存器和IP除外)赋值

内存单元可以通过寄存器或者数据赋值,不能使用 mov 内存单元地址,内存单元地址 赋值,下面两种均是可以的。

mov ds:[0],ax              ; ax已经指明是word类型,无需加上word ptr
mov word ptr ds:[0],33h   ; 需要指定word ptr或者byte ptr

2. add ax,2

解释:将十进制的2加给AX寄存器,也可以对内存单元使用,如 add word ptr es:[0],33h ;相关的指令有 sub ax,2 ,使AX寄存器减去十进制的2

3. inc ax

解释:AX寄存器加1,也可以对内存单元使用,如 inc word ptr es:[0] ;相关的指令有 dec ax ,使AX寄存器减1

4. push ax

解释:将AX寄存器(或者内存单元)的值入栈

栈顶为SS:SP,满足先入后出原则,入栈SP变小,出栈SP变大;使用时需要先声明栈段(stack segment),栈段完全由程序员控制,没有保护机制。此外, pushpop 时,SP只能加2或者减2。

指令 解释
push ax 1. sub sp,2
2. mov ss:[sp],ax
pop ax 1. mov ax,ss:[sp]
2. add sp,2

5. loop s

解释:同一个代码段(段内短转移)往前跳转到s标记处循环

  1. CX减1,并判断是否为0
  2. 如果CX为0,则不跳转继续往下执行代码;如果CX大于0,则跳转到s标记循环

6. and al,11011111b

解释:将AL值的二进制与 11011111b 做与运算,功能上将AL转为大写字符

and 0 1
0 0 0
1 0 1

相关的指令有 or al,00100000b ,它是将AL值的二进制与 00100000b 做或运算,功能上将AL转为小写字符

or 0 1
0 0 1
1 1 1

7. db 'unIX'

解释:在内存中定义字节型(byte)数据,等效于 db 75H,6EH,49H,58H75H,6EH,49H,58HunIX 的16进制ASCII码

相类似的还有dw(define word)、dd(define double word),均是编译器识别的伪指令

8. div bx

解释:BX为除数,被除数为AX(低位)和DX(高位)构成的数,商存放于AX中,余数存放于DX中

除数 被除数 余数
8位 AX AL AH
16位 AX(低位)、DX(高位) AX DX

相关的指令有 mul bx ,这里BX为乘数,被乘数为AX,积为AX(低位)和DX(高位)构成的数

乘数 被乘数
8位 AL AX
16位 AX AX(低位)、DX(高位)
; 应用举例
div reg                         ; 8位或者16位reg
div 内存单元地址                 ; 需要加上 byte ptr / word ptr

div word ptr es:[0]
div byte ptr [bx + si + 8]  ; ds:[bx + si + 8]

mul reg                        ; 8位或者16位reg
mul 内存单元地址                ; 需要加上 byte ptr / word ptr

mul word ptr es:[0]
mul byte ptr [bx + si + 8]  ; ds:[bx + si + 8]

9. db 200 dup (0)

解释:定义200个字节的 0dup (duplication)同样也是编译器识别的伪指令

10. mov si,offset s

解释:操作符 offset 由编译器识别,值为标记 s 处相对代码起始位置的偏移量,通常用于串传送

11. jmp short s

解释:CS和IP由于其特殊性,不能直接通过赋值改变,jmp指令登场! jmp short s 跳转到标号s处执行代码,是段内短转移,转移范围为 -128~127 (段内转移只改变IP)

指令 解释 类别
jmp short s 跳转到标号s处 段内短转移( -128~127
jmp near ptr s 跳转到标号s处 段内近转移( -32768~32767
jmp ax 将AX的值赋给IP 段内近转移( -32768~32767
jmp far ptr s 跳转到标号s处 段间远转移(改变CS和IP)
jmp word ptr 内存单元地址 内存单元的值赋给IP 段内近转移( -32768~32767
jmp dword ptr 内存单元地址 内存单元低地址赋给IP,高地址赋给CS 段间远转移(改变CS和IP)

12. jcxz s

解释:当CX为0时,跳转到标号s处,否则往下执行;属于有条件转移指令,短转移,对IP的修改范围为 -128~127

13. call s

解释:将call下一条指令1的地址压入栈中,然后跳转到标号s处

搭档 解释 指令 解释
ret 1. pop ip call s 1. push ip
2. jmp near ptr s
call 16位reg 1. push ip
2. jmp 16位reg
call word ptr 内存单元地址 1. push ip
2. jmp word ptr 内存单元地址
retf 1. pop ip
2. pop cs
call far ptr s 1. push cs
2. push ip
3. jmp far ptr s
call dword ptr 内存单元地址 1. push cs
2. push ip
3. jmp dword ptr 内存单元地址

14. adc ax,bx

解释:带进位加法,前面指令对标志寄存器中CF的影响会加到这里,等效于 (ax)+(bx)+CF

相关的指令还有 sbb ax,bx ,带进位减法

add al,bl
adc ah,bh
; 等效于 add ax,bx

sub al,bl
sbb ah,bh
; 等效于 sub ax,bx

15. cmp ax,bx

解释:用AX减BX,但不保存结果,只影响标志寄存器,一般和je等条件转移搭配使用

无符号条件转移有:je、jne、jb、jnb、ja、jna;有符号条件转移有:jg、jng、jl、jnl;更多内容可参考:http://marin.jb.free.fr/jumps/

; 应用示例
cmp bl,11
jb s
inc ax
s: inc si
loop k
...

16. pushf

解释:标志寄存器压栈

相关指令 popf 从栈中取值赋给标志寄存器

17. rep movsb

解释:串传送指令, movsb 是按照byte传送; movsw 是按照word传送

指令 解释
movsb 1. ((es)*16+(di))=((ds)*16+(si))
2. 如果df=0( cld ),则 inc siinc di ;如果df=1( std ),则 dec sidec di
rep movsb s:movsb
loop s
(重复次数由CX决定)

串传送步骤

  1. 设置DS:SI和ES:DI
  2. 设置传送方向,cld(低到高)、std(高到低)
  3. 设置传送长度CX
  4. rep movsb 或者 rep movsw

18. int 21h

解释:21h号中断,对应中断向量表 0:21h*4 位置(这里存储了21h中断例程的段地址 0:21h*4+2 和偏移地址 0:21h*4 ),再执行中断例程,一般中断程序中会有 iret 返回

指令 解释
int 21h 1. 取得中断类型码N(如21h)
2. pushf
3. TF=0,IF=0
4. push cs , push ip
5. (IP)=(4\*N),(CS)=(4\*N+2)
iret 1. pop ip
2. pop cs
3. popf

报错指南

  1. [idata] 单独表示编译器会报错,可以使用 ds:[idata] ,或者先 mov bx,idata 再用 [bx] 表示( idata 即普通数据,如33H)
  2. 不能对两个内存单元地址直接操作,如 mov 内存单元地址,内存单元地址
  3. 包含多段(code segment、data segment、stack segment等)的程序必需加入代码开始标号,最后 end 标号 ,否则编译器默认第一段开始为代码段
  4. 地址如果用16进制表示,结尾需要加上H
  5. 内存单元与数据的操作( movaddand 等),需要指明 word ptr 或者 byte ptr

  1. CPU执行指令的步骤是:1. 从CS:IP指向的内存单元读取指令进入指令缓冲器;2. IP指向下一条指令;3. 执行缓冲器中的指令 

Leave a comment