汇编语言学习笔记

Coding Alan 10年前 (2015-05-16) 6349次浏览 扫描二维码

汇编语言学习笔记

第一天 – 基础知识

机器语言是机器指令的集合

指令: 01010000 (PUSH AX)

汇编语言是直接在硬件之上工作的编程语言,汇编语言的主体是汇编指令,汇编语言是机器指令便于记忆的书写格式。寄存器是CPU中可以存储数据的器件,如AX, BX等。

CPU要对存储器进行数据的读写,需要进行三类信息的交互:地址信息、控制信息(读或写等)和数据信息。计算机中连接CPU和其它芯片的导线通常称为总线,因而对应的就有地址总线、控制总线和数据总线。

CPU从内存中读取数据的过程演示(通过地址总线确定内存中的地址,控制总线发出读的指令,数据总线到对应的地址读取数据):

汇编语言学习笔记

CPU向内存中写入数据的过程演示

汇编语言学习笔记

地址总线:一个CPU有n根总线,则可以 说这个CPU的地址总线的宽度为n,这样的CPU可以寻找2n个内存单元

数据总线:数据总线的宽度决定了CPU和外界的数据传送速度,8088CPU数据总线宽度为8,8086CPU数据总线宽度为16

控制总线:CPU对外部器件的控制是通过控制总线来进行的

主板上的器件通过总线连接,CPU通过插在扩展插槽上的接口卡控制外部设备(显示器、音箱、打印机等)。

只读存储器:装有BIOS(Basic Input/Output System)的ROM,习惯上在数字最后加H表示十六进制(Hexadecimal),加B表示二进制(Binary)

第二天 – 寄存器(CPU工作原理)

一个典型的CPU由运算器控制器寄存器等器件组件,这些器件由内部总线相连接。8086CPU有14个寄存器,分别为AX, BX, CX, DX, SI, DI, SP, BP, IP, CS, SS, DS, ES, PSW。8086CPU所有的寄存器都是16位的,可以存放两个字节。AX, BX, CX, DX通常用来存放一般性的数据被称为通用寄存器。以AX为例,通用寄存器的逻辑结构如下:

汇编语言学习笔记

8086上一代CPU为8088,其寄存器都是8位,因此为保持兼容性AX(BX, CX, DX同理)可以分为AH和AL两个独立的8位寄存器。

汇编语言学习笔记

一个字可以存在一个16位寄存器中,这个字的高位字节和低位字节自然就存在这个寄存器的高8位寄存器和低8位寄存器中。

汇编指令不区分大小写,举例如下:

汇编语言学习笔记

CPU访问内存单元时要给出内存单元的地址。所有的内存单元构成的存储空间是一个一维的线性空间。

每一个内存单元在这个空间中都有唯一的地址,这个唯一的地址称为物理地址

8086有20位地址总线(外部),可传送20位地址,寻址能力为1M(220)。而8086内部为16位结构,它只能传送16位的地址,表现出的寻址能力却只有64K(216)。因些8086CPU采用一种在内部用两个16位地址(段地址[SA]和偏移地址[EA])合成的方法来形成一个20位的物理地址(物理地址 = 段地址×16+偏移地址)。合成出物理地址的演示如下:

汇编语言学习笔记

“段地址 x 16″就是二进制左移4位,CPU可以通过不同的段地址和偏移地址来形成同一个物理地址。

段寄存器:CS, DS, SS, ES。CS和IP是8086CPU中最关键的寄存器,CS为代码段寄存器存放指令的段地址,IP为指令指针寄存器存放指令的偏移地址。

在 8086CPU 加电启动或复位后( 即 CPU刚开始工作时)CS和IP被设置为CS=FFFFH,IP=0000H,即在8086PC机刚启动时,CPU从内存FFFF0H(CS:IP)单元中读取指令执行,FFFF0H单元中的指令是8086PC机开机后执行的第一条指令。

修改CS, IP的指令: jmp 段地址:偏移地址

仅修改IP的内容: jmp 某一合法的寄存器,如jmp ax或jmp bx

CPU只将CS:IP指向的内存单元中的内容看作指令,执行完后IP指向下一条指令。

Win+R,输入cmd,然后在命令窗口输入debug进入调试窗口,其中常用的一些命令有:

R命令查看、改变CPU寄存器内的内容;

D命令查看内存中的内容;

E命令改写内存中的内容;

U命令将内存中的机器指令翻译成汇编指令;

T命令执行一条机器指令;

A命令以汇编指令的格式在内存中写入一条机器指令;

第三天 – 寄存器(内存访问)

CPU通过 内存单元的地址读取一个内存单元,8086CPU中有一个DS寄存器(段地址),偏移地址放在中括号中,如[0],读取内存单元中地址10000H数据

mov bx, 1000H

mov ds, bx

mov al, [0]

注意,不能使用mov ds, 1000H

:后进先出(LIFO – Last In, First Out),入栈和出栈的指令分别为PUSH和POP。段寄存器SS存放栈顶的段地址,寄存器SP存放栈顶的偏移地址。当栈满 的时候再使用push指令入栈,当栈空的时候再使用pop命令出栈,都将发生栈顶越界问题。

第四天 – 第一个程序

编写:使用文本编缉器(如Notepad++,UltraEdit等),用汇编语言编写汇编源程序;

编译连接:使用汇编语言编译程序(MASM.EXE)对源程序文件中的源程序进行编译,产生目标文件;

再用连接程序(LINK.EXT)对目标文件进行连接,生成可在操作系统中直接运行的可执行文件;

执行:将可执行文件中的机器码和数据加载入内存,并进行相关的初始化,然后由CPU执行

汇编语言学习笔记

测试编写执行计算23的程序

首先创建一个asm文件,如1.asm

assume cs:abc

	abc segment
		mov ax, 2
		add ax, ax
		add ax, ax

		mov ax, 4c00H
		int 21H
	abc ends

end

下载masm(下载地址: http://pan.baidu.com/s/1ntxcDCl 密码: e69b)将其中的LINK,EXE, MASM.EXE, ML.EXE解压到与1.asm相同的文件夹

打开cmd窗口,cd到1.asm存放的文件夹,执行masm 1.asm,编译成功在该文件夹中会出现一个1.obj文件,输入link 1.obj,在相应的位置按enter键继续执行(加分号就不需要再按enter键),内容如下:

Run File [1.exe]:

List File [nul.map]:

Libraries [.lib]:

Definitions File [nul.def]:

LINK : warning L4021: no stack segment

LINK : warning L4038: program has no starting address(在程序中添加mov ax, 4c00H以及int21H即可去除这一警告)

连接成功后会出现一个可执行文件1.exe,直接输入1.exe即可执行程序,执行完成后会返回原来的cmd窗口。通过ml 1.asm可同时完成编译和连接两个过程。在cmd中输入debug 1.exe可在debug中执行该程序,此时您可能会注意到DS和CS并不相同,比如DS为14DB,CS为14EB,加上偏移地址共相差256个字节,其中存放的是PSP。在debug中可使用t命令对程序进行单步高度,但在int 21H这一步请执行p命令, 这时会提示程序正常结束(Program terminated normally),返回到debug中,执行q命令返回到cmd窗口。

汇编语言学习笔记

第五天 – [BX]和loop指令

以下代码中CX用于控制循环次数,s为标号(可自定义)

assume cs:code
code segment
	mov ax,2
	mov cx,11
	s:add ax,ax
	loop s

	mov ax,4c00h
	int 21h
code ends

end

在汇编程序中mov ax, ffffh要写成mov ax, 0ffffh,因为汇编源程序中数据不能以字母开头,报错信息类似:4.asm(3) : error A2006: undefined symbol : ffffh,所以要在前面加0。

assume cs:code
	code segment
		mov ax, 0ffffh
		mov ds, ax
		mov bx, 6
		mov ax, [bx]

		mov dx,0
		mov cx,123

		s: add dx, ax
		loop s

		mov ax, 4c00h
		int 21h

	code ends
end

在debug中对于上述这样将ffff:6中的值乘以123次或更多次时进行单步调试难度可想而知,这时可以通过u查看指定代码的ip值然后用g指令加指定ip地址来执行到对应步骤(这里ds为14D8,而用u查看代码起始位置在14E8是因为存放了256个字节的PSP),或者在单步执行到Loop循环的位置时执行p指令也可将循环执行完毕

汇编语言学习笔记

一段安全的空间:随意向内存空间中写入内容是很危险的,在一般的PC机中DOS模式下,DOS和其它合法的程序都没有使用0:200~0:2FF这个内存单元,所以可以安全地对这段内存单元进行操作。

第六天 – 包含多个段的程序

源程序中使用伪指令用assume cs:code, ds:data, ss:stack将cs,ds,ss分别和code,data,stack相连,但若要CPU知道并执行,我们在code段中使用指令

mov ax, stack
mov ss,ax
mov sp,16

第七天 – 更灵活的定位内存地址的方法

and和or指令,and是逻辑与指令,按位进行与运算;or是逻辑或指令,按位进行或运算。

ASCII码:ASCII完整码表

大小写转换:大写字母与小写字母在ASCII码中相差32(20H),所以大写转小写只需要加上32(20H)即可,另外大小写字母另一个差别在二进制中大写字母第5位为0,小写字母第5位为1,因此可以通过和11011111b的与运算来将小写变成大写,能过和00100000b的或运算来将大写变成小写,示例如下:

assume cs:codesg, ds:datasg
datasg segment
db 'BaSiC'
db 'iNfOrMaTiOn'
datasg ends

codesg segment
start:  mov ax, datasg
		mov ds,ax
		
		mov bx,0
		mov cx,5
		s:mov al,[bx]
		and al,11011111b
		mov [bx],al
		inc bx
		loop s
		
		mov bx,5
		mov cx,11
		s0:mov al,[bx]
		or al,00100000b
		mov [bx],al
		inc bx
		loop s0
		
		mov ax,4c00h
		int 21h
codesg ends

end start

备注:汇编语言中常用中英文对照

AH&AL=AX(accumulator): 累加寄存器

BH&BL=BX(base):基址寄存器

CH&CL=CX(count):计数寄存器

DH&DL=DX(data):数据寄存器

SP(Stack Pointer):堆栈指针寄存器

BP(Base Pointer):基址指针寄存器

SI(Source Index):源变址寄存器

DI(Destination Index):目的变址寄存器

IP(Instruction Pointer):指令指针寄存器

CS(Code Segment)代码段寄存器

DS(Data Segment):数据段寄存器

SS(Stack Segment):堆栈段寄存器

ES(Extra Segment):附加段寄存器

OF overflow flag 溢出标志 操作数超出机器能表示的范围表示溢出,溢出时为1.

SF sign Flag 符号标志 记录运算结果的符号,结果负时为1.

ZF zero flag 零标志 运算结果等于0时为1,否则为0.

CF carry flag 进位标志 最高有效位产生进位时为1,否则为0.

AF auxiliary carry flag 辅助进位标志 运算时,第3位向第4位产生进位时为1,否则为0.

PF parity flag 奇偶标志 运算结果操作数位为1的个数为偶数个时为1,否则为0.

DF direcion flag 方向标志 用于串处理.DF=1时,每次操作后使SI和DI减小.DF=0时则增大.

IF interrupt flag 中断标志 IF=1时,允许CPU响应可屏蔽中断,否则关闭中断.

TF trap flag 陷阱标志 用于调试单步操作.

1. 通用数据传送指令.

MOV 传送字或字节.

MOVSX 先符号扩展,再传送.

MOVZX 先零扩展,再传送.

PUSH 把字压入堆栈.

POP 把字弹出堆栈.

PUSHA 把AX,CX,DX,BX,SP,BP,SI,DI依次压入堆栈.

POPA 把DI,SI,BP,SP,BX,DX,CX,AX依次弹出堆栈.

PUSHAD 把EAX,ECX,EDX,EBX,ESP,EBP,ESI,EDI依次压入堆栈.

POPAD 把EDI,ESI,EBP,ESP,EBX,EDX,ECX,EAX依次弹出堆栈.

BSWAP 交换32位寄存器里字节的顺序

XCHG 交换字或字节.( 至少有一个操作数为寄存器,段寄存器不可作

为操作数)

CMPXCHG 比较%B

喜欢 (0)
[]
分享 (0)