SS, SP, BP 三个寄存器

本文详细解析了SS、SP与BP三个寄存器的功能与应用场景,特别是BP寄存器在函数调用过程中的作用。通过具体示例说明了如何利用这些寄存器进行堆栈管理和函数参数传递。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 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://hi.baidu.com/donghongchen/blog/item/486ac300e96dc4027bec2c80.html


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只是存取某时刻的栈顶指针,以方便对栈的操作,如获取函数参数、局部变量等

### Outlook 认证失败解决方案 对于Outlook认证失败的问题,通常涉及配置错误或权限不足。以下是详细的排查和解决办法: #### 1. 配置AD FS声明规则 如果使用的是企业环境下的Exchange服务,并依赖于AD FS (Active Directory Federation Services) 进行单点登录,则需确保AD FS声明规则设置正确。具体来说,X-MS-Client-Application字段应包含正确的应用程序名称而非`Microsoft.Exchange.PopImap`,因为后者可能导致POP/IMAP客户端无法完成身份验证过程[^1]。 #### 2. 授权第三方应用访问 针对个人邮箱账户(如163邮箱),即使用户名密码无误也可能因未授予相应权限而遭遇认证障碍。此时应当前往目标邮箱的安全中心开启SMTP服务并给予特定设备或程序必要的API调用许可。例如,在某些情况下需要为QQ邮箱这样的外部客户端提供特别授权才能成功连接至163邮箱服务器[^2]。 #### 3. 检查网络环境差异带来的影响 有时同样的代码逻辑在不同运行环境中表现各异。比如Spring Boot项目可能由于Kubernetes集群内部特殊的防火墙策略或是DNS解析问题造成邮件传输协议握手阶段出现问题,进而触发`javax.mail.AuthenticationFailedException`异常。因此建议开发者仔细对比开发机与生产服务器之间的区别所在,必要时调整相关参数设定以适应实际部署场景的需求[^3]。 #### 4. 处理Google SMTP服务器的身份验证需求 当遇到类似于“530 5.5.1 Authentication Required”的提示信息时,这表明当前会话缺少有效的OAuth2令牌或者其他形式的有效凭证。如果是Gmail用户试图通过编程方式发送电子邮件,则务必按照官方文档指引启用两步验证机制以及创建专门的应用专用密码;而对于G Suite管理员而言则需要注意区分普通Gmail账号同付费版本间存在的功能限制——前者不具备管理后台入口[^4]。 ```java // JavaMail API示例:处理身份验证请求 Properties props = new Properties(); props.put("mail.smtp.auth", "true"); props.put("mail.smtp.starttls.enable", "true"); // 启用TLS加密通信 Session session = Session.getInstance(props, new Authenticator() { protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication(username, password); } }); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值