王爽的汇编语言,有这样一道题:

检测点2.2

  (2)  有一数据存放在内存20000H单元中,现给定段地址为SA,若想用偏移地址寻到此单元。则SA应满足的条件是:最小为         , 最大为         。

  提示,反过来思考一下,当段地址给定为多少,CPU无论怎么变化偏移地址都无法寻到20000H单元?

  我的思考过程是,关键是看“物理地址=段地址(SA)*10H+偏移地址(EA)”这句话,容易得到段地址=(物理地址-偏移地址)/10H(10H也可以写成16)。当偏移地址为最大时,能求得最小的段地址;否则求得最大的段地址。而偏移地址是16位的,也就是说寻址范围是0~FFFFH。那么,顺着这个想法很容易得到“答案”——当偏移地址为最大(FFFFH)时段地址最小;当偏移地址最小(0)时段地址最大。

  但是,经过计算发现,“段地址=(物理地址-偏移地址)/16”对应的式子“SA=(20000H-EA)/16”,其数学上等价的另一条分配律得到的式子“SA=20000H/16-EA/16”,在计算SA最大值的时候所计算的结果却不一样!(前者是20000H-FFFFH得到10001H,之后10001H除以10H,得到的结果是1000;后者是20000H/10H先得到2000H,再FFFFH/10H得到FFFH,最后2000H-FFFH,得到的结果是1001)

  为什么完全相等的两条数学运算,其结果竟然不同!

  先想一想*10H(*16)的本质:

  从一个例子来观察(后缀B表示二进制、后缀D表示十进制、后缀H表示十六进制):

       10B(  2D、  2H),左移1位

为      100B(  4D、  4H),左移1位

为    1000B(  8D、  8H),左移1位

为  10000B(16D、10H),左移1位

为100000B(32D、20H)

  得到      1) 10B左移1位,其十进制从2D变成4D,其十六进制从2H变成4H;      2) 10B左移4位,其十进制从2D变成32D,其十六进制从2H变成20H

  所以有以下的结论:    1) 一个数据的二进制左移1位,相当于其十进制乘上2,也相当于其十六进制乘上2;      2) 一个数据的二进制左移N位,相当于该数据乘以2的N次方

  所以,一个数据乘上10H(乘上16)其本质是该数据以二进制形式左移4位

  对应地,一个数据除以10H(除以16)其本质就是该数据以二进制形式右移4位

  

  回到这道题上面,为什么完全相同的两个数学式子,结果会不同?

  这就是因为题目这句话:段地址*10H必须是16的倍数。段地址SA为2000H,乘上10H(暂时称段地址*10H的结果为基础地址,并没有这个概念),本质上是以二进制形式左移4位(2的4次方,幂就是左移的位数),这在十六进制中表现为其末尾为0,所以其基础地址的末尾必为0,而不是20001H或20002H,而是20000H。

  接着,基础地址加上偏移地址就得到了物理地址,则基础地址=物理地址-偏移地址,即SA*16=20000H-EA

  如果EA取理论最大值FFFFH(因为偏移地址为4位,即可变化范围为0~164-1,十六进制为0~FFFFH),那么其基础地址为:20000H-FFFFH=10001H,可以发现这个基础地址是错误的。若要保证其基础地址必须为16的倍数(也就是其十六进制形式的末尾为0),那么偏移地址的最大值只能为FFF0H,这个FFF0H末尾的0是为了保证与基础地址20000H末尾的0对应,从而保证段地址*10H的结果是16的倍数

  而这两条数学式子:SA=(20000-EA)/16和SA=20000/16-EA/16,虽然从数学角度来说是相等的,但其本身表示的意义就不同了,前者先执行(20000-EA)运算,最大的问题就是无法保证其表示的意义——基础地址的末尾必为0;而先执行20000/16就能保证执行运算时先排除末尾的干扰,无论其末尾是什么,通过除以16(右移4位)得到了保护,最终能使得基础地址的末位为0不变

  

  所以这就是SA=(20000-EA)/16和SA=2000-EA/16运算结果不想等的原因

  正确的算法应该是SA=2000-EA/16才能排除算法的逻辑错误

  (这是我在学习汇编语言的过程中得到的心得写的第一篇笔记,如果我的表述有错误,欢迎指出,打扰各位了~)

「汇编」加深理解段地址*10H(*16)必须是16的倍数的更多相关文章

  1. 「Python」_init_理解与学习

    Python是面向对象的编程语言,因此我从Class.Instance以及属性(property/attribute)的角度出发解释. _init_根据其英文意思(initialize),用来初始化一 ...

  2. 「MoreThanJava」机器指令到汇编再到高级编程语言

    「MoreThanJava」 宣扬的是 「学习,不止 CODE」,本系列 Java 基础教程是自己在结合各方面的知识之后,对 Java 基础的一个总回顾,旨在 「帮助新朋友快速高质量的学习」. 当然 ...

  3. 零元学Expression Blend 4 - Chapter 16 用实例了解互动控制项「Button」II

    原文:零元学Expression Blend 4 - Chapter 16 用实例了解互动控制项「Button」II 本章将教大家如何制作自己的Button,并以玻璃质感Button为实作案例. ? ...

  4. 【入门必看】不理解「对象」?很可能有致命bug:简单的Python例子告诉你

    简介:越来越多的人要在学习工作中用到『编程』这个工具了,其中很大一部分人用的是Python.大部分人只是做做简单的科研计算.绘图.办公自动化或者爬虫,但-- 这就不需要理解「指针与面向对象」了吗? 在 ...

  5. 「C++」理解智能指针

    维基百科上面对于「智能指针」是这样描述的: 智能指针(英语:Smart pointer)是一种抽象的数据类型.在程序设计中,它通常是经由类型模板(class template)来实做,借由模板(tem ...

  6. 「2014-3-18」multi-pattern string match using aho-corasick

    我是擅(倾)长(向)把一篇文章写成杂文的.毕竟,写博客记录生活点滴,比不得发 paper,要求字斟句酌八股结构到位:风格偏杂文一点,也是没人拒稿的.这么说来,arxiv 就好比是 paper 世界的博 ...

  7. jvm系列(十):如何优化Java GC「译」

    本文由CrowHawk翻译,是Java GC调优的经典佳作. 本文翻译自Sangmin Lee发表在Cubrid上的"Become a Java GC Expert"系列文章的第三 ...

  8. 一个「学渣」从零开始的Web前端自学之路

    从 13 年专科毕业开始,一路跌跌撞撞走了很多弯路,做过餐厅服务员,进过工厂干过流水线,做过客服,干过电话销售可以说经历相当的“丰富”. 最后的机缘巧合下,走上了前端开发之路,作为一个非计算机专业且低 ...

  9. LOJ 2664. 「NOI2013」向量内积 解题报告

    #2664. 「NOI2013」向量内积 两个 \(d\) 维向量 \(A=[a_1, a_2 ,...,a_d]\) 与 \(B=[b_1 ,b_2 ,...,b_d]\) 的内积为其相对应维度的权 ...

随机推荐

  1. 联发科Helio P90,MT6779VWB芯片处理器

    联发科(p90)MT6779VWB芯片是一个集成了蓝牙.fm.wlan和gps模块的高度集成的基带平台,包括调制解调器和应用处理子系统.支持LTE/LTE-A和C2K智能手机应用程序.该芯片集成了两个 ...

  2. CentOS_关机与重启命令详解

    Linux centos关机与重启命令详解 Linux centos重启命令: 1.reboot 2.shutdown -r now 立刻重启(root用户使用) 3.shutdown -r 10 过 ...

  3. Java三种方式实现栈和队列

    栈:LIFO(后进先出) 队列:FIFO(先进先出) 1.栈:LIFO(后进先出) 1.1.栈的顺序存储结构实现: /** * 基于数组实现的顺序栈 * @param <E> */ pub ...

  4. Java集合-ArrayList源码解析-JDK1.8

    ◆ ArrayList简介 ◆ ArrayList 是一个数组队列,相当于 动态数组.与Java中的数组相比,它的容量能动态增长.它继承于AbstractList,实现了List, RandomAcc ...

  5. python接口自动化(二)--什么是接口测试、为什么要做接口测试(详解)

    简介 上一篇和大家一起科普扫盲接口后,知道什么是接口,接口类型等,对其有了大致了解之后,我们就回到主题-接口测试. 什么是接口测试 接口测试是测试系统组件间接口的一种测试.接口测试主要用于检测外部系统 ...

  6. Java泛型的重要目的:别让猫别站在狗队里

    <Java编程思想>第四版足足用了75页来讲泛型——厚厚的一沓内容,很容易让人头大——但其实根本不用这么多,只需要一句话:我是一个泛型队列,狗可以站进来,猫也可以站进来,但最好不要既站猫, ...

  7. 两个案例轻松理解MyBatis中的TypeHandler!

    在做开发时,我们经常会遇到这样一些问题,比如我有一个Java中的Date数据类型,我想将之存到数据库的时候存成一个1970年至今的毫秒数,怎么实现?再比如我有一个User类,User类中有一个属性叫做 ...

  8. [开发技巧]·Numpy广播机制的深入理解与应用

    [开发技巧]·Numpy广播机制的深入理解与应用 1.问题描述 我们在使用Numpy进行数据的处理时,经常会用到广播机制来简化操作,例如在所有元素都加上一个数,或者在某些纬度上作相同的操作.广播机制很 ...

  9. SOFARPC源码解析-搭建环境

    文档地址:https://www.sofastack.tech 简介摘要 SOFA 是蚂蚁金服自主研发的金融级分布式中间件,包含构建金融级云原生架构所需的各个组件,包括微服务研发框架,RPC 框架,服 ...

  10. [翻译] 使用 Python 创建你自己的 Shell:Part II

    目录 使用 Python 创建你自己的 Shell:Part II 原文链接与说明 步骤 4:内置命令 最后的想法 使用 Python 创建你自己的 Shell:Part II 原文链接与说明 htt ...