IA-32中常见的伪指令
- 格式:docx
- 大小:17.30 KB
- 文档页数:2
伪指令知识点总结伪指令这玩意儿,听起来是不是有点玄乎?其实啊,它就像我们生活中的“幕后英雄”,虽然不直接参与“表演”,但却起着至关重要的作用。
比如说,在编程的大舞台上,指令就像是冲锋陷阵的战士,执行着各种具体的任务。
而伪指令呢,则像是军师,在幕后出谋划策,为整个程序的架构和布局提供指导。
咱先来说说数据定义伪指令。
这就好比是在为程序的“仓库”划分区域,规定好每个区域存放什么样的“货物”。
比如说,定义一个字节类型的数据,就像是给仓库里划出一个小格子,只能放一个小小的“物件”;定义一个字类型的数据呢,那就是一个稍微大一点的格子,可以放个稍微大一点的“宝贝”。
你说这是不是很形象?再看看段定义伪指令。
这就像是给程序的“大部队”划分阵营。
不同的阵营有不同的任务和职责。
比如说,代码段就是专门负责执行具体操作的“战斗部队”;数据段呢,则是存放各种“粮草弹药”的地方。
如果没有段定义伪指令,那程序岂不是乱成了一锅粥?还有过程定义伪指令,这就像是给程序中的一个小任务成立了一个“特别行动小组”。
这个小组有自己的规则和流程,能独立完成特定的功能。
宏定义伪指令呢?这就好比是给程序制作了一个“快捷方式”。
当你需要重复执行一段复杂的操作时,不用一次次地重复写那些代码,只要调用这个“快捷方式”就行了,多省事啊!伪指令的作用可不仅仅是这些,它还能控制程序的编译过程,就像是一个精明的“导演”,掌控着整个程序的“拍摄进度”和“效果呈现”。
总之,伪指令在编程中可是不可或缺的存在。
要是没有它们,程序就像是失去了方向的船只,在茫茫的代码海洋中迷失。
所以啊,咱们可得好好掌握这些伪指令的知识,让我们的程序能够高效、准确地运行,为我们解决各种复杂的问题。
你说是不是这个理儿?。
《计算机系统基础》模拟试卷及答案一、单项选择题(共20题,40分)1、—个完整的计算机系统包括硬件和软件。
软件又分为()A、操作系统和语言处理程序B、系统软件和应用软件C、操作系统和髙级语言D、低级语言程序和高级语言程序2、假设同一套指令集用不同的方法设计了两种计算机A和B。
机器A的时钟周期为1.2ns ,机器B的时钟周期为2ns。
某个程序在机器A上运行时的CPI为2,在B上的CPI为1,则对于该程序来说,机器A和机器B之间的速度关系为()。
A、机器A比机器B快1.2倍B、机器B比机器A快1.2倍C、机器A的速度是机器B的1.2倍D、机器B的速度是机器A的1.2倍3、以下有关指令集体系结构的说法中,错误的是()A、指令集体系结构位于计算机软件和硬件的交界面上B、指令集体系结构是指低级语言程序员所看到的概念结构和功能特性C、程序员可见寄存器的长度、功能与编号不属于指令集体系结构的内容D、指令集体系结构的英文缩写是ISA4、以下有关冯•诺依曼计算机结构的叙述中,错误的是()。
A、计算机由运算器、控制器、存储器和输入/输岀设备组成B、程序由指令和数据构成,存放在存储器中C、指令由操作码和地址码两部分组成D、指令按地址访问,所有数据在指令中直接给出5、假定变量i、f的数据类型分别是int、float。
已知i=12345,f=1.2345e3,则在一个32位机器中执行下列表达式时,结果为“假”的是()。
A、i==(int)(float)iB、i==(int)(double)iC、f==(float)(int)fD、f==(float)(double)f6、在一般的计算机系统中,西文字符编码普遍采用()。
A、BCD码B、ASCII码C、格雷码D、CRC码7、“北”的区位码是1717,那么,其机内码是()。
A、B1B1HB、1717HC、9797HD、3737H8、CPU中能进行算术和逻辑运算的最基本运算部件是()。
完整版汇编语言中常用的伪指令档汇编语言是一种低级的程序设计语言,它用于编写底层计算机程序。
在汇编语言中,伪指令是一类特殊的指令,它们在程序运行时不会被计算机执行,而是在编译或汇编时被处理器或汇编器解释和展开。
伪指令在汇编语言中起到辅助编程、优化代码和声明常量等作用。
本文将介绍完整版汇编语言中常用的伪指令档。
一、伪指令的定义和作用伪指令是汇编语言中的一类特殊指令,它们不是真正的指令,不会被计算机执行,而是在编译或汇编的过程中被汇编器或处理器解释和处理。
伪指令主要用于辅助编程、优化代码和声明常量等作用。
伪指令的格式一般与真正的指令相似,但一般不包含操作码。
在一些汇编语言中,伪指令以特殊的标记或符号来区分,比如以“.”开头的指令。
二、常用的伪指令档1. ORG指令ORG指令用于指定程序的起始地址。
在汇编程序中,使用ORG指令可以将程序的代码段或数据段放置在指定的内存地址处。
其格式一般为:ORG 地址其中,地址为16进制数或表示内存单元的符号。
2. EQU指令EQU指令用于定义符号常量或符号变量。
它将一个符号与一个数值或地址进行关联,使得在程序中使用该符号时可以被汇编器或处理器替换为对应的数值或地址。
其格式一般为:符号 EQU 数值或地址其中,符号为一个标识符,数值或地址可以是16进制数、10进制数或表示内存单元的符号。
3. DB指令DB指令用于定义字节型数据。
它可以用于声明字符、整数等字节型数据,并将这些数据存储在指定的内存地址中。
其格式一般为:标号 DB 表达式其中,表达式可以是一个字节常量、字符常量或表示内存单元的符号。
4. DW指令DW指令用于定义字型数据。
它可以用于声明无符号整数等字型数据,并将这些数据存储在指定的内存地址中。
其格式一般为:标号 DW 表达式其中,表达式可以是一个字常量或表示内存单元的符号。
5. DD指令DD指令用于定义双字型数据。
它可以用于声明无符号双字整数等双字型数据,并将这些数据存储在指定的内存地址中。
IA-32常用指令类型(4)控制转移指令指令执行可按顺序或跳转到转移目标指令处执行–无条件转移指令JMP DST:无条件转移到目标指令DST处执行–条件转移Jcc DST:cc为条件码,根据标志(条件码)判断是否满足条件,若满足,则转移到目标指令DST处执行,否则按顺序执行–条件设置SETcc DST:按条件码cc判断的结果保存到DST(是一个8位寄存器)–调用和返回指令(用于过程调用)CALL DST:返回地址RA入栈,转DST处执行RET:从栈中取出返回地址RA,转到RA处执行–中断指令(详见第7、8章)IA-32的标志寄存器•6个条件标志–OF、SF、ZF、CF 各是什么标志(条件码)?–AF:辅助进位标志(BCD码运算时才有意义)–PF:奇偶标志•3个控制标志–DF(Direction Flag):方向标志(自动变址方向是增还是减)–IF(Interrupt Flag):中断允许标志(仅对外部可屏蔽中断有用)–TF(Trap Flag):陷阱标志(是否是单步跟踪状态)•……808680286/386回顾:整数减法举例-7-6 = -7 + (-6) = +3 -3 -5 = -3 + (-5) = -89 -6 = 3 13 -5 = 811++0001111111011110101111可利用条件标志进行大小判断X √做减法以比较大小,规则:Unsigned: CF=0时,大于Signed:OF=SF时,大于OF=0、ZF=0、SF=1、借位CF=0OF=1、ZF=0SF=0、借位CF=0√√验证:9>6,故CF=0;13>5,故CF=0验证:-7<6,故OF≠SF-3<5,故OF≠SF条件转移指令分三类:(1)根据单个标志的值转移(2)按无符号整数比较转移(3)按带符号整数比较转移例子:程序的机器级表示与执行int sum(int a[ ], unsigned len) {int i,sum = 0;for (i = 0; i <= len–1; i++) sum += a[i]; return sum;}当参数len为0时,返回值应该是0,但是在机器上执行时,却发生了存储器访问异常。
IA-32常用指令类型(1)传送指令–通用数据传送指令MOV:一般传送,包括mov b、mov w和mov l等MOVS:符号扩展传送,如mov sbw、mov swl等MOVZ:零扩展传送,如mov zwl、mov zbl等XCHG:数据交换PUSH/POP:入栈/出栈,如push l,push w,pop l,pop w等–地址传送指令LEA:加载有效地址,如lea l(%edx,%eax), %eax”的功能为R[eax]←R[edx]+R[eax],执行前,若R[edx]=i,R[eax]=j,则指令执行后,R[eax]=i+j–输入输出指令IN和OUT:I/O端口与寄存器之间的交换–标志传送指令PUSHF、POPF:将EFLAG压栈,或将栈顶内容送EFLAG栈底新栈顶栈底栈顶•栈(Stack)是一种采用“先进后出”方式进行访问的一块存储区,用于嵌套过程调用。
从高地址向低地址增长•“栈”不等于“堆栈”(由“堆”和“栈”组成)R[sp]←R[sp]-2、M[R[sp]]←R[ax]为什么AL在栈顶?小端方式!执行前执行后栈底新栈顶栈底栈顶•栈(Stack)是一种采用“先进后出”方式进行访问的一块存储区,用于嵌套过程调用。
从高地址向低地址增长R[ax]←M[R[sp]]、[sp]←R[sp]+2执行前执行后原栈顶处的数据送AX080483d4<add>: 80483d4: 55push %ebp80483d5: 89 e5mov %esp, %ebp 80483d7: 83 ec 10 sub $0x10, %esp 80483da: 8b 45 0c mov 0xc(%ebp), %eax 80483dd: 8b 55 08 mov 0x8(%ebp), %edx 80483e0: 8d 04 02 lea (%edx,%eax,1), %eax80483e3: 89 45 fc mov %eax, -0x4(%ebp)80483e6: 8b 45 fc mov -0x4(%ebp), %eax 80483e9: c9 leave 80483ea:c3 ret“objdump -d test” 结果add函数中有哪些传送指令?每一条传送指令的功能是什么?R[esp]←R[esp]-4;M[R[esp]]←R[ebp]R[ebp]←R[esp]R[eax]←M[R[ebp]+12]R[edx]←M[R[ebp]+8]R[eax]←R[edx]+R[eax]M[R[ebp]-4]]←R[eax]R[eax]←M[R[ebp]-4]]指令的功能用RTL 描述080483d4<add>: 80483d4: 55push %ebp 80483d5: 89 e5mov %esp, %ebp 80483d7: 83 ec 10 sub $0x10, %esp80483da: 8b 45 0c mov 0xc(%ebp), %eax 80483dd: 8b 55 08 mov 0x8(%ebp), %edx 80483e0: 8d 04 02 lea (%edx,%eax,1), %eax 80483e3: 89 45 fc mov %eax, -0x4(%ebp)80483e6: 8b 45 fc mov -0x4(%ebp), %eax 80483e9: c9 leave 80483ea: c3 retadd 函数从80483d4开始!“objdump -d test” 结果执行add时,起始EIP=?EIP ←0x80483d4程序的执行过程如何?周而复始执行指令!指令如何执行?根据EIP取指令指令译码取操作数指令执行回写结果修改EIP的值取并执行指令OP举例控制器A L U标志寄存器地址数据控制GPRs017bfff002080483d680483d580483d4080483d4<add>: 80483d4: 55push %ebp80483d5: 89 e5mov %esp, %ebp 89e5EBP ESPEIPbfff0020bfff0000bfff000080483d480483d45589e583Rd5589e58355MDR5589e58380483d4S1:取指令IR5589e583RdS2:指令译码S3:指令执行MARbeeefffc5545控制器A L U标志寄存器地址数据控制GPRs017bfff002080483d680483d580483d4080483d4<add>: 80483d4: 55push %ebp80483d5: 89 e5mov %esp, %ebp 5589e5EBP ESPEIPbfff0020bfff000080483d455MDR80483d4S1:取指令IRS2:指令译码S3:指令执行MARbeeefffc45bfff0000控制器A L U标志寄存器地址数据控制GPRs017bfff002080483d680483d580483d4080483d4<add>: 80483d4: 55push %ebp80483d5: 89 e5mov %esp, %ebp 5589e5EBP ESPEIPbfff0020bfff000080483d455MDR80483d4S1:取指令IRS2:指令译码S3:指令执行beeefffc MARbeeefffc45控制器A L U标志寄存器地址数据控制GPRs017bfff002080483d680483d580483d4080483d4<add>: 80483d4: 55push %ebp80483d5: 89 e5mov %esp, %ebp 5589e5EBP ESPEIPbfff0020bfff000080483d455MDRS1:取指令IRS2:指令译码S3:指令执行beeefffc MARbeeefffcbeeefffc54控制器A L U标志寄存器地址数据控制GPRs017bfff002080483d680483d580483d4080483d4<add>: 80483d4: 55push %ebp80483d5: 89 e5mov %esp, %ebp 5589e5EBP ESPEIPbfff0020bfff000080483d4Wr55MDRS1:取指令IRWrS2:指令译码S3:指令执行beeefffc MARbeeefffcbeeefffcbfff0020bfff0020beeefffc45控制器A L U标志寄存器地址数据控制GPRs017bfff002080483d680483d580483d4080483d4<add>: 80483d4: 55push %ebp80483d5: 89 e5mov %esp, %ebp 5589e5EBP ESP EIPbfff0020bfff0000Wr55MDRS1:取指令IRWrS2:指令译码S3:指令执行beeefffc MARbeeefffcbeeefffc bfff0020bfff0020beeefffc2000ff bf 80483d445指令执行过程控制器A L U标志寄存器地址数据控制GPRs017bfff002080483d680483d580483d4080483d4<add>: 80483d4: 55push %ebp80483d5: 89 e5mov %esp, %ebp 5589e5EBP ESPEIPbfff0020bfff000080483d555MDRS1:取指令IRS2:指令译码S3:指令执行、EIP增量beeefffc MARbeeefffcbeeefffcbfff0020bfff0020beeefffc2000ff bf 开始执行下一条指令45WrWr传送指令举例将以下Intel格式指令转换为AT&T格式指令,并说明功能。
一、单选题1、以下关于x86实地址模式下异常/中断机制的叙述中,错误的是()。
A.中断向量表固定在0~3FFH的内存区域B.中断服务程序首地址占8个字节C.中断向量地址为中断类型号乘以4D.采用向量中断方式识别中断源正确答案:B解析: B、实地址模式下,每个中断向量占4个字节,由16位段地址和16位段内偏移量组成,通过对段地址左移4位然后加上段内偏移量,以得到20位的中断服务程序首地址。
2、以下关于x86系统启动过程的叙述中,错误的是()。
A.BIOS程序在主存中设置中断向量表B.进入保护模式后中断向量表中被填入新的中断向量C.与输入/输出相关的操作通过执行int指令由中断服务程序实现D.开机后系统首先在实地址模式下工作正确答案:B解析: B、系统启动结束时进入保护模式,此时,不再使用主存0~3FFH区域内的中断向量表,而是通过专门的中断描述符表来获得中断服务程序或异常处理程序的入口地址。
3、以下关于IA-32的异常/中断机制的叙述中,错误的是()。
A.在实地址模式下使用中断向量表保存异常处理程序和中断服务程序的首地址B.在保护模式下通过中断描述符表获取异常处理程序和中断服务程序的首地址C.中断向量表和中断描述符表中都有256个表项,每个表项都占8个字节D.最多可以有256种异常和中断类型,每种类型有一个中断号i(0≤i≤255)正确答案:C解析: C、实地址模式下,每个中断向量表的表项占4个字节,由16位段地址和16位段内偏移量组成。
4、以下选项中,不属于中断描述符表中表项内容的是()。
A.调用门描述符B.任务门描述符C.陷阱门描述符D.中断门描述符正确答案:A5、以下关于IA-32的中断门描述符的叙述中,错误的是()。
A.包含对应中断服务程序首地址(段选择符和偏移地址)B.包含存在位(字段P),用于表示对应中断类型是否存在C.包含DPL字段,用于表示访问本段时的CPL所要求的最低特权级D.每个中断门描述符占64位,与一个中断类型号对应解析: B、存在位P用于表示对应段(即异常处理程序或中断服务程序所在的段,通常就是指内核代码段)是否存在,而不是表示对应中断类型是否存在。
IA-32指令简表IA-32指令共有10个部分:一般用途指令、x87浮点运算处理单元指令、x87浮点运算处理单元和SIMD状态管理指令、MMX指令、SSE指令、SSE2指令、SSE3指令、系统指令、64位模式指令、虚拟机扩展。
下表显示了各IA-32构架CPU支持各部分指令的情况:1. 一般用途指令一般用途指令执行基本的数据移动、算术运算、逻辑运算、程序流程和字符串操作,这些操作通常被程序员用来写运行于IA-32处理器上的应用程序和系统程序。
这些指令可以操作在内存中、通用寄存器中和标志寄存器中的数据,也可以是存储于内存、通用寄存器和段寄存器中的地址信息。
现代微机原理与接口技术·2·附录B IA-32指令简表·3·现代微机原理与接口技术·4·附录B IA-32指令简表·5··6·现代微机原理与接口技术2. x87浮点运算处理单元指令附录B IA-32指令简表·7·现代微机原理与接口技术·8·3. x87浮点运算处理单元和SIMD 状态管理指令以下为两个基于IA-32结构Pentium II 系列处理器的状态管理指令:4. MMX 指令四项扩展指令集被引入IA-32结构,使得IA-32处理器能够执行SIMD 操作。
这四项扩展分别是MMX 技术、SSE 指令、SSE2指令和SSE3指令。
MMX 指令可处理存储于内存、MMX 寄存器和通用寄存器中的打包的字节、字、双字或四字的整数操作数。
MMX 指令只能在支持附录B IA-32指令简表·9·现代微机原理与接口技术·10·5. SSE指令SSE指令代表了和MMX技术一起介绍的SIMD执行模式的一个扩展。
SSE指令只能在支持SSE的IA-32处理器上执行。
SSE指令可分为四个部分:5.1 SSE SIMD单精度浮点指令这些指令可以处理存储于MMX寄存器和内存中的打包的分等级单精度浮点数据。
高级语言源程序和目标机器代码的实验总结一、实验目的1.掌握高级语言源程序和目标机器代码的不同表示及其相互转换。
2.深刻理解高级语言和机器语言之间的关系。
3.掌握子程序设计的思想、方法及上机调试过程。
4.理解中断服务子程序的执行过程。
二、实验准备知识1.IA-32中过程调用和返回指令的格式和功能。
2.子程序设计的思想和方法(1)子程序是功能相对独立的程序段,它可以实现源程序的模块化,简化源程序结构,提高编程效率(2)子程序定义:利用过程伪指令PROC和ENDP,格式如下:过程名PROC[NEAR|FAR]……;过程体过程名ENDP其中:可选的参数指定过程的调用属性。
没有指定过程属性,则采用默认属性NEAR。
NEAR属性:段内近调用,子程序只能被相同代码段的其他程序调用FAR属性:段间远调用,子程序可以被相同或不同代码段的程序调用(3)主程序(调用程序)调用子程序(被调用程序):利用CALL指令(4)子程序返回主程序:利用RET指令(5)保护现场:子程序开始处应该保护子程序中使用的寄存器(通常利用堆栈),子程序返回前相应进行恢复。
(6)子程序中对堆栈的压入和弹出操作通常成对使用,以保持堆栈的平衡。
(7)子程序允许嵌套和递归(8)处理好子程序与主程序之间的参数传递问题:利用寄存器、内存缓冲区及堆栈。
3.过程调用的执行步骤(假设P为调用者,Q为被调用者):(1)P保存现场(必要时);(2)将入口参数(实参)放到Q能访问到的地方;(3)P保存返回地址,然后将控制转移到Q;(4)Q保存P的现场,并为自己的非静态局部变量分配空间;(5)执行Q的过程体(函数体);(6)Q恢复P的现场,释放局部变量空间;(7)Q取出返回地址,将控制转移到P。
4.Linux常用命令以及GCC编译器的使用命令。
三、实验性质本实验为验证性实验。
四、实验学时本实验学时为4学时。
五、实验内容及步骤1.用C语言编写一个完整的源程序,实现main函数调用一个子函数的功能。
IA-32指令系统类型IA-32中的传送指令IA-32常⽤指令类型(1)传送指令– 通⽤数据传送指令MOV:⼀般传送,包括movb、movw和movl等MOVS:符号扩展传送,如movsbw、movswl等MOVZ:零扩展传送,如movzwl、movzbl等XCHG:数据交换PUSH/POP:⼊栈/出栈,如pushl,pushw,popl,popw等–地址传送指令LEA:加载有效地址,如leal (%edx,%eax), %eax”的功能为R[eax]←R[edx]+R[eax],执⾏前,若R[edx]=i,R[eax]=j,则指令执⾏后,R[eax]=i+j – 输⼊输出指令IN和OUT:I/O端⼝与寄存器之间的交换– 标志传送指令PUSHF、POPF:将EFLAG压栈,或将栈顶内容送EFLAG“⼊栈”(pushw %ax)“出栈” (popw %ax)程序由指令序列组成功能:R[esp]← R[esp]-4,M[R[esp]] ←R[ebp]的实现原理执⾏下⼀个指令IA-32中的定点算术运算指令(2)定点算术运算指令– 加 / 减运算(影响标志、不区分⽆/带符号)ADD:加,包括addb、addw、addl等SUB:减,包括subb、subw、subl等– 增1 / 减1运算(影响除CF以外的标志、不区分⽆/带符号)INC:加,包括incb、incw、incl等DEC:减,包括decb、decw、decl等– 取负运算(影响标志、若对0取负,则结果为0且CF清0,否则CF置1) NEG:取负,包括negb、negw、negl等– ⽐较运算(做减法得到标志、不区分⽆/带符号)CMP:⽐较,包括cmpb、cmpw、cmpl等– 乘 / 除运算(不影响标志、区分⽆/带符号)MUL / IMUL:⽆符号乘 / 带符号乘DIV/ IDIV:带⽆符号除 / 带符号除算数运算IA-32的寄存器组织功能:R[eax]← R[edx]+R[eax]*1功能:R[eax]← R[edx]+R[eax]*1 (执⾏后)定点加法指令举例假设 R[ax]=FFFAH,R[bx]=FFF0H,则执⾏以下指令后“addw %bx, %ax”AX、BX中的内容各是什么?标志CF、OF、ZF、SF各是什么?要求分别将操作数作为⽆符号数和带符号整数解释并验证指令执⾏结果。
汇编学习笔记(4)-伪指令(MASM)前⾔ 编写汇编代码的时候会使⽤到两种语句,⼀种就是前⾯介绍的汇编指令⼜CPU提供功能⽀持,另⼀种呢叫做伪指令,伪指令是由汇编的编译器提供⽀持。
所以伪指令的运⾏结果都必须实在编译的时候就能确定的,下⾯介绍的就是伪指令了。
注意接下来介绍的伪指令都是基于MASM汇编编译器,⽐较常⽤的还有NASM 它的语法以后有机会介绍数值表达式 数值表达式不是汇编指令,表达式的值是在汇编代码的汇编过程中就由汇编编译器计算出结果⽽写到⼆进制程序中了,并不是在程序运⾏的过程中才计算的 (1) 常数表达式 常数就是直接的数字,直接写数字默认表⽰10进制数,也可以⽤符号指定为其他进制 D = ⼗进制 ; MOV AL, 1234D B = ⼆进制 ; MOV AL, 0101B H = ⼗六进制 ; MOV AL, 0FFFFH , 注意常数必须是数字开头不能是字母开头,如果16进制数第⼀个数字是字母的话就要补⼀个0在前⾯ Q = ⼋进制 ; MOV AL, 123Q 因为在程序中字母也是数字,所以其实也可以直接将字母或者字符串当成数字,⽐如 MOV AL, 'a' MOV AX,"ab" ; 双引号和单引号都是可以使⽤的 (2) 算数运算符 就是简单的正(+) 负(-) 加(+) 减(-) 乘(*) 除(/) 模(mod) mov ax, 100+200 mov ax, 100/2 (3) 关系运算符 等于(EQ) 不等(NE) ⼤于(GT) ⼩于(LT) ⼤于等于(GE) ⼩于等于(LE) 如果等式成⽴则实际的值为0FFFF就是补码表⽰的-1, 如果关系不成⽴那么结果就是0 mov ax, 123 gt 234 mov ax, 1234+5 lt 1235 (4) 逻辑运算 与(and) 或(or) ⾮(not) 异或(xor) 左位移(shl) 右位移(shr) mov ax, 1 shl 3 mov al, 3 and 47 (5) 其他操作符 HIGH LOW WIDTH MASK HIGH 表⽰取数据的⾼⼋位 LOW 表⽰取数据的低⼋位地址表达式 地址表达式所表⽰的是存储器操作数的地址。
IA-32的向量中断方式•有256种不同类型的异常和中断•每个异常和中断都有唯一编号,称之为中断类型号(也称向量号)。
如类型0为“除法错”,类型2为“NMI中断”,类型14为“缺页”•每个异常和中断有与其对应的异常处理程序或中断服务程序,其入口地址放在一个专门的中断向量表或中断描述符表中。
•前32个类型(0~31)保留给CPU使用,剩余的由用户自行定义(这里的用户指机器硬件的用户,即操作系统)•通过执行INT n(指令第二字节给出中断类型号n,n=32~255)使CPU自动转到OS给出的中断服务程序执行•实模式下,用中断向量表描述•保护模式下,用中断描述符表描述回顾:中断的分类•Intel将中断分成可屏蔽中断(maskable interrupt)和不可屏蔽中断(nonmaskable interrupt,NMI)。
–可屏蔽中断:通过INTR 向CPU请求,可通过设置屏蔽字来屏蔽请求,若中断请求被屏蔽,则不会被送到CPU。
–不可屏蔽中断:非常紧急的硬件故障,如:电源掉电,硬件线路故障等。
通过NMI 向CPU请求。
一旦产生,就被立即送CPU,以便快速处理。
这种情况下,中断服务程序会尽快保存系统重要信息,然后在屏幕上显示相应的消息或直接重启系统。
CPU 中断控制器NMIINTRIA-32的中断类型•用户自定义类型号为32~255,部分用于可屏蔽中断,部分用于软中断•可屏蔽中断通过CPU的INTR 引脚向CPU发出中断请求•软中断指令INT n 被设定为一种陷阱异常,例如,Linux通过int $0x80指令将128号设定为系统调用,而Windows通过int $0x2e指令将46号设定为系统调用。
回顾:用“系统思维”分析问题代码段一:int a = 0x80000000;int b = a / -1;printf("%d\n", b);运行结果为-2147483648代码段二:int a = 0x80000000;int b = -1;int c = a / b;printf("%d\n", c);运行结果为“Floating point exception”,显然CPU检测到了溢出异常objdump反汇编代码, 得知除以-1 被优化成取负指令neg, 故未发生除法溢出为什么两者结果不同!a/b用除法指令IDIV实现,但它不生成OF 标志,那么如何判断溢出异常的呢?实际上是“除法错”异常#DE(类型0)Linux中,对#DE类型发SIGFPE信号实地址模式下的中断向量表实地址模式(Real Mode)是Intel为80286及其之后的处理器提供的一种8086兼容模式。
TITLE 伪指令将整行标为注释
INCLUDE伪指令后跟文件名,指定从某一文件中拷贝必需的信息
.code伪指令用来标记代码段的开始,程序中所有可执行语句都放于此处
PROC伪指令允许声明一个过程并且附带参数列表,其使用格式为
label PROC { [,parameter_1] }
每个参数的格式为参数名:类型
ENDP伪指令标识子程序的结束
END伪指令标明该行是汇编程序的最后一行,编译器将忽略该行后面的所有内容
.386伪指令指出了程序要求的最低CPU(Intel386)
.MODEL伪指令指示编译器哪种模式程序生成代码
STDCALL伪指令允许程序调用MS-Windows函数
PROTO伪指令声明了程序使用的子程序
INVOKE是一个用于调用过程或函数的汇编伪指令
BYTE,SBYTE等类似的,用于定义数据的伪指令。
早期还是用DB,但DB无法区分是否有符号DUP操作使用一个常量表达式作为计数器来重复分配存储空间。
即使用DUP可以一次分配多个空间,并且决定对此空间进行全部初始化或全部都不初始化
.DAT A伪指令可用于声明未初始化数据,它在定义大块的未初始化数据时非常有用,因为它可以缩小编译后的程序尺寸
=(等号伪指令)将符号名和整数表达式联系起来。
以=定义的符号可重定义任意多次EQU伪指令将符号名和整数表达式或任意文本联系起来。
三种使用格式
name EQU expression 有效的整数表达式
name EQU symbol 已被=或EQU定义的符号
name EQU <text>
用EQU定义的符号不能在同一源代码文件中重复定义
TEXTEQU伪指令可用来创建文本宏(text macro)
OFFSET操作符返回一个变量相对于其所在段开始的偏移,即返回数据标号的偏移地址PTR操作符允许重载变量的默认尺寸
TYPE操作符返回数组中每个元素的大小(以字节计算)
LENGTHOF操作符返回数组内元素的数目。
注意对在DUP的嵌套使用和换行的情况SIZEOF操作符返回数组初始化时占用的字节数。
即返回LENGTHOF和TYPE返回值的乘积ALLIGN伪指令将变量的位置按字节、字、双字边界对齐ALLIGN 1|2|4。
数据对齐可能会浪费一部分存储空间,但CPU处理存储在偶数地址的数据比处理存储在奇数地址的
数据要快
LABEL伪指令允许插入一个标号并赋予其尺寸属性而无需分配任何实际的存储空间
JMP指令导致向代码段内的目标地址做无条件转移
LOOP指令提供了一种将程序块重复执行特定次数的简单方法。
ECX被自动用作计数器。
并且注意LOOP指令的执行是分两步:首先,ECX减1,接着与0比较。
根据比较的
结果来决定是否发生跳转
.NOLIST伪指令禁止编译器在创建的列表文件中显示这些源文件行。
.LIST伪指令允许显示后面文件行
USES与PROC伪指令配套使用的USES操作符允许列出被过程修改的所有寄存器,它只是编译器做两件事情:首先,在过程的开始出生成PUSH指令在堆栈上保存寄存器;其
次,在过程的结束处生成POP指令恢复这些寄存器的值。
LOCAL伪指令在过程内声明一个或多个命名局部变量,语句必须紧跟在PROC伪指令所在行
之后
LOCAL 变量列表
每个变量定义的格式如下,标号:类型
PROTO伪指令为一个已存在的过程创建过程原型。
原型声明了过程的名字和参数列表,它允许一个过程在被定义之前就可以在其他地方被调用。
很类似C语言里面的函数声
明。
使用PROTO创建过程原型时,去掉原过程中的寄存器列表,但要给出相应的
参数列表。
它的作用类似于C语言中的函数声明
.MODEL伪指令可确定所用的内存模式。
它决定程序的几个重要特性:内存模式类型、过程命名方案和参数传递约定。
在IA-32中可以使用的内存模式有:
tiny,small,medium,compact,large,huge,flat。
它们之间的主要区别在于去代码段数据
段之间数量的区别,以及放置区别。
.MODEL伪指令的格式是:
.MODEL 内存模式[,模式选项]
模式选项可包含语言关键字或堆栈的远近选项。
语言关键字决定了过程和公共符号
的调用约定及命名约定。
在这里我们着重讲解
.MODEL falt,C
.MODEL falt,stdcall
.MODEL falt,pasca
.MODEL falt,C指定过程以反向顺序(从右往左)在堆栈上压入过程参数,在过
程调用之后堆栈参数的移出上,ESP要被加上一个常量,将堆栈指针重设为参数压
入之前的值
.MODEL falt,stdcall指定过程按照从右到左的顺序压入参数,在过程调用之后的
堆栈参数移除时,要求过程在RET指令后面必须提供一个常量操作数,RET指令
在堆栈上弹出返回地址之后把该常量同ESP相加
.MODEL falt,pasca指定过程按从左往右的顺序在堆栈上压入参数,在过程调用
结束后的堆栈参数移除上与.MODEL falt,stdcall相同
OPTION PROC:PRIVATE伪指令放在模块文件头部,使得模块中的所有过程都变成私有PUBLIC 伪指令指定任何想要导出的过程,使用例如:PUBLIC sub1,sub2,sub3
EXTERN伪指令用于在调用当前模块之外的过程时使用,它可以指定外部过程的名字和外部过程堆栈框架的大小。
ALLIGN伪指令设置下一个域或变量的地址对齐方式。
对齐,是为了取得最佳的I/O性能,结构的成员应该根据其数据类型进行对齐,否则CPU在访问结构的成员时就要花费
更多的时间ALLIGN datatype。