Contents

《汇编语言》学习笔记(updating)

oxoo 前言

在绿盟测试赛题时遇到Reverse就头大,于是购入了王爽老师的第四版《汇编语言》,从零开始学习。

0x01 基础知识

汇编语言有以下3类指令组成。

(1)汇编指令:机器码的助记符,有对应的机器码,汇编语言的核心。

(2)伪指令:没有对应的机器码,由编译器执行,计算机并不执行。

(3)其他符号:如+、-、*、/等,由编译器识别,没有对应的机器码。

CPU想要进行数据的读写,必须和外部器件进行下面3类信息交互。

(1)存储单元的地址(地址信息)-—到哪儿去?

(2)器件的选择,读或写的命令(控制信息)-—怎么去?

(3)读或写的数据(数据信息)-—谁去?

内存地址空间的大小受CPU地址总线宽度的限制

0x02 寄存器

AX、BX、CX、DX这4个寄存器通常用来存放一般性的数据,被称为通用寄存器。AX的低8位(0-7位)构成了AL寄存器,高八位(8-15位)构成了AH寄存器。

在进行数据传送或运算时,要注意指令的两个操作对象的位数应当是一致的。

物理地址=段地址x16+偏移地址

段地址x16有一个更为常用的说法,左移4位

CS为代码段寄存器,IP为指令指针寄存器。

8086CPU的工作流程可以简要描述如下:

(1)从CS:IP指向的内存单元读取指令,读取的指令进入指令缓冲器。

(2)IP=IP+所读指令的长度,从而指向下一条指令。

(3)执行指令。转到步骤(1),重复这个过程。

“jmp 段地址:偏移地址”指令的功能:用指令中给出的段地址修改CS,偏移地址修改IP。

“jmp 某一合法寄存器”指令的功能:用寄存器中的值修改IP。

0x03 寄存器(内存访问)

任何两个地址连续的内存单元,N号单元和N+1号单元,可以将它们看成两个内存单元,也可看成一个地址为N的字单元中的高位字节单元和低位字节单元。

“[…]“表示一个内存单元,”[…]“中的0表示内存单元的偏移地址。

如果将10000H-1FFFFH,这段空间当作栈段,初始状态栈是空的,此时,SS=1000H,SP=?

如果将10000H-1FFFFH这段空间当作栈段,SS=1000H,栈空间为64KB,栈最底的字单元地址为1000:FFFE。任意时刻,SS:SP指向栈顶单元,当栈中只有一个元素的时候,SS=1000H,SP=FFFEH。栈为空,就相当于栈中唯一的元素出栈, 出栈后,SP=SP+2。

SP原来为FFFEH,加2后SP=0,所以,当栈为空的时候,SS=1000H, SP=0。

换一个角度看,任意时刻,SS:SP 指向栈顶元素,当栈为空的时候,栈中没有元素,也就不存在栈项元素,所以SS:SP只能指向栈的最底部单元下面的单元,该单元的地址栈最底部的字单元的地址+2。栈最底部字单元的地址为1000:FFFE,所以栈空时,SP=0000H。

下载winXP,DEBUG使用的是十六进制。

详细使用可参考:https://www.cnblogs.com/tiger2soft/p/5094917.html

0x04 第一个程序

段名 segment

段名 ends

segment和ends是成对使用的伪指令,功能是定义一个段,segment说明一个段的开始,ends说明一个段的结束。

end是一个汇编程序的结束标记,不同于ends。

assume的含义是“假设”,将特定用途的段和相关的段寄存器关联起来。

安装masm来对程序进行编程、编译、连接、跟踪。

0x05 [BX]和loop指令

loop指令的格式是:loop标号,CPU执行loop指令时,要执行两步操作,1、(cx)=(cx)-1;2、判断cx中的值,不为零则转至标号处执行程序,如果为零则向下执行。

在汇编源程序中,数据不能以字母开头。

0x06 包含多个段的程序

“dw”的含义是定义字型数据。dw即“define word”。

在单任务系统中,可执行文件中的程序执行过程如下。

(1)由其他的程序(Debug、command或其他程序)将可执行文件中的程序加载入内存

(2)设置CS:IP指向程序的第一条要执行的指令(即程序的入口),从而使程序得以运行。

(3)程序运行结束后,返回到加载者。

“assume cs:code,ds:data,ss:stack"将cs、ds和ss分别和code、data、stack段相连。

0x07 更灵活的定位内存地址的方法

用’…..‘的方式指明数据是以字符的形式给出的,编译器将它们转化为相对应的ASCII码。

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

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

寻址方式

(1)[idata]用一个常量来表示地址,用于直接定位一个内存单元。

(2)[bx]用一个变量来表示内存地址,可用于间接定位一个内存单元。

(3)[bx+idata]用一个变量和常量表示地址,可在一个起始地址的基础上用变量间接定位一个内存单元。

(4)[bx+si]用两个变量表示地址。

(5)[bx+si+idata]用两个变量和一个常量表示地址。

一般来说,在需要暂存数据的时候,我们都应该使用栈。

0x08 数据处理的两个基本问题

reg的集合包括:ax、bx、cx、dx、ah、al、bh、bl、ch、cl、dh、dl、sp、bp、si、di;

sreg的集合包括:ds、ss、cs、es。

在8086CPU中,只有bx、si、di和dp可以用在”[….]“中来进行内存单元寻址。

在[…]中,这4个寄存器可以单个出现,或只能以4种组合出现:bx和si、bx和di、bp和si、bp和di。

只要在[…]中使用寄存器bp,而指令中没有显性地给出段地址,段地址就默认在ss中。

div做除法时的注意事项:

(1)除数:有8位和16位两种,在一个reg或内存单元中。

(2)被除数:默认放在AX或DX和AX中,如果除数为8位,被除数则为16位,默认在AX中存放;如果除数为16位,被除数则为32位,在DX和AX中存放,DX存放高16位,AX存放低16位。

(3) 结果:如果除数为8位,则AL存储除法操作的商,AH存储除法操作的余数;如果除数为16位,则AX存储除法操作的商,DX存储除法操作的余数。

dup的使用格式如下:

db 重复次数 dup (重复的字节型数据)

dw 重复次数 dup (重复的字型数据)

dd 重复次数 dup (重复的双字型数据)

0x09 转移指令的原理

短转移IP的修改范围为-128-127

近转移IP的修改范围为-32768-32767

操作符offset在汇编语言中是由编译器处理的符号,它的功能是取得标号的偏移地址。

jmp short 标号(转到标号处执行指令),实现段内的短转移,功能为(IP)=(IP)+8位位移。

CPU在执行jmp指令的时候并不需要转移的目的地址。

jmp near ptr 标号,实现的是段内近转移,功能为(IP)=(IP)+16位位移。

“jmp far ptr 标号"实现的是段间转移,又称远转移。

“jcxz 标号"的功能相当于:if((cx)==0) jmp short 标号;

0x0A CALL和RET指令

ret指令用栈中的数据,修好IP的内容,从而实现近转移。

retf指令用栈中的数据,修好CS和IP的内容,从而实现远转移。

CPU执行call指令时,进行两步操作:

(1)将当前的IP或CS和IP压入栈中;

(2)转移。

call 标号(将当前的IP压栈后,转到标号处执行指令)

CPU执行此种格式call指令时,进行两步操作:

(1)(sp)=(sp)-2

((ss)*16+(sp))=(IP)

(2)(IP)=(IP)+16位位移

call far ptr 标号,实现的是段间转移。

CPU执行此种格式call指令时,进行两步操作:

(1)(sp)=(sp)-2

((ss)*16+(sp))=(CS)

(sp)=(sp)-2

((ss)*16+(sp))=(IP)

(2)(CS)=标号所在段的段地址

(IP)=标号所在段中的偏移地址

使用mul做乘法的时候,注意以下两点:

(1)两个相乘的数:两个相乘的数,要么都是8位,要么都是16位。如果是8位,一个默认放在AL中,另一个放在8位reg或内存字节单元中;如果是16位,一个默认放在AX中,另一个放在16位reg或内存字节单元中;

(2)结果:如果是8位乘法,结果默认放在AX中;如果是16位乘法,结果高位默认放在DX中,低位在AX中。

0x0B 标志寄存器

CF和OF的区别:CF是对无符号数运算有意义的标志位,而OF是对有符号数运算有意义的标志位。

adc是带进位的加法指令,利用了CF上记录的进位值。

指令格式:adc 操作对象1 操作对象2

功能:操作对象1=操作对象1+操作对象2+CF

如果CF的值是被sub指令设置的,那么它的含义就是借位值;如果是被add指令设置的,那么它的含义就是进位值。

sbb是带借位的减法指令,利用了CF上记录的借位值。

指令格式:sbb 操作对象1 操作对象2

功能:操作对象1=操作对象1-操作对象2-CF

cmp是比较指令,cmp的功能相当于减法指令,只是不保存结果。cmp指令执行后,将对标志寄存器产生影响。其他相关指令通过识别这些被影响的标志寄存器位来得知比较结果。

DF在串处理指令中,控制每次操作后si、di的增减。

df=0 每次操作后si、di递增;df=1 每次操作后si、di递减。