寄存器的分类  | 寄存器  | 主 要 用 途  | |
通  用 寄  存  器  | 数据  寄存器  | AX  | 乘、除运算,字的输入输出,中间结果的缓存  | 
AL  | 字节的乘、除运算,字节的输入输出,十进制算术运算  | ||
AH  | 字节的乘、除运算,存放中断的功能号  | ||
BX  | 存储器指针  | ||
CX  | 串操作、循环控制的计数器  | ||
CL  | 移位操作的计数器  | ||
DX  | 字的乘、除运算,间接的输入输出  | ||
变址 寄存器  | SI  | 存储器指针、串指令中的源操作数指针  | |
DI  | 存储器指针、串指令中的目的操作数指针  | ||
变址 寄存器  | BP  | 存储器指针、存取堆栈的指针  | |
SP  | 堆栈的栈顶指针  | ||
指令指针  | IP/EIP  | [size=9.0000pt]   | |
标志位寄存器  | Flag/EFlag  | [size=9.0000pt]   | |
32位  CPU的 段寄存器  | 16位CPU的  段寄存器  | ES  |  附加段寄存器  | 
CS  |  代码段寄存器  | ||
SS  |  堆栈段寄存器  | ||
DS  |  数据段寄存器  | ||
新增加的 段寄存器  | FS  |  附加段寄存器  | |
GS  |  附加段寄存器  | ||
file:///C:\Users\ADMINI~1\AppData\Local\Temp\ksohtml6184\wps1.png  | 寄存器AX[size=9.0000pt]和AL通常称为累加器(Accumulator),用累加器进行的操作可能需要更少时间。累加器可用于乘、除、输入/输出等操作,它们的使用频率很高;  | 
file:///C:\Users\ADMINI~1\AppData\Local\Temp\ksohtml6184\wps2.png  | 寄存器BX称为基地址寄存器(Base Register)。它可作为存储器指针来使用;   | 
file:///C:\Users\ADMINI~1\AppData\Local\Temp\ksohtml6184\wps3.png  | 寄存器CX称为计数寄存器(Count Register)。在循环和字符串操作时,要用它来控制循环次数;在位操作中,当移多位时,要用CL来指明移位的位数;  | 
file:///C:\Users\ADMINI~1\AppData\Local\Temp\ksohtml6184\wps4.png  | 寄存器DX称为数据寄存器(Data Register)。在进行乘、除运算时,它可作为默认的操作数参与运算,也可用于存放I/O的端口地址。  | 
它们主要用于访问堆栈内的存储单元,并且规定:  | |
file:///C:\Users\ADMINI~1\AppData\Local\Temp\ksohtml6184\wps5.png  | BP为基指针(Base Pointer)寄存器,用它可直接存取堆栈中的数据;  | 
file:///C:\Users\ADMINI~1\AppData\Local\Temp\ksohtml6184\wps6.png  | SP为堆栈指针(Stack Pointer)寄存器,用它只可访问栈顶。  | 
CPU内部的段寄存器:  | |
file:///C:\Users\ADMINI~1\AppData\Local\Temp\ksohtml6184\wps7.png  | CS——代码段寄存器(Code Segment Register),其值为代码段的段值;  | 
file:///C:\Users\ADMINI~1\AppData\Local\Temp\ksohtml6184\wps8.png  | DS——数据段寄存器(Data Segment Register),其值为数据段的段值;  | 
file:///C:\Users\ADMINI~1\AppData\Local\Temp\ksohtml6184\wps9.png  | ES——附加段寄存器(Extra Segment Register),其值为附加数据段的段值;  | 
file:///C:\Users\ADMINI~1\AppData\Local\Temp\ksohtml6184\wps10.png  | SS——堆栈段寄存器(Stack Segment Register),其值为堆栈段的段值;  | 
file:///C:\Users\ADMINI~1\AppData\Local\Temp\ksohtml6184\wps11.png  | FS——附加段寄存器(Extra Segment Register),其值为附加数据段的段值;  | 
file:///C:\Users\ADMINI~1\AppData\Local\Temp\ksohtml6184\wps12.png  | GS——附加段寄存器(Extra Segment Register),其值为附加数据段的段值。  | 
实方式:  | 前4个段寄存器CS[size=9.0000pt]、DS[size=9.0000pt]、ES[size=9.0000pt]和SS与先前CPU中的所对应的段寄存器的含义完全一致,内存单元的逻辑地址仍为“段值:偏移量”的形式。为访问某内存段内的数据,必须使用该段寄存器和存储单元的偏移量。  | 
保护方式:  | 在此方式下,情况要复杂得多,装入段寄存器的不再是段值,而是称为“选择子”(Selector)的某个值。段寄存器的具体作用在此不作进一步介绍了,有兴趣的读者可参阅其它科技资料。  | 
AH  | 功 能  | 调用参数  | 返回参数 / 注释  | 
1  |  置光标类型  |   (CH)0―3 = 光标开始行[size=9.0000pt] (CL)0―3 = 光标结束行  | [size=9.0000pt]   | 
2  |  置光标位置  |   BH = 页号 [size=9.0000pt] DH = 行[size=9.0000pt] DL = 列  | [size=9.0000pt]   | 
3  |  读光标位置  |   BH = 页号  |  CH = 光标开始行[size=9.0000pt] CL = 光标结束行[size=9.0000pt] DH = 行[size=9.0000pt] DL = 列  | 
4  |  置显示页  |   AL = 显示页号  | [size=9.0000pt]   | 
5  |  屏幕初始化或上卷  | [size=9.0000pt]   | [size=9.0000pt]   | 
6  |  屏幕初始化或上卷  |   AL = 上卷行数 [size=9.0000pt] AL =0全屏幕为空白 [size=9.0000pt] BH = 卷入行属性[size=9.0000pt] CH = 左上角行号 [size=9.0000pt] CL = 左上角列号 [size=9.0000pt] DH = 右下角行号 [size=9.0000pt] DL = 右下角列号  | [size=9.0000pt]   | 
7  |  屏幕初始化或下卷  |   AL = 下卷行数[size=9.0000pt] AL = 0全屏幕为空白 [size=9.0000pt] BH = 卷入行属性[size=9.0000pt] CH = 左上角行号 [size=9.0000pt] CL = 左上角列号 [size=9.0000pt] DH = 右下角行号 [size=9.0000pt] DL = 右下角列号  | [size=9.0000pt]   | 
8  |  读光标位置的属性和字符  |   BH = 显示页  |  AH = 属性[size=9.0000pt] AL = 字符  | 
9  |  在光标位置显示字符及其属性  |   BH = 显示页[size=9.0000pt] AL = 字符[size=9.0000pt] BL = 属性[size=9.0000pt] CX = 字符重复次数  | [size=9.0000pt]   | 
A  |  在光标位置只显示字符  |   BH = 显示页[size=9.0000pt] AL = 字符 [size=9.0000pt] CX = 字符重复次数  | [size=9.0000pt]   | 
E  |  显示字符(光标前移)  |   AL = 字符[size=9.0000pt] BL = 前景色  |  光标跟随字符移动  | 
13  |  显示字符串  |   ES:BP = 串地址 [size=9.0000pt] CX = 串长度 [size=9.0000pt] DH, DL = 起始行列 [size=9.0000pt] BH = 页号[size=9.0000pt] AL = 0,BL = 属性 [size=9.0000pt] 串:Char,char,……,char[size=9.0000pt] AL = 1,BL = 属性 [size=9.0000pt] 串:Char,char,……,char [size=9.0000pt] AL = 2 [size=9.0000pt] 串:Char,attr,……,char,attr [size=9.0000pt] AL = 3 [size=9.0000pt] 串:Char,attr,……,char,attr  | [size=9.0000pt] [size=9.0000pt] [size=9.0000pt] [size=9.0000pt] 光标返回起始位置[size=9.0000pt] [size=9.0000pt] 光标跟随移动[size=9.0000pt] [size=9.0000pt] [size=9.0000pt] 光标返回起始位置[size=9.0000pt] [size=9.0000pt] [size=9.0000pt] 光标跟随串移动  | 
SS, SP, BP 三个寄存器 SS:存放栈的段地址; SP:堆栈寄存器SP(stack pointer)存放栈的偏移地址; BP: 基数指针寄存器BP(base pointer)是一个寄存器,它的用途有点特殊,是和堆栈指针SP联合使用的,作为SP校准使用的,只有在寻找堆栈里的数据和使用个别的寻址方式时候才能用到 比如说,堆栈中压入了很多数据或者地址,你肯定想通过SP来访问这些数据或者地址,但SP是要指向栈顶的,是不能随便乱改的,这时候你就需要使用BP,把SP的值传递给BP,通过BP来寻找堆栈里数据或者地址.一般除了保存数据外,可以作为指针寄存器用于存储器寻址,此时它默认搭配的段寄存器是SS-堆栈段寄存器.BP是16位的,再扩充16位就是EBP,用于32位编程环境的.一般高级语言的参数传递等等,转换为汇编后经常由BP/EBP来负责寻址\处理. SP,BP一般与段寄存器SS 联用,以确定堆栈寄存器中某一单元的地址,SP用以指示栈顶的偏移地址,而BP可 作为堆栈区中的一个基地址,用以确定在堆栈中的操作数地址。 (下面这个像Win32汇编中的) bp为基址寄存器,一般在函数中用来保存进入函数时的sp的栈顶基址 每次子函数调用时,系统在开始时都会保存这个两个指针并在函数结束时恢复sp和bp的值。像下面这样: 在函数进入时: push bp // 保存bp指针 mov bp,sp // 将sp指针传给bp,此时bp指向sp的基地址。 // 这个时候,如果该函数有参数,则[bp + 2*4]则是该子函数的第一个参数,[bp+3*4]则是该子函数的 第二个参数,以此类推,有多少个参数则[bp+(n-1)*4]。 ..... ..... 函数结束时: mov sp,bp // 将原sp指针传回给sp pop bp // 恢复原bp的值。 ret // 退出子函数 http://my.oschina.net/orion/blog/15879 下面是按调用约定__stdcall 调用函数test(int p1,int p2)的汇编代码 ;假设执行函数前堆栈指针ESP为NN push p2 ;参数2入栈, ESP -= 4h , ESP = NN - 4h push p1 ;参数1入栈, ESP -= 4h , ESP = NN - 8h call test ;压入返回地址 ESP -= 4h, ESP = NN - 0Ch (注意CALL指令会把返回地址压入堆栈) ;//进入函数内 { push ebp ;保护先前EBP指针, EBP入栈, ESP-=4h, ESP = NN - 10h mov ebp, esp ;设置EBP指针指向栈顶 NN-10h mov eax, dword ptr [ebp+0ch] ;ebp+0ch为NN-4h,即参数2的位置 这里可以看到了BP的作用了 mov ebx, dword ptr [ebp+08h] ;ebp+08h为NN-8h,即参数1的位置 这里可以看到了BP的作用了 ub esp, 8 ;局部变量所占空间ESP-=8, ESP = NN-18h (栈底的地址大)                                                       ;这里就是为局部变量申请空间. ... add esp, 8 ;释放局部变量, ESP+=8, ESP = NN-10h                                                       ;(假设在上面的指令中EBP没变的话, 直接MOV ESP, EBP即可达到堆栈平衡,                                                       ; 事实上也经常这么用) pop ebp ;出栈,恢复EBP, ESP+=4, ESP = NN-0Ch ret 8 ;ret返回,弹出返回地址,ESP+=4, ESP=NN-08h,                                                      ; 后面加操作数8为平衡堆栈,ESP+=8,ESP=NN, 恢复进入函数前的堆栈                                                      ; 为什么是8? 因为Test子函数有两个参数, 8就是对应了两个参数入栈时SP减少了8 } 原来ESP就是一直指向栈顶的指针,而EBP只是存取某时刻的栈顶指针,以方便对栈的操作,如获取函数参数、局部变量等  | 
| 欢迎光临 firemail (http://www.firemail.wang:8088/) | Powered by Discuz! X3 |