汇编语言
2021-07-11 12:01:10 0 举报
AI智能生成
汇编语言整理
作者其他创作
大纲/内容
汇编指令(8086)
mov(赋值)
mov ax, 1234H
mov ax, ds:[0]<br>(段前缀访问模式,不加段前缀,默认ds段)<br>mov ds:[0], ax<br>mov ax, [200+bx] = mov ax, 200[bx] = mov ax, [bx].200<br>mov ax, [bx+si] = mov ax, [bx][si]<br>mov ax, [bx+si+di] = mov ax, [bx][si][di]<br>(偏移地址的多种访问方式)<br>mov byte ptr....,如mov byte ptr [bx],1<br>mov word ptr....,如mov byte word [bx],1<br>(操作内存的时候,可以指定ptr值名操作内存的大小)
add(加法)
add ax, bx(结果存到ax)
sub(减法)
sub ax, bx(结果存到ax)
mul(乘法)
mul bl(用al与bl相乘,结果放在ax中)
mul bx (用ax与bx相乘,高位放在dx中,低位放在ax中)
mul byte ptr [bx]
mul word ptr [bx]
loop(循环)
s: 代码段<br> loop s
int(中断)
int 21H
jmp(指令跳转)
jmp 2AE3:3 (将CS设置2AE3,IP设置为3)
jmp ax (将IP设置为ax中的值)
jmp dword ptr ds:[0]<br>(ds[0]-ds[1]是偏移地址,ds[2]-ds[3]是段地址)
jmp far prt [标号]<br>(将cs设置为标号的cs,将ip设置为标号的ip)
jmp word ptr [bx]<br>jmp word ptr ds:[0]<br>(将IP中的值设置为内存中的值)
jmp short [标号]<br>(s为某段代码,汇编会根据jmp的目的地址,修改IP的值,即ip = ip + 需要跳转代码的字节数)<br>(只支持8位位移,即-128~127)<br>
jmp near ptr [标号]<br>(支持16位转移,即-32768~23767)
jcxz(指令有条件位移)
jcxz [标号] (当cx寄存器为0的时候,相当于jmp short [标号])
ret(指令跳转)
出栈第一个数据,修改IP的内容<br>
retf(指令跳转)
先出栈第一个数据先修改CS的内容,在出栈第二个数据修改IP的内容<br>
iret(指令跳转)
先出栈第一个数据修改IP的内容,在出栈一个数据出栈CS的内容
call(指令跳转+位移)
call [标号] (将当前的IP入栈,在位移到标号处,相当于jmp near ptr [标号])
call far ptr [标号](将当前CS入栈,再将IP入栈,在将cs与ip设置为标号处的值)
call ax (先将当前IP入栈,然后自将IP的值设置为ax的值)
call word ptr [bx](先将当前IP入栈,在将IP设置为bx内存处的值)
call dword ptr [bx](先将当前cs入栈,在将ip入栈,在跳转至内存bx指向的cs与ip,相当于先做两次push,在jmp dword ptr [bx] )
push(入栈)
push ax<br>push [100]<br>
pop(出栈)
pop ax
inc(自增)
inc ax
dec(自减)
dec ax
and(逻辑与)
两个2进制数,将两数字同为位为1的位置,设置为1,否则设置为0
or(逻辑或)
两个2进制数,将两数字任意位为1的位置,设置为1,否则设置为0
xor(异或)<br>
如果两个位的值相同,设置为1,否则设置为0
div(除法)
如果被除数大于16位,则高16位用DX,低16位用AX
abc(带进位加发)
sbb(带借位减法)
cmp(比较)
cmp ax, bx<br>
无符号<br>结果:目的操作数 < 源操作数 ZF=0 CF=1<br>结果:目的操作数 > 源操作数 ZF=0 CF=0<br>结果:目的操作数 = 源操作数 ZF=1 CF=0<br>
有符号<br>结果:目的操作数 < 源操作数 SF ≠ OF<br>结果:目的操作数 > 源操作数 SF=OF<br>结果:目的操作数 = 源操作数 ZF=1<br>
je(等于则转移)
zf = 1
jne(不等于则转移)
zf = 0
jb(低于则转移)
cf = 1
jnb(不低于则转移)
cf = 0
ja(高于则转移)
cf = 0 && zf = 0
jna(不高于则转移)
cf = 1 || zf = 1
rep(重复指令)
rep xx(根据cx的值,重复执行后面的指令)
movsb(串传送指令)
movsw(串传送指令,传送一个字)
rep
iret
将栈中的前16位放入CS中,再讲接下来16位放入IP中,在将接下来16位放入flag中
cld(将标志寄存器的df位置设为0)
std(将标志寄存器的df位置设为1)
sti(将标志寄存器的if位置设为1)
打开中断
cli(将标志寄存器的if位置设为0)
关闭中断
pushf(将标志寄存器的值压栈)
prof(将标志寄存器的值出栈)
in(端口读)
out(端口写)
shl(逻辑左移)
shr(逻辑右移)
hlt(cpu睡眠)
nop(空指令)
xchg(交换)
lock(锁前缀)<br>
lock add ax, 1(只对当前指令生效)
汇编指令(80386)
lgdt(加载GDT的地址进入GDTR寄存器)
sgdt(保存GDTR寄存器中的内容)
pushfd(32为eflag寄存机入栈)
popfd(32为eflag寄存机出栈)
伪汇编指令(masm6.11)
assume(定义有用途的段和相关寄存器的联系)
申明代码段 assume cs:[code]
申明数据段 assume ds:[data]
申明栈段 assume ss:[stack]
segmen(段定义)
定义代码段([code] segment)
定义数据段([data] segment,mov ds data)
定义栈段([stack] segment,mov ss, stack)
ends(定义的代码段结束的标记)
end(汇编代码结束的标记)<br>
通知程序结束
通知程序入口在哪,即加载汇编程序后,设置IP:end start
dw(定义字类型数据)
dw 0123h,0456h
db(定义字节类型数据)
db 'linux'
dd(定义双字数据)
dd 100001h
dup(数据重复定义)
db 3 dup (0) = db 0 0 0
offset(获取标号偏移地址)
mov ax, offset start<br>获取start的偏移地址
+ - * / mod (四则运算符号)
org(设置程序起始地址)
org 2000H(将代码开始的偏移指令放在2000H)
汇编语言源程序中若没有ORG伪指令,则程序执行时,指令代码被放到自由内存空间的CS:0处;<br>若有ORG伪指令,编译器则把其后的指令代码放到ORG伪指令指定的偏移地址。
两个ORG伪指令之间,除了指令代码,若有自由空间,则用0填充。
数字表示
2进制
11011011b(字母B结尾)
16进制
9fh(字母h结尾,如果第一位是字母,需要0开头)
10进制
9(不需要结尾标注)
伪汇编指令(nasm2.15)
equ(定义常量)
test db 'hello world'
db<br>db<br>dd<br>dq<br>dt
times(汇编指令被汇编多次)
有效的地址引用
wordvar dw 123<br>mov ax, [wordvar]<br>mov ax, [wordvar + 1]<br>mov ax, [wordvar + 1 + di]<br>mov as, [es:wordvar+bx]
mav ax, wordvar(将wordvar的偏移地址赋值ax)<br>mov ax, [wordvar](将wordvar的值123赋值给ax)
$
当前代码开始处的位置,不包含当前行
$$
当前段开始处的地址,通过$-$$可以计算出当前段内的偏移
常数
数值常数
mov ax, 0a2h<br>mov ax, 100
字符常数
mov ax, 'ab'
字符串常数
db 'abcdefg'
浮点常数
dd 1.2<br>
运算符号
| 或运算<br>^ 异或<br>& 与运算<br><< 左位移预算<br>>> 右位移运算<br>+ 加法<br>- 减法<br>* 乘法<br>/ 除法,无符号<br>// 除法,有符号<br>% 模运算,无符号<br>%% 模运算,有符号
seg()
wrt()
临界表达式
NASM 的一个限制是它是一个两遍的汇编器,它总是只做两遍汇编。<br>第一遍汇编是用于确定所有的代码与数据的尺寸大小,这样的话,<br>在第二遍产生代码的时候,就可以知道代码引用的所有符号地址。<br>所以,有一件事NASM 不能处理,那就是一段代码的尺寸依赖于另一个符号值,<br>而这个符号又在这段代码的后面被声明。比如: <br>times (label-$) db 0<br> label: db 'Where am I?'<br>第一遍的时候,无法确认label的值,导致无法计算,因为label的值需要看times重复几次
本地labels
section
1.组织代码与存储的方式<br>2.支持标准的.data, .text和.bss,编译后的程序文件中的内存地址顺序是.text, .data,用户自定义section<br>3.同名的section,编译后会放在同一块连续的内存上<br>4.每个SECTION默认都是按4字节对齐的
bits
[bits 16]以下代码编译成16位<br>[bits 32]以下代码编译成32位
宏定义
模板<br>%macro macro_name number_of_params<br><macro body><br>%endmacro<br>示例<br>%macro Descriptor 3<br> dw %2 & 0FFFFh<br> dw %1 & 0FFFFh<br> db (%1>>16) & 0FFh<br> dw ((%2 >> 8) & 0F00h) | (%3 & 0F0FFh)<br> db (%1 >> 24) & 0FFh<br>%endmacro<br><br>%1第一个参数,%2第二个参数,%3第三个参数
align
align num,num 必须是2的幂,如:2、4、8和16等<br>本伪指令下面的内存变量必须从下一个能被Num整除的地址开始分配。<br>如果下一个地址正好能被Num整除,那么,该伪指令不起作用,否则,汇编程序将空出若干个字节,直到下一个地址能被Num整除为止。<br>
寄存器(8086)
ax(通用寄存器)
乘法结果的低16位
端口的读写中间寄存器
bx(通用寄存器)
ds的端的偏移地址
cx(通用寄存器)
loop遍历计数器
jcxz条件跳转指令
dx(通用寄存器)
被除数的高位;结果的余数
乘法结果的高16位
si(通用寄存器,不能拆分为2个8位,支持[si + 偏移地址],ds段的偏移地址)
di(通用寄存器,不能拆分为2个8位,支持[di + 偏移地址],ds段的偏移地址)
cs(指令段地址)
ds(数据段地址)
ss(栈段地址)
es(附加段寄存器)
ip(指令偏移地址,cs段的偏移地址)
sp(栈偏移地址)
入栈,SP会减,出栈,SP会增加,永远指向栈顶
bp(基址寄存器)
一般在函数中用来保存进入函数时的sp的栈顶基址
flag(标志寄存器)
zf(零标志位,记录相关指令执行后,其结果是否为0,1=是,0=否。如add,sub,or,and等)<br>
debug中:ZR=1 NZ=0
pf(奇偶标志位,记录相关指令执行后,其结果的所有bit位中1的个数是偶数是偶数,1=是,0=否)
debug中:PE=1 PO=0
sf(符号标志位,记录相关指令执行后,其结果是否是为负数,1=是,0=否)
debug中:NG=1 PL=0
cf(进位标志位,它记录无符号运算结果的最高有效位是否向更高位进位或者借位,1=是,0=否)
debug中: CY=1 NC=0
通常用来比较,比较大小时,如果小于,则等于减法借位,导致cf = 1
of(溢出标志位,它记录有符号符号运算是否发生了溢出,1=是,0=否)
debug中:OV=1 NV = 0
df(方向标志位)
debug中:DN=1 UP=0
if(是否响应可屏蔽中断标志位,1=是,0=否)
寄存器(80836)
cr0
GDTR
eflag
debug工具
R (查看CPU中的信息)
D (查看内存中的信息,D 2000:0)
E(修改内存中的信息,E 2000:0 1 2 3……)
U(查看CS与IP最近10条的汇编指令,多次执行,等于翻页 -U -U 1000:10)
A(用汇编指令的模式,编写)
T(执行当前IP指向的汇编指令)
P(执行完当前循环,将IP执行下一个指令)
G(将IP跳到指定的编译地址,如G 00FF)
常用编译器
masm 编译
masa(masa 汇编源码文件,生成obj文件)
link(link obj文件,生成可执行文件)
nasm 编译
nasm.exe -f bin test.asm
masm与nasm区别
其他
字节(8bit)
CPU访问的最小单位是一个字节,即一个物理地址对应一个字节
字(2个字节)
16进制表示法,16进制1位=2进制4位
段寄存器需要用寄存器赋值,无法直接赋值
寄存器中,操作偏移量都是字节,如:偏移1=一个字节(比较难以理解,容易陷入其中)
立即数: idata,编码写在汇编指令的数字
同一个汇编指令,对应的立即数位数不一致,其指令也不一致
jmp 4e00(这里的jmp的机器码 = e9)
jmp 4f(这里的jmp的机器码 = eb)
代码转移
短转移只支持8位计算偏移地址
长转移支持16位计算偏移地址
转移可以理解为相对路径跳转
代码跳转可以理解为绝对路径跳转
补码
最高位为1,表示负数
正数的补码取反加1后,为其对应的负数的补码
负数的补码取反加1后,为其绝对值
正数的补码与其二进制一样
汇编中补码
mov al, 0F0H,表示有符号数-16的补码
中断程序
一个中断向量里面,可以有多个子程序
bios(基本输入输出系统)
硬件系统的检测与初始化程序
外部中断和内部中断的中断程序
用于对硬件设备进行I/P操作的中断程序
其他和硬件系统相关的中断程序
与输入输出设备交互,通过设置寄存器的值,通知io设备,完成操作
bios与dos中断程序安装
开机后,CPU通电后,初始化CS=FFFFH,IP=0,自动从FFFF:0单元开始执行程序。FFFF:0处有一条跳转指令,CPU执行该指令后,转去执行BIOS中的硬件系统检测与初始化程序
初始化程序将建立BIOS所支持的中断向量,即将BIOS提供的中断程序的入口地址登录在中断向量表中。注意,对于BIOS所提供的的中断程序,只需将入口地址登记在中断向量表中即可,以为它们是固话到ROM中的程序,一直在内存中存在
硬件系统检测和初始化程序完成后,调用int 19h进行操作系统的引导,从此将计算机交给操作系统控制
操作系统启动后,除完成其他工作外,还将它自己所提供的的中断程序装入内存,并存入中断向量表中
中断类型
中断方式
内中断
除法错误
单步执行
执行info指令
执行int指令
外中断
外部设备的中断
中断类型
可屏蔽中断
几乎所有的外设都是可屏蔽中断
不可屏蔽中断
中断向量表
一共有256中断,每个中断占用4个字节,用来存放cs与ip,中断类型号码 * 4 = IP,中断类型号码 * 4 + 2 = CS
其内存地址:0000:0000 ~ 0000:03FF,一共1024个字节
中断过程
获取中断码
标志寄存器的值入栈,再讲第8位TF与第9位IF的值设置为0
将CP入栈,再将IP入栈
获取中断程序的cs与ip,并设置
CPU工作模式
实模式
通过段地址+偏移地址,直接访问物理地址
保护模式
通过段选择器定位GDT或者LDT中的段描述符,找到其中的基地址+偏移,访问物理地址
虚拟8086模式
.com tiny
masm6编译出来的文件,前面有256字节的内容,代码都放在其后面,这里存放的是文件头,代码段,初始化数据段三部分
0 条评论
下一页