汇编语言

汇编语言

将机器代码抽象成方便人类方便理解的符号

组成:

汇编指令、伪指令、符号

由于 汇编指令和机器指令关系密切,不同的指令集架构对应的汇编指令也有所差别,所以必须在某一种具体的指令集架构下进行学习。


以下的讨论基于x86架构 8086cpu

16位机器字长,20位地址线

由于地址线有20位,机器字长只有16位,所以一次能处理的地址只有16根,为此8086计算实际物理地址的方法是 高16位作为段地址,低16位作为偏移量,通过这种方式来描述物理地址。段地址*16+偏移地址=实际地址
可以简单的描述为 段地址:偏移地址

段 的含义:

一块连续的内存地址称为段,内存本身并没有将内存分段,而是cpu通过设置段地址和偏移地址来寻址,段本身只是一个概念

两点:

  • 由于段为20位地址的高16位,所以段地址必定是16的倍数
  • 由于偏移地址只有16位,所以一个段的最大长度为64kb

寄存器 :

8086cpu有16个寄存器,AX,BX,CX,DX,SI,DI,SP,BP,IP,CS,SS,DS,ES,PWD
寄存器长度为16位

通用寄存器

AX,BX,CX,DX,用于存放一般数据,以AX为例,可以分为高字节AH 和低字节AL
如果用(AL+某个数)超过8位溢出的位会被舍弃,不会进位到AL
add al 255

段寄存器

CS,DS,SS,ES,存放的都是段地址
CS 存放的代码段地址 ,配合IP指令寄存器,CS:IP 就能确定指令的具体位置
8086cpu 刚启动时(复位或通电)CS=FFFFH ,IP=0000H
所以计算机执行的第一条指令的地址就是FFFF0H

当读取一条指令后 ip=ip+指令长度

DS 存放的数据段地址 ,DS :[x] 就能从数据段中找到位置,x是某个寄存器

辅助寄存器

SI和DI
si和di的功能和ax,bx类似,不同的是,他们不能拆分成单独8位寄存器使用

汇编指令:

mov ax 12 将12放到寄存器ax中
mov ah 12 将12放到寄存器ax中的高字节位置
mov ax bx 将bx的内容放到ax中
在debug 中 [10] 是如下解释的
mov ax [10] 将内存地址为 DS:10的字存到ax
mov ax [bx] 将内存地址为 DS:bx的字存到ax
在编译器中,[10]解释为10

add ax bx 等价于 ax=ax+bx 或 ax+=bx
sub ax bx 等价于 ax=ax-bx 或 ax-=bx

栈操作:栈操作是以字长为单位的
任意时刻 ss:sp 指向栈顶元素
push ax sp=sp-2
pop bx sp=sp+2

跳转

jmp 段地址:偏移地址 同时设置cs和ip
jmp 偏移地址 只设置ip

dw abcdH,efghH,abcdH 定义字型数据,开辟内存空间
dw 0,0,0,0,0,0 分配6字节的空间
db 数据 定义字节型数据,和dw类似
db ‘abcdefgxx’
dd 定义双字型数据

为了表达更清晰:使用() 描述存储单元的内容
()中的内容只能是(寄存器名)或者(20位内存地址)
由于(内存地址)可能取的字或字节,具体取决于左值

约定用 idata表示常量比如 mov ax idata或 add mov bx [idata]

循环指令
s: …

loop s

当执行到 loop s 时 ,会 对cx-- ,判断cx是否大于0,是则跳转到s继续执行。

汇编代码要求

不能直接对段寄存器进行赋值
汇编程序源代码,数据不能以字母开头,所以地址FFFFH 要写成 0FFFFH
[常数] 表示 常数,除非使用 段地址:[常数] 才代表地址的内容
[寄存器] 表示 寄存器中的值

写代码前思考

运算的单位是字节还是字
运算是否会溢出
是否要经过转换再计算

汇编程序的基本结构

assume cs:code
code segment
start : …



code ends
end start

end除了告诉编译器一个段的结束,还能说明程序的入口在哪

将不同的内容放在不同的段中

使结构更加清晰,并且不易出错

assume cs:code,ds:data,ss:stack
data segment
dw 0123h,0456h,0789h,0abch
data ends
stack segment
dw 0,0,0,0,0,0,0,0,0,0
stack ends
code segment
start:…
…//可以使用每段的段名,当做段地址,比如 data stack code,相当于常量
//比如:
// mov ax,data
//mov ds,ax

code ends
end

实验结果

在win10中的dosbox 中运行 每个段的偏移若小于64k,则下个段的地址为上个段的段地址+1
栈的地址空间中,起始地址是 空间的最大地址,

汇编大小写转换

由于ascii码中 小写字母a的16进制表示 为 61H ,大写字母A 的十六进制表示为41H
6对应的二进制为0110,4对应的二进制为0100,
所以使用汇编进行大小写转换时,不需要判断字母是大写还是小写,只需要
转换大写 and al,01000000B
转换小写 or al,01100000B

访问内存地址的方法总结(在编译情形下)

段地址:内存地址
[常数] 比如[1aaa]
[寄存器] 比如[bx]
[寄存器+常量] 比如[bx+1000]
[寄存器+寄存器] 比如[bx+si] ,可以写成 [寄存器][寄存器]
[寄存器+寄存器+常数] 可以写成 常数 [ax] [bx] 或者 [ax].常数 [bx] 或者[ax] [bx].200

能作为内存地址的寄存器

在8086cpu上,只有 bx ,si ,di ,bp 能作为[…] 里的内容
或者他们的固定组合方式, bx和si,bx和di,bp和si,bp和di
而其他寄存器寻址,比如 [ax] 等都是非法的操作,

bp的段地址默认为ss

指令要处理的数据

1.寄存器中
2.内存中
3.cpu指令缓冲区中 比如 add ax,1

8086数据寻址方式

直接寻址 [idata]
寄存器间接寻址
[bx]
[bp]
[si]
[di]
寄存器相对寻址
[bx+idata] //用于结构体寻址,数组,二维数组
[bp+idata]
[si+idata]
[di+idata]
基址变址寻址
[bx+si] //二维数组
[bx+di]
[bp+si]
[bp+di]
基址变址相对寻址
[bx+si+idata] //二维数组 或者结构体成员有数组
[bx+di+idata]
[bp+si+idata]
[bp+di+idata]


8086指令指定的数据长度

1.通过寄存器指定
ax ,ah,al
2.使用符号指定
word ptr
byte ptr
比如 mov word ptr [0],[10]
mov byte ptr [2],[3]
3.push 和pop操作
push和pop只能进行字操作


div 除法指令

除数:有8位和16位,可以在内存或寄存器中
被除数:默认放在 ax或dx中,
如果除数是8位,则被除数为16位在ax中。
如果除数是16位,被除数则为32位,dx中存放高16位,ax中存放低16位
结果:如果除数为8位,AL作为除法的商,AH存放余数,
如果除数为16位,ax作为除法的商,dx存放除法的余数
div 指令的格式
div reg
div 内存单元 比如 div byte ptr [bx]


编译器识别的指令总结

db dw dd 分别定义 字节, 字, 双字型数据
dup,和上面的指令配合使用,用于数据的复制

比如
dw 3 dup (0,1,2) //表示定义了9个字型数据,分别是0,1,2,0, 1,2, 0,1, 2

使用dup能非常方便在内存中开辟一块很大的区域,
比如
stack segment
db 200 dup(0)
stack ends


172页 实验7


转移指令

段间转移
段内转移:根据修改ip的范围不同,可以分成短转移和近转移
短转移:-128到127
近转移:-32768到32767

转移指令分类:
无条件转移 jmp
条件转移
循环指令 loop
过程
中断

offset操作符

由编译器解释,用于获取标号的偏移地址
比如
mov ax,offset s
mov dx,offset start

jmp指令

  • jmp 地址在 指令中

jmp short 标号(比如 s,start,s0)//short表明最多向前向后越过 -128到127个字节
注意 对于 jmp short 标号 ,这种指令,查看二进制内容会发现,jmp 后面紧跟的,二进制内容不是标号对应的地址,而是相对于当前位置的偏移量
在这里插入图片描述
jmp 的地址是 03 , jmp指令本身占两字节的 长度 ,jmp 的下一条指令 是05, EB 03 中的03 则表明,偏移是3 , 5+3=8 是jmp指令想要跳转的目的地址


jmp near ptr 标号
和 jmp short 标号类似,也是近转移 功能为 (ip)=(ip)+16位位移
16位位移 ,也是从jmp的下一条指令起始到标号处起始的 长度 范围 -32768-32767


jmp far ptr 标号
段间转移, 实现的功能 和 jmp cs:ip 相同
在这里插入图片描述


  • jmp 指令在寄存器中
    jmp 寄存器

  • jmp指令在内存单元中
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值