汇编语言

原创
2019/05/28 17:57
阅读数 182

通用寄存器

8086 CPU的所有寄存器都是16位的,可以存放2个字节。

AX、BX、CX、DX这4个寄存器通常用来存放一般性的数据,被称为通用寄存器 16位寄存器的逻辑结构

处于对兼容性的考虑,8086 CPU可以一次性处理一下两者尺寸的数据

  • 字节:记为byte,一个字节由8个bit组成,可以存储在8位寄存器中。
  • 字:记为word,一个字由两个字节组成,这两个字节分别称为这个字的高位字节和低位字节。

段寄存器

CS和IP

CS是代码段寄存器,IP是指令指针寄存器。CS:IP只想的内容当做指令执行

jmp指令可以修改CS IP的值,格式为 "jmp 短地址:偏移地址"

如: jmp 2AE3:3,执行后:CS=2AE3H,IP=0003H,CPU将从2AE33H出读取指令。

如果仅修改IP的内容,可以用"jmp 某一合法寄存器"的指令完成,其功能为:用寄存器中的值修改IP

如:

jmp ax,指令执行前:ax=1000H,CS=2000H,IP=0003H

指令执行后:ax=1000H,CS=2000H,IP=1000H

jmp bx,指令执行前:bx=0B16H,CS=2000H,IP=0003H

指令执行后:ax=0B16H,CS=2000H,IP=0B16H

DS和[address]

mov bx, 1000H // 把1000H放到寄存器bx中
mov ds, bx // 把bx的值放到ds中,也就是1000H
mov al, [0] // [...]表示一个内存单元,中括号中的值表示偏移地址,那么基地址(段地址)在哪里呢,8086 CPU会自动取ds中数据作为内存单元的段地址
// 所以这段汇编指令最终就是将 1000:0 中数据读入al中,为什么不直接把1000H放入ds呢?8086 CPU不支持 mov ds,1000H,所以需要一个寄存器中转

mov、add、sub指令

mov指令有一些集中形式
mov 寄存器, 数据         // mov ax, 8
mov 寄存器, 寄存器      // mov ax, bx
mov 寄存器, 内存单元  // mov ax, [0]
mov 内存单元, 寄存器  // mov [0], ax
mov 段寄存器, 寄存器  // mov ds, ax
mov 寄存器, 段寄存器  // mov ax, ds
mov 内存单元, 段寄存器
mov 段寄存器, 内存单元
add指令有一些集中形式
add 寄存器, 数据         // add ax, 8
add 寄存器, 寄存器      // add ax, bx
add 寄存器, 内存单元  // add ax, [0]
add 内存单元, 寄存器  // add [0], ax
sub指令有一些集中形式
sub 寄存器, 数据         // sub ax, 8
sub 寄存器, 寄存器      // sub ax, bx
sub 寄存器, 内存单元  // sub ax, [0]
sub 内存单元, 寄存器  // sub [0], ax

8086 CUP提供入栈和出栈指令,最基本的两个第PUSH和POP,如push ax表示将寄存器ax中的数据送入栈中,pop ax表示从栈顶取出数据送入ax中,8086CUP的入栈和出栈操作都是以字为单位进行的。栈顶的段地址存放在SS中,偏移地址存放在SP中,任意时刻,SS:SP 指向栈顶元素 ,push指令和pop指令执行时,CUP从SS和SP中得到栈顶地址。 push指令的执行过程 pop指令执行过程

注意栈超界问题,8086CPU不会检查栈边界,push和pop都可能超界,需要编程人员自己注意不要超界

push和pop的一些格式
push 寄存器      // 将一个寄存器中的数据入栈
pop 寄存器       // 将栈顶元素放入寄存器中
push 段寄存器
pop 段寄存器
push 内存单元  // 将一个内存字单元出的字入栈(注意:栈操作都是以字为单位)
pop 内存单元

描述性的符号 "()"

使用描述性符号"( )"表示一个寄存器或内存单元中的内容

如:(ax)表示ax中的内容,(20000H)表示内存20000H单元的内容。

((ds)16+(bx))表示 ds中的内容16+bx中的内容。

"( )"中的元素可以有3中类型:1、寄存器名 2、段寄存器名 3、内存单元的物理地址(一个20位数据)

约定符号 idata 表示常量

idata表示常量

[bx]

mov ax, [bx]
功能:bx中存放的数据作为一个偏移地址EA,段地址SA默认在ds中,
将SA:EA处的数据送入ax中,即:(ax)=((ds)*16+(bx))

Loop指令

loop指令的格式是:loop 标号,CUP执行loop指令的时候,要进行两步操作,1、(cx)=(cx)-1; 2、判断cx中的值,不为0则专指标号处执行程序,如果为0则向下执行。cx中通常存放循环次数

例:计算2^12
assume cs:code
code segment
	mov ax, 2
	mov cx, 11  // 循环次数,除了第一次执行外,还要循环11次,共12次
s: add ax, ax  // 标号
	loop s        // loop
	mov ax, 4c00h
	int 21h
code ends
end

CPU在执行 loop s的时候,要进行两步操作:
1、(cx)=(cx)-1
2、判断 cx 中的值,不为 0 则专指标号s锁标识的地址出执行,如果为0则执行下一条指令

[bx+idata]

[bx+idata] 表示一个内存单元,它的偏移地址为(bx)+idata

mov ax, [bx+200]
表示将一个内存单元的内容送入ax,这个内存单元的的长度为2个字节(字单元),存放一个字,偏移地址为bx中的数值加上200,段地址在ds中。
数学化描述为:(ax)=((ds)*16+(bx)+200)

SI和DI

si和di是8086cpu中和bx功能相近的寄存器,si和di不能够分成两个8位寄存器来使用。

[bx+si]和[bx+di]

mov ax, [bx+si]
将一个内存单元的内容送入ax,这个内存单元的长度为2字节(字单元),存放一个字,偏移地址为bx中的数值加上si中的数值,段地址在ds中。
数学化描述为:(ax)=((ds)*16+(bx)+(si))
该指令也可以写成如下格式(常用):
mov ax, [bx][si]

[bx+si+idata]和[bx+di+idata]

mov ax, [bx+si+idata]
将一个内存单元的内容送入ax,这个内存单元的的长度为2字节(字单元),存放一个字,偏移地址为bx中的数值加上si中的数值再加上idata,段地址在ds中。
数学化描述为:(ax)=((ds)*16+(bx)+(si)+idata)
该指令也可以写成如下格式(常用):
mov ax, [bx+200+si]
mov ax, [200+bx+si]
mov ax, 200 [bx] [si]
mov ax, [bx] .200 [si]
mov ax, [bx] [si] .200

不同寻址方式的灵活运用

不同寻址方式的灵活运用

###寻址方式 当数据存放在内存中的时候,我们可以用多种方式来给定这个内存单元的偏移地址,这种定位内存单元的方法一般被称为寻址方式。 寻址方式小结

指令要处理的数据有多长

  1. 通过寄存器名指明要处理的数据的尺寸 寄存器指明
  2. 在没有寄存器名存在的情况下,用操作符 X ptr 指明内存单元的长度,X在汇编指令中可以为word或byte ptr指定
  3. 其他方法 其他方法

div指令

div是处方指令,使用div做除法的时候应注意以下问题。

伪指令dd

db用来定义字节型数据

dw用来定义字型数据

dd用来定义dword(double word,双字)型数据

dup

dup是一个操作符,在汇编语言中同db、dw、dd等一样,也是有编译器识别处理的符号。和db、dw、dd等数据定义伪指令配合使用,用来进行数据的重复

如:db 3 dup (0) 
定义了三个字节,它们的值都是0,相当于 db 0,0,0

db 3 dup (0,1,2)
定义了9个字节,它们是0,1,2,0,1,2,0,1,2,相当于 db 0,1,2,0,1,2,0,1,2
展开阅读全文
JMP
加载中
点击引领话题📣 发布并加入讨论🔥
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部