为什么SHL和SAL相同

2024-03-06 19:38
文章标签 相同 sal shl

本文主要是介绍为什么SHL和SAL相同,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

    • 1 移位指令简介
      • 1.1 左移
      • 1.2 右移
    • 2 为什么两者会有不同呢?
      • 2.1 对于左移操作
      • 2.2 对于右移操作
      • 2.3 这样就能说明SHL和SAL是相同的吗?
        • 2.3.1 对于左移操作:
        • 2.3.2 对于右移操作
    • 3 其他

1 移位指令简介

1.1 左移

SAL		OPD, OPS               ; 算术左移,操作数左移,最低位补0,最高位进CF
SHL		OPD, OPS               ; 逻辑左移,操作数左移,最低位补0,最高位进CF

1.2 右移

SAR		OPD, OPS			   ; 算术右移,操作数右移,最高位不变,最低位进CF
SHR		OPD, OPS			   ; 逻辑右移,操作数右移,最高位补0,最低位进CF

我们会发现,左移指令 SALSHL是进行同样的操作
而右移指令 SARSHR 进行的是不同的操作

2 为什么两者会有不同呢?

先来看一段C语言代码:

#include <stdio.h>
int main(void)
{char n = 64;unsigned char m = 64;n = n << 1;m = m << 1;printf("n = %d\n", n);printf("m = %d", m);return 0;
}

运行结果:

n = -128
m = 128

我们知道C语言中移位操作常用于快速乘除(左移为乘,右移为除)
但是64为什么左移1(*2)后变成了一个负数呢?
十进制数64的二进制码为01000000,当它左移后变成10000000
n为一个有符号数,所以10000000就是 -128
m为一个无符号数,所以10000000就是128

2.1 对于左移操作

可以发现,左移操作相当于乘法操作,它是会让操作数变大的,也就是说,它随时存在着溢出的风险

若左移操作保留符号位的话,那么左移会出现越来越小的情况,但是你的本意是让这个数变大这里写图片描述

最后却发现左移后的数变小了,为了规避这种溢出带来的问题,统一了左移操作,也就是说,在左移操作中,寄存器只负责储存这个数(不管是否合乎人意,它只要是个数就行),若没有溢出的时候,则原样存储。所以说左移操作是会改变符号位的(也就是上述C语言的例子)。

2.2 对于右移操作

我们知道右移操作的算术操作是除法,那么在计算机中是肯定让这个数变小的,所以不存在溢出的风险,那么设计者就把是否保留符号位的权力交给了程序编写人员,所以 SARSHR 是两个不同的操作

2.3 这样就能说明SHL和SAL是相同的吗?

2.3.1 对于左移操作:

这里写图片描述

这里写图片描述

可以明显发现,两者对应操作的机器码是完全相同的,由此可以断定, SHLSAL是不同名的同种操作,下面再来看右移操作。

2.3.2 对于右移操作

这里写图片描述

这里写图片描述

可以发现他们对应的机器码是不同的,所以 SARSHR是两个不同的操作

3 其他

关于这两者,维基百科提到:

Logical shifts are best used with unsigned numbers
逻辑移位最好用于无符号数

In an arithmetic shift, the spaces are filled in such a way to preserve the sign of the number being slid. For this reason, arithmetic shifts are better suited for signed numbers in two’s complement format
在算术移位中,移位空间被补0或者保留高位(即符号位)的方式处理,因此,算术移位操作更适用于两个有符号数的补码操作


参考:
x86 Assembly - wikibooks
SAL/SAR/SHL/SHR - 移位操作码表


这篇关于为什么SHL和SAL相同的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/781104

相关文章

相同的生命周期

1.保证相同的生命周期 bool GameOverLayer::init()   {       if (CCLayerColor::initWithColor(ccc4(0, 255, 0, 255))){              _label = CCLabelTTF::create("word", "Artial", 40);              CCSize size = CC

TCP 和 UDP 可以同时绑定相同的端口吗?

在网络编程中,TCP和UDP都可以绑定到同一个端口上进行通信。TCP和UDP是OSI模型中的传输层协议,它们分别使用不同的端口号来区分不同的应用程序或服务。 TCP(Transmission Control Protocol)提供了面向连接的、可靠的传输服务,它使用三次握手建立连接,并通过确认、重传、窗口控制等机制保证数据的可靠传输。 UDP(User Datagram Protocol)提供

在MySQL中基本认为schema和数据库相同,也就是说schema的名称和数据库的实例的名称相同,一个数据库有一个schema。

在SQL环境下,schema就是数据库对象的集合,所谓的数据库对象也就是常说的表,索引,视图,存储过程等。 在schema之上的,就是数据库的实例,也就是通常create databases获得的东西。也就是说一个schema 实例 可以有多个schema, 可以给不同的用户创建不同的schema,并且他们都是在同一数据库实例下面。 在MySQL中基本认为schema和数据库相同,也就是

诺瓦星云入职认知能力SHL测验Verify职业性格问卷OPQ可搜索带解析求职题库

欢迎您开启诺瓦星云的求职旅程 恭喜您进入测评环节,接下来您需要作答两个测验,分别是职业性格问卷OPQ和认知能力测验Verify,总共用时大约1小时,祝您作答顺利! 【华东同舟求职】由资深各行业从业者建立的一站式人才服务网络平台,现阶段目标是“提升全市场各行业岗位信息的流动性和透明度”。我们接受众多行业机构的直接委托发布,并尽力通过各种方法搜寻高价值岗位信息。事实上,我们

opencascade 判断两个TopoDS-Shape 是否相同

我们使用opencascade提取实体时,经常会出现实体重复,例如从正方体实体中提取Edge,我们会发现能提取出24个Edge,但正方体只有12条边,这是因为每条边有两个面,进行了重复提取。         如果我们想去掉重复的边,可以通过判断两条边是否相等实现(实际上不需要通过此方法),但是通过 == 运算符进行判断通常是无效的,即两条重合的边在运算符 == 下会被判定为否,那

ArcGIS查找相同图斑、删除重复图斑

​ 点击下方全系列课程学习 点击学习—>ArcGIS全系列实战视频教程——9个单一课程组合+系列直播回放 点击学习——>遥感影像综合处理4大遥感软件ArcGIS+ENVI+Erdas+eCognition 这次是上次 今天分享一下,很重要却被大家忽略的两个工具      这两个工具不仅可以找出属性上异同,也能够找出空间几何上的不同。         报告要素类或表中

来自Google Research:宽模型和深模型学到的是相同的东西吗?

点击上方“AI公园”,关注公众号,选择加“星标“或“置顶” 因公众号更改了推送规则,记得读完点“在看”~下次AI公园的新文章就能及时出现在您的订阅列表中 作者:Thao Nguyen, AI Resident, Google Research 编译:ronghuaiyang 导读 提高模型容量可以从宽度和深度着手,但是,宽模型和深模型学到的是相同的东西吗?用各自适用的场景吗? 论文链接:h

JAXB 不同子类使用相同的元素名称

要求云主机、带宽、云硬盘配置的元素名称都为itemConfig,并且能根据对应的类生成正确的元素 。 使用@XmlMixed 和 @XmlElementRefs 可实现 //订单选项配置@XmlTransientpublic class OrderItemConfig {}   //订单云主机配置@XmlRootElement(name = "itemConfig")public

leetcode100相同的树

思路 主要是递归,判断终止条件 代码 public boolean isSameTree(TreeNode p, TreeNode q) {if (p == null && q == null){//全为空return true;}if (p==null||q==null){ //有一个nullreturn false;}if (p.val != q.val){return false;}r

PHP关于foreach按引用循环,最后一个值和前一个相同的问题

执行代码: <?php $a=[4,5,6,7]; foreach ($a as $k=>&$v){ var_dump($a); echo "<br/>"; } echo "<br/>"; foreach ($a as $k=>$v){     print_r($a);     echo "<br/>"; } echo "<br/>"; print_r($a);   执行过程和结果: a