精华内容
下载资源
问答
  • S7-200系列可编程控制器基本逻辑指令及程序编制 第一节S7-200系列可编程控制器基本逻辑控制指令 梯形图指令与语句表指令是可编程控制器程序中最常用的两种编程语言,逻辑控制指令是构成梯形图和语句表的基本成分。 ...
  • 指令基础及位逻辑指令

    千次阅读 2020-06-07 19:30:59
    主要介绍了在进行PLC编程的过程中,编程指令的具体概念和符号所代表的意义。并且着重介绍了编程里的位...其中的一些具体指令在实际例子中的应用,以及每逻辑指令的功能,通过总结、更有利于我们进行程序的编写。

    指令基础及位逻辑指令

    一、指令基础

    一、指令的概念

    1. 指令:程序的最小独立单位,用户程序由若干条顺序排列的指令构成。指令由操作码和操作数组成。 操作码用来表示使用什么样的操作,操作数用来指定操作的对象。
    2. 操作数:由标识符和参数组成。标识符又分为主标识符和辅助标识符。主标识符表示了存储区域,而辅助标识符表示了存储类型。参数表示的是存储区域的起始地址。下面给大家举个例子,来说明指令的概念。
      在这里插入图片描述

    二、S7-300中的系统存储区
    S7-300的系统存储区集成在CPU中,不能被扩展,是主标识符所标识的存储区域。系统存储区根据功能分为不同的区域供用户使用, 如下表所示:
    在这里插入图片描述
    三、S7-300中的常用存储类型

    辅助标识符表示了存储类型,有四种,分别为位、字节、字和双字,不同类型所占用的存储空间是不一样的,一个双字包含了两个字,一个字包含了两个字节,一个字节包含了8个位。
    在这里插入图片描述
    四、S7-300中块分类
    在这里插入图片描述
    (1)有无存储区的区别: 简言之,存储区是用来存储数据的,有存储区,就意味着数据存储起来,断电不丢失;而无存储区,就意 味着数据只能暂存,断电会丢失掉。
    (2)背景数据块与共享数据块的区:背景数据块是专用块,是供所对应的FB或SFB块使用 ,其他块使用不了;而共享数据块是通用块,是所有块都可以使用的。

    二、位逻辑指令

    位逻辑指令处理的对象为二进制位信号,位逻辑指令的运算结果用两个二进制数字1和0来表示 ,而逻辑运算结果我们往往用其英文简写RLO来指代。位逻辑指令包括触点与线圈、取反指令、置位和复位指令、SR和RS触发器指令、边沿检测指令等。

    一、触点与线圈

    1. 常开触点
      当<操作数>中位值为0时,常开触点将断开,操作结果为0 ;当<操作数>中位值为1时,常开触点将接通,操作结果为1。
      在这里插入图片描述

    2. 常闭触点 当<操作数>中位值为0时,常闭触点将接通,操 作结果为1;当<操作数>中位值为1时,常闭触点将断 开,操作结果为0 。
      在这里插入图片描述

    3. 输出线圈 输出线圈可视为输出继电器的线圈;当输出线圈前端的逻辑运算结果,即RLO,为1时,<操作数>中位值将被设置为1;当输出线圈前端的RLO为0时,<操作 数>中位值将被设置为0。操作数所在的存储区可以是 :I,Q,M,L,D区。它表明了操作位值。
      在这里插入图片描述

    二、取反指令

    该指令的功能为使其前端的RLO取反。
    在这里插入图片描述
    三、置位和复位指令

    1. 置位指令当该指令前端的RLO为1时,<操作数>中位值将被置位为1,即使其前端的RLO又变为0;当该指令前端的RLO为0时,<操作数>中位值保持不变。
      在这里插入图片描述

    2. 复位指令 当该指令前端的RLO为1时,<操作数>中位值将被 复位为0;当该指令前端的RLO为0时,<操作数>中位值保持不变。
      在这里插入图片描述

    四、 SR和RS触发器指令

    1.SR触发器指令当参数S前端的RLO为0,参数R1前端的RLO为0 时,<操作数>中位值将不变;当参数S前端的RLO 为1,参数R1前端的RLO为0时, <操作数>中位值将被置位为1;当参数S前端的RLO为0,参数R1前 端的RLO为1时, <操作数>中位值将被复位为0; 当参数S前端的RLO为1,参数R1前端的RLO为1时, <操作数>中位值将被复位为0,也就是说复位优先于置位。
    在这里插入图片描述2. RS触发器指令当参数R前端的RLO为0,参数S1前端的RLO为0时, <操作数>中位值将不变;当参数R前端的RLO为1,参数S1前端的RLO为0时, <操作数>中位值将被复位为0;当参数R前端的RLO为0,参数S1前端的RLO为1时, <操作数>中位值将被置位为1; 当参数R前端的RLO为1,参数S1前端的RLO为1时, <操作数>中位值将被置位为1 ,也就是说置位优先于复位。
    在这里插入图片描述
    五、边沿检测指令
    该指令有两大类,一类是RLO信号检测指令, 一类是操作数信号检测指令。而RLO信号检测指令又分为RLO信号上升沿检测指令和RLO信号下降沿检测指令。

    RLO信号检测指令

    1. RLO信号上升沿检测指令
      当该指令检测到其之前的RLO信号有“0”>“1”跳变时,该指令操作结果将产生一个扫描周期的1信号。
      在这里插入图片描述
      在这里插入图片描述

    当I0.0有0到1的跳变时,该指令会检测到这个 跳变,它会使后面的输出在一个周期内为1,也就是使Q0.0在一个周期之内为1。这个周期的级别在毫秒级别上。

    1. RLO信号下降沿检测指令 当该指令检测到其之前的RLO信号有“1”>“0”跳变时,该指令操作结果将产生一个扫描周期的1信号。
      在这里插入图片描述
      在这里插入图片描述

    I0.0从1到0产生一个跳变,这个跳变是下降沿的跳变。RLO下降沿指会检测到这个跳变,使后面的输出也就是Q0.0为1,这个为1的时间也是一个扫描周期。

    六、操作数信号检测指令

    1. 操作数信号上升沿检测指令 操作数1上一个周期的逻辑值保存在操作数2中, 当前周期该指令将对其进行对比,检测到操作数1有 “0”->“1”跳变时,该指令操作结果将产生一个扫描周期的1信号。
      在这里插入图片描述
      在这里插入图片描述

    M0.1是保存M0.0在上一个周期的逻辑数值,当这 个周期来的时候。M0.0的当前逻辑数值又会和M0.1里 面的数值,也就是它上一个周期的数值进行比较。如 果有一个产生从“0”->“1”跳变,该指令就会检测 到这个跳变,然后就使它后面的输出在一个扫描周期 之内为1,这里使Q0.0在一个扫描周期之内为1。

    1. 操作数信号下降沿检测指令 操作数1上一个周期的逻辑值保存在操作数2中, 当前周期该指令将对其进行对比,检测到操作数1有 “1”->“0”跳变时,该指令操作结果将产生一个扫 描周期的1信号。
      在这里插入图片描述
      在这里插入图片描述
      M0.1依然保存了M0.0在上一个周期当中的逻辑数 值,当本周期来的时候,M0.0的当前逻辑数值就会和 M0.1当中的数值,也就是它上一个周期的逻辑数值进 行比较,如果有出现一个“1”->“0”跳变,也就是出现一个下降沿的跳变,该指令就会检测到下降沿, 检测到下降沿之后,会使它后面的输出在一个周期之 内为1,在这个例子当中,也就是使Q0.0为1,为1的 时间是保持一个周期。
    展开全文
  • 常用逻辑运算及其指令

    千次阅读 2017-08-08 20:21:15
    1. xor亦或运算只有在两比较的位不同时其结果是1,否则结果为0 即“两输入相同时为0,不同则为1”! 00000000 11111111 11111111 0101 xor 00000000 11111111 00000000 0010 结果 00000000 ...

    1. xor亦或运算

    只有在两个比较的位不同时其结果是1,否则结果为0
    即“两个输入相同时为0,不同则为1”!

    0000000011111111111111110101
    xor0000000011111111000000000010
    结果0000000000000000111111110111

    2. and与运算

    只有两个位都是1时才为1
    即有假(0)即得假(0)

    0000000011111111111111110101
    and0000000011111111000000000010
    结果0000000011111111000000000000

    3. or或运算

    与and运算相逆,只有两个位为0时才得0
    即有真(1)即为真(1)

    0000000011111111111111110101
    or0000000011111111000000000010
    结果0000000011111111111111110111

    4. shl逻辑左移,asl算数左移

    这两个运算效果相同,向左移位,右边加补0

    5. shr逻辑右移

    向右做移位运算,左边补零

    6. sar算数右移

    当操作数为正数时,移位后左边补0
    单操作数为负数时,移位后左边补1(与负数在计算机中的表示是补码有关)

    7. shr与sar测试

    这里写图片描述

    测试说明:
      我在测试时拿16和-16当操作数,所有测试数都做了右移1位的运算。上面是操作数,下面是对应的计算结果,计算结果分别用十进制和二进制表示。
      可见对-16逻辑右移之后结果变成了一个非常大的数字,因为最高位补上了0。

    展开全文
  • 算术和逻辑指令

    千次阅读 2012-10-13 20:32:21
    算术和逻辑指令 ADC : 带进位的加法 (Addition with Carry) ADC{条件}{S} , , dest = op_1 + op_2 + carry ADC 将把两操作数加起来,并把结果放置到目的寄存器中。它使用一进位标志位,这样就...

    算术和逻辑指令

    ADC : 带进位的加法

    (Addition with Carry)

    ADC{条件}{S} <dest>, <op 1>, <op 2>
    dest = op_1 + op_2 + carry

    ADC 将把两个操作数加起来,并把结果放置到目的寄存器中。它使用一个进位标志位,这样就可以做比 32 位大的加法。下列例子将加两个 128 位的数。
    128 位结果: 寄存器 0、1、2、和 3
    第一个 128 位数: 寄存器 4、5、6、和 7
    第二个 128 位数: 寄存器 8、9、10、和 11。

    ADDS R0, R4, R8 ; 加低端的字
    ADCS R1, R5, R9 ; 加下一个字,带进位
    ADCS R2, R6, R10 ; 加第三个字,带进位
    ADCS R3, R7, R11 ; 加高端的字,带进位

    如果如果要做这样的加法,不要忘记设置 S 后缀来更改进位标志。

     

    ADD : 加法

    (Addition)

    ADD{条件}{S} <dest>, <op 1>, <op 2>
    dest = op_1 + op_2

    ADD 将把两个操作数加起来,把结果放置到目的寄存器中。操作数 1 是一个寄存器,操作数 2 可以是一个寄存器,被移位的寄存器,或一个立即值:

    ADD R0, R1, R2 ; R0 = R1 + R2
    ADD R0, R1, #256 ; R0 = R1 + 256
    ADD R0, R2, R3,LSL#1 ; R0 = R2 + (R3 << 1)

    加法可以在有符号和无符号数上进行。

     

    AND : 逻辑与

    (logical AND)

    AND{条件}{S} <dest>, <op 1>, <op 2>
    dest = op_1 AND op_2

    AND 将在两个操作数上进行逻辑与,把结果放置到目的寄存器中;对屏蔽你要在上面工作的位很有用。 操作数 1 是一个寄存器,操作数 2 可以是一个寄存器,被移位的寄存器,或一个立即值:

    AND R0, R0, #3 ; R0 = 保持 R0 的位 0 和 1,丢弃其余的位。

    AND 的真值表(二者都是 1 则结果为 1):

    Op_1 Op_2 结果
    0 0 0
    0 1 0
    1 0 0
    1 1 1

    BIC : 位清除

    (Bit Clear)

    BIC{条件}{S} <dest>, <op 1>, <op 2>
    dest = op_1 AND (!op_2)

    BIC 是在一个字中清除位的一种方法,与 OR 位设置是相反的操作。操作数 2 是一个 32 位位掩码(mask)。如果如果在掩码中设置了某一位,则清除这一位。未设置的掩码位指示此位保持不变。

    BIC R0, R0, #%1011 ; 清除 R0 中的位 0、1、和 3。保持其余的不变。

    BIC 真值表 :

    Op_1 Op_2 结果
    0 0 0
    0 1 0
    1 0 1
    1 1 0
    译注:逻辑表达式为 Op_1 AND NOT Op_2

     

    EOR : 逻辑异或

    (logical Exclusive OR)

    EOR{条件}{S} <dest>, <op 1>, <op 2>
    dest = op_1 EOR op_2

    EOR 将在两个操作数上进行逻辑异或,把结果放置到目的寄存器中;对反转特定的位有用。操作数 1 是一个寄存器,操作数 2 可以是一个寄存器,被移位的寄存器,或一个立即值:

    EOR R0, R0, #3 ; 反转 R0 中的位 0 和 1

    EOR 真值表(二者不同则结果为 1):

    Op_1 Op_2 结果
    0 0 0
    0 1 1
    1 0 1
    1 1 0

    MOV : 传送

    (Move)

    MOV{条件}{S} <dest>, <op 1>
    dest = op_1

    MOV 从另一个寄存器、被移位的寄存器、或一个立即值装载一个值到目的寄存器。你可以指定相同的寄存器来实现 NOP 指令的效果,你还可以专门移位一个寄存器:

    MOV R0, R0 ; R0 = R0... NOP 指令
    MOV R0, R0, LSL#3 ; R0 = R0 * 8

    如果 R15 是目的寄存器,将修改程序计数器或标志。这用于返回到调用代码,方法是把连接寄存器的内容传送到 R15:

    MOV PC, R14 ; 退出到调用者
    MOVS PC, R14 ; 退出到调用者并恢复标志位
    (不遵从 32-bit 体系) 

    MVN : 传送取反的值

    (Move Negative)

    MVN{条件}{S} <dest>, <op 1>
    dest = !op_1

    MVN 从另一个寄存器、被移位的寄存器、或一个立即值装载一个值到目的寄存器。不同之处是在传送之前位被反转了,所以把一个被取反的值传送到一个寄存器中。这是逻辑非操作而不是算术操作,这个取反的值加 1 才是它的取负的值:

    MVN R0, #4 ; R0 = -5
    MVN R0, #0 ; R0 = -1

    ORR : 逻辑或

    (logical OR)

    ORR{条件}{S} <dest>, <op 1>, <op 2>
    dest = op_1 OR op_2

    OR 将在两个操作数上进行逻辑或,把结果放置到目的寄存器中;对设置特定的位有用。操作数 1 是一个寄存器,操作数 2 可以是一个寄存器,被移位的寄存器,或一个立即值:

    ORR R0, R0, #3 ; 设置 R0 中位 0 和 1

    OR 真值表(二者中存在 1 则结果为 1):

    Op_1 Op_2 结果
    0 0 0
    0 1 1
    1 0 1
    1 1 1

    RSB : 反向减法

    (Reverse Subtraction)

    RSB{条件}{S} <dest>, <op 1>, <op 2>
    dest = op_2 - op_1

    SUB 用操作数 two 减去操作数 one,把结果放置到目的寄存器中。操作数 1 是一个寄存器,操作数 2 可以是一个寄存器,被移位的寄存器,或一个立即值:

    RSB R0, R1, R2 ; R0 = R2 - R1
    RSB R0, R1, #256 ; R0 = 256 - R1
    RSB R0, R2, R3,LSL#1 ; R0 = (R3 << 1) - R2

    反向减法可以在有符号或无符号数上进行。

     

    RSC : 带借位的反向减法

    (Reverse Subtraction with Carry)

    RSC{条件}{S} <dest>, <op 1>, <op 2>
    dest = op_2 - op_1 - !carry

    同于 SBC,但倒换了两个操作数的前后位置。

     

    SBC : 带借位的减法

    (Subtraction with Carry)

    SBC{条件}{S} <dest>, <op 1>, <op 2>
    dest = op_1 - op_2 - !carry

    SBC 做两个操作数的减法,把结果放置到目的寄存器中。它使用进位标志来表示借位,这样就可以做大于 32 位的减法。SUBSBC 生成进位标志的方式不同于常规,如果需要借位则清除进位标志。所以,指令要对进位标志进行一个操作 - 在指令执行期间自动的反转此位。

     

    SUB : 减法

    (Subtraction)

    SUB{条件}{S} <dest>, <op 1>, <op 2>
    dest = op_1 - op_2

    SUB 用操作数 one 减去操作数 two,把结果放置到目的寄存器中。操作数 1 是一个寄存器,操作数 2 可以是一个寄存器,被移位的寄存器,或一个立即值:

    SUB R0, R1, R2 ; R0 = R1 - R2
    SUB R0, R1, #256 ; R0 = R1 - 256
    SUB R0, R2, R3,LSL#1 ; R0 = R2 - (R3 << 1)

    减法可以在有符号和无符号数上进行。

    移位指令

    ARM 处理器组建了可以与数据处理指令(ADC、ADD、AND、BIC、CMN、CMP、EOR、MOV、MVN、ORR、RSB、SBC、SUB、TEQ、TST)一起使用的桶式移位器(barrel shifter)。你还可以使用桶式移位器影响在 LDR/STR 操作中的变址值。

    译注:移位操作在 ARM 指令集中不作为单独的指令使用,它是指令格式中是一个字段,在汇编语言中表示为指令中的选项。如果数据处理指令的第二个操作数或者单一数据传送指令中的变址是寄存器,则可以对它进行各种移位操作。如果数据处理指令的第二个操作数是立即值,在指令中用 8 位立即值和 4 位循环移位来表示它,所以对大于 255 的立即值,汇编器尝试通过在指令中设置循环移位数量来表示它,如果不能表示则生成一个错误。在逻辑类指令中,逻辑运算指令由指令中 S 位的设置或清除来确定是否影响进位标志,而比较指令的 S 位总是设置的。在单一数据传送指令中指定移位的数量只能用立即值而不能用寄存器。

    下面是给不同的移位类型的六个助记符:

    LSL 逻辑左移
    ASL 算术左移
    LSR 逻辑右移
    ASR 算术右移
    ROR 循环右移
    RRX 带扩展的循环右移

    ASLLSL 是等同的,可以自由互换。

    你可以用一个立即值(从 0 到 31)指定移位数量,或用包含在 0 和 31 之间的一个值的寄存器指定移位数量。

    逻辑或算术左移

    (Logical or Arithmetic Shift Left)

    Rx, LSL #n or
    Rx, ASL #n or
    Rx, LSL Rn or
    Rx, ASL Rn

    接受 Rx 的内容并按用‘n’或在寄存器 Rn 中指定的数量向高有效位方向移位。最低有效位用零来填充。除了概念上的第 33 位(就是被移出的最小的那位)之外丢弃移出最左端的高位,如果逻辑类指令中 S 位被设置了,则此位将成为从桶式移位器退出时进位标志的值。

    考虑下列:

    MOV R1, #12
    MOV R0, R1, LSL#2

    在退出时,R0 是 48。 这些指令形成的总和是 R0 = #12, LSL#2 等同于 BASIC 的 R0 = 12 << 2

    逻辑右移

    (Logical Shift Right)

    Rx, LSR #n or
    Rx, LSR Rn

    它在概念上与左移相对。把所有位向更低有效位方向移动。如果逻辑类指令中 S 位被设置了,则把最后被移出最右端的那位放置到进位标志中。它同于 BASIC 的 register = value >>> shift

    算术右移

    (Arithmetic Shift Right)

    Rx, ASR #n or
    Rx, ASR Rn

    类似于 LSR,但使用要被移位的寄存器(Rx)的第 31 位的值来填充高位,用来保护补码表示中的符号。如果逻辑类指令中 S 位被设置了,则把最后被移出最右端的那位放置到进位标志中。它同于 BASIC 的 register = value >> shift

    循环右移

    (Rotate Right)

    Rx, ROR #n or
    Rx, ROR Rn

    循环右移类似于逻辑右移,但是把从右侧移出去的位放置到左侧,如果逻辑类指令中 S 位被设置了,则同时放置到进位标志中,这就是位的‘循环’。一个移位量为 32 的操作将导致输出与输入完全一致,因为所有位都被移位了 32 个位置,又回到了开始时的位置!

    带扩展的循环右移

    (Rotate Right with extend)

    Rx, RRX

    这是一个 ROR#0 操作,它向右移动一个位置 - 不同之处是,它使用处理器的进位标志来提供一个要被移位的 33 位的数量。

    乘法指令

     

    指令格式

    这两个指令与普通算术指令在对操作数的限制上有所不同:

    1. 给出的所有操作数、和目的寄存器必须为简单的寄存器。
    2. 你不能对操作数 2 使用立即值或被移位的寄存器。
    3. 目的寄存器和操作数 1 必须是不同的寄存器。
    4. 最后,你不能指定 R15 为目的寄存器。

    MLA : 带累加的乘法

    (Multiplication with Accumulate)

    MLA{条件}{S} <dest>, <op 1>, <op 2>, <op 3>
    dest = (op_1 * op_2) + op_3

    MLA 的行为同于 MUL,但它把操作数 3 的值加到结果上。这在求总和时有用。

     

    MUL : 乘法

    (Multiplication)

    MUL{条件}{S} <dest>, <op 1>, <op 2>
    dest = op_1 * op_2

    MUL 提供 32 位整数乘法。如果操作数是有符号的,可以假定结果也是有符号的。

    比较指令

     

    指令格式

    译注:CMP 和 CMP 是算术指令,TEQ 和 TST 是逻辑指令。把它们归入一类的原因是它们的 S 位总是设置的,就是说,它们总是影响标志位。

    CMN : 比较取负的值

    (Compare Negative)

    CMN{条件}{P} <op 1>, <op 2>
    status = op_1 - (- op_2)

    CMN 同于 CMP,但它允许你与小负值(操作数 2 的取负的值)进行比较,比如难于用其他方法实现的用于结束列表的 -1。这样与 -1 比较将使用:

    CMN R0, #1 ; 把 R0 与 -1 进行比较

    详情参照 CMP 指令。

     

    CMP : 比较

    (Compare)

    CMP{条件}{P} <op 1>, <op 2>
    status = op_1 - op_2

    CMP 允许把一个寄存器的内容如另一个寄存器的内容或立即值进行比较,更改状态标志来允许进行条件执行。它进行一次减法,但不存储结果,而是正确的更改标志。标志表示的是操作数 1 比操作数 2 如何(大小等)。如果操作数 1 大于操作操作数 2,则此后的有 GT 后缀的指令将可以执行。
    明显的,你不需要显式的指定 S 后缀来更改状态标志... 如果你指定了它则被忽略。

     

    TEQ : 测试等价

    (Test Equivalence)

    TEQ{条件}{P} <op 1>, <op 2>
    Status = op_1 EOR op_2

    TEQ 类似于 TST。区别是这里的概念上的计算是 EOR 而不是 AND。这提供了一种查看两个操作数是否相同而又不影响进位标志(不象 CMP 那样)的方法。加上 P 后缀的 TEQ 还可用于改变 R15 中的标志(在 26-bit 模式中)。详情请参照 psr.html,在 32-bit 模式下如何做请参见这里

     

    TST : 测试位

    (Test bits)

    TST{条件}{P} <op 1>, <op 2>
    Status = op_1 AND op_2

    TST 类似于 CMP,不产生放置到目的寄存器中的结果。而是在给出的两个操作数上进行操作并把结果反映到状态标志上。使用 TST 来检查是否设置了特定的位。操作数 1 是要测试的数据字而操作数 2 是一个位掩码。经过测试后,如果匹配则设置 Zero 标志,否则清除它。象 CMP 那样,你不需要指定 S 后缀。

    TST R0, #%1 ; 测试在 R0 中是否设置了位 0。

    分支指令

    B : 分支

    ( Branch)
    B{条件} <地址>
    B 是最简单的分支。一旦遇到一个 B 指令,ARM 处理器将立即跳转到给定的地址,从那里继续执行。
    注意存储在分支指令中的实际的值是相对当前的 R15 的值的一个偏移量;而不是一个绝对地址。
    它的值由汇编器来计算,它是 24 位有符号数,左移两位后有符号扩展为 32 位,表示的有效偏移为 26 位(+/- 32 M)。
    在其他处理器上,你可能经常见到这样的指令:
    OPT 1
    LDA &70
    CMP #0
    BEQ Zero
    STA &72
    .Zero RTS
    (取自 Acorn Electron User Guide issue 1 page 213)
    在 ARM 处理器上,它们将变成下面这些东西:
    OPT 1
    ADR R1, #&70
    LDR R0, [R1]
    CMP #0
    BEQ Zero
    STR R0, [R1, #2]
    .Zero
    MOV PC, R14
    这不是一个很好的例子,但你可以构想如何更好的去条件执行而不是分支。另一方面,如果你有大段的代码或者你的代码使用状态标志,那么你可以使用条件执行来实现各类分支: 这样一个单一的简单条件执行指令可以替代在其他处理器中存在的所有这些分支和跳转指令。
    OPT 1
    ADR R1, #&70
    LDR R0, [R1]
    CMP R0, #0
    STRNE R0, [R1, #2]
    MOV PC, R14

    BL : 带连接的分支

    ( Branch with Link)
    BL{条件} <地址>
    BL 是另一个分支指令。就在分支之前,在寄存器 14 中装载上 R15 的内容。你可以重新装载 R14 到 R15 中来返回到在这个分支之后的那个指令,
    它是子例程的一个基本但强力的实现。它的作用在屏幕装载器 2 (例子 4)中得以很好的展现...
    .load_new_format
    BL switch_screen_mode
    BL get_screen_info
    BL load_palette
    .new_loop
    MOV R1, R5
    BL read_byte
    CMP R0, #255
    BLEQ read_loop
    STRB R0, [R2, #1]!
    ...在这里我们见到在装载器循环之前调用了三个子例程。接着,一旦满足了条件执行就在循环中调用了 read_byte 子例程。

    条件执行

     

     

    ARM 处理器的一个非常特殊的特征是它的条件执行。我们指的不是基本的如果进位则分支,ARM 使这个逻辑阶段进一步深化为如果进位则 XXX - 这里的 XXX 是任何东西。

    为了举例,下面是 Intel 8086 处理器分支指令的一个列表:

    JA Jump if Above
    JAE Jump if Above or Equal
    JB Jump if Below
    JBE Jump if Below or Equal
    JC Jump if Carry
    JCXZ Jump if CX Zero (CX is a register that can be used for loop counts)
    JE Jump if Equal
    JG Jump if Greater than
    JGE Jump if Greater than or Equal
    JL Jump if Less than
    JLE Jump if Less Than or Equal
    JMP JuMP
    JNA Jump if Not Above
    JNAE Jump if Not Above or Equal
    JNB Jump if Not Below
    JNBE Jump if Not Below or Equal
    JNC Jump if No Carry
    JNE Jump if Not Equal
    JNG Jump if Not Greater than
    JNGE Jump if Not Greater than or Equal
    JNL Jump if Not Less than
    JNLE Jump if Not Less than or Equal
    JNO Jump if Not Overflow
    JNP Jump if Not Parity
    JNS Jump if Not Sign
    JNZ Jump if Not Zero
    JO Jump if Overflow
    JP Jump if Parity
    JPE Jump if Parity Even
    JPO Jump if Parity Odd
    JS Jump if Sign
    JZ Jump if Zero
    80386 添加了:
    JECXZ Jump if ECX Zero
    作为对比,ARM 处理器只提供了:
    B 分支
    BL 带连接的分支
    但 ARM 提供了条件执行,你可以不受这个表面上不灵活的方式的限制:
    BEQ Branch if EQual
    BNE Branch if Not Equal
    BVS Branch if oVerflow Set
    BVC Branch if oVerflow Clear
    BHI Branch if HIgher
    BLS Branch if Lower or the Same
    BPL Branch if PLus
    BMI Branch if MInus
    BCS Branch if Carry Set
    BCC Branch if Carry Clear
    BGE Branch if Greater than or Equal
    BGT Branch if Greater Than
    BLE Branch if Less than or Equal
    BLT Branch if Less Than
    BLEQ Branch with Link if EQual
    ....
    BLLT Branch with Link if Less Than
    还有两个代码,
    • AL - ALways,缺省条件所以不须指定
    • NV - NeVer,不是非常有用。你无论如何不要使用这个代码...
    当你发现所有 Bxx 指令实际上是同一个指令的时候,紧要关头就到了。
    接着你会想,如果你可以在一个分支指令上加上所有这些条件,那么对一个寄存器装载指令能否加上它们? 答案是可以。

    下面是可获得的条件代码的列表:

    EQ : 等于
    如果一次比较之后设置了 Z 标志。
      NE : 不等于
    如果一次比较之后清除了 Z 标志。
      VS : 溢出设置
    如果在一次算术操作之后设置了 V 标志,计算的结果不适合放入一个 32bit 目标寄存器中。
      VC : 溢出清除
    如果清除了 V 标志,与 VS 相反。
      HI : 高于(无符号)
    如果一次比较之后设置了 C 标志 清除了 Z 标志。
      LS : 低于或同于(无符号)
    如果一次比较操作之后清除了 C 标志 设置了 Z 标志。
      PL : 正号
    如果一次算术操作之后清除了 N。出于定义‘正号’的目的,零是正数的原因是它不是负数...
      MI : 负号
    如果一次算术操作之后设置了 N 标志。
      CS : 进位设置
    如果一次算术操作或移位操作之后设置了 C 标志,操作的结果不能表示为 32bit。你可以把 C 标志当作结果的第 33 位。
      CC : 进位清除
    与 CS 相反。
      GE : 大于或等于(有符号)
    如果一次比较之后...
    设置了 N 标志 设置了 V 标志
    或者...
    清除了 N 标志 清除了 V 标志。
      GT : 大于(有符号)
    如果一次比较之后...
    设置了 N 标志 设置了 V 标志
    或者...
    清除了 N 标志 清除了 V 标志
    并且...
    清除了 Z 标志。
      LE : 小于或等于(有符号)
    如果一次比较之后...
    设置了 N 标志 清除了 V 标志
    或者...
    清除了 N 标志 设置了 V 标志
    并且...
    设置了 Z 标志。
      LT : 小于(有符号)
    如果一次比较之后...
    设置了 N 标志 清除了 V 标志。
    或者...
    清除了 N 标志 设置了 V 标志。
      AL : 总是
    缺省条件,所以不用明显声明。
      NV : 从不
    不是特别有用,它表示应当永远不执行这个指令。是穷人的 NOP。
    包含 NV 是为了完整性(与 AL 相对),你不应该在你的代码中使用它。
    有一个在最后的条件代码 S,它以相反的方式工作。当用于一个指令的时候,导致更改状态标志。这不是自动发生的 - 除非这些指令的目的是设置状态。例如:
    ADD R0, R0, R1
    ADDS R0, R0, R1
    ADDEQS R0, R0, R1
    第一个例子是一个基本的加法(把 R1 的值增加到 R0),它不影响状态寄存器。

    第二个例子是同一个加法,只不过它导致更改状态寄存器。

    最后一个例子是同一个加法,更改状态寄存器。不同在于它是一个有条件的指令。只有前一个操作的结果是 EQ (如果设置了 Z 标志)的时候它才执行。

    下面是条件执行的一个工作中的例子。你把寄存器 0 与存储在寄存器 10 中内容相比较。

    如果不等于 R10,则调用一个软件中断,增加它并分支回来再次做这些。否则清除 R10 并返回到调用它的那部分代码(它的地址存储在 R14)。

    \ 条件执行的一个例子
    .loop ; 标记循环开始位置
    CMP R0, R10 ; 把 R0 与 R10 相比较
    SWINE &40017 ; 不等于: 调用 SWI &40017
    ADDNE R0, R0, #1 ; 向 R0 加 1
    BNE loop ; 分支到 'loop'
    MOV R10, #0 ; 等于 : 设置 R10 为零
    LDMFD R13!, {R0-R12,PC} ; 返回到调用者
    注解:
    • SWI 编号就象我写的这样。在 RISC OS 下,它是给 Econet_DoImmediate 的编号。不要字面的接受它,这只是一个例子!
    • 你可能以前没见过 LDMFD,它从栈中装载多个寄存器。在这个例子中,我们从一个完全正式的栈中装载 R0 至 R12 和 R14。关于寄存器装载和存储的更多信息请参阅 str.html
    • 我说要装载 R14。那么为什么要把它放入 PC 中? 原因是此时 R14 存储的值包含返回地址。我们也可以采用:
      LDMFD R13!, {R0-R12,R14}
      MOV PC, R14

      但是直接恢复到 PC 中可以省略这个 MOV 语句。
    • 最后,这些寄存器很有可能被一个 SWI 调用所占用(依赖于在调用期间执行的代码),所以你最好把你的重要的寄存器压入栈中,以后在恢复它们。

    SWI 指令

     

    SWI : 软件中断

    (Software Interrupt)

    SWI{条件} <24 位编号>
    指令格式

    这是一个简单的设施,但可能是最常用的。多数操作系统设施是用 SWI 提供的。没有 SWI 的 RISC OS 是不可想象的。

    Nava Whiteford 解释了 SWI 是如何工作的(最初在 Frobnicate issue 12½)...

     

    SWI 是什么?

    SWI 表示 Software Interrupt。在 RISC OS 中使用 SWI 来访问操作系统例程或第三方生产的模块。许多应用使用模块来给其他应用提供低层外部访问。

    SWI 的例子有:

    • 文件器 SWI,它辅助读写磁盘、设置属性等。
    • 打印机驱动器 SWI,用来辅助使用打印并行端口。
    • FreeNet/Acorn TCP/IP 协议栈 SWI,用 TCP/IP 协议在 Internet 上发送和接收数据。

    在以这种方式使用的时候,SWI 允许操作系统拥有一个模块结构,这意味着用来建立完整的操作系统的所需的代码可以被分割成许多小的部分(模块)和一个模块处理程序(handler)。

    当 SWI 处理程序得到对特定的例程编号的一个请求的时候,它找到这个例程的位置并执行它,并传递(有关的)任何数据。

    它是如何工作的?

    首先查看一下如何使用它。一个 SWI 指令(汇编语言)看起来如下:
    SWI &02
    SWI "OS_Write0"
    这些指令实际上是相同的,将被汇编成相同的指令。唯一的不同是第二个指令使用一个字符串来表示 SWI 编号 &02。
    在使用采用了字符串编号的程序的时候,在执行之前首先查找这个字符串。

    在这里我们不想处理字符串,因为它不能给出它要进行什么的一个真实表示。它们通常用于增进一个程序的清晰程度,但不是实际执行的指令。

    让我们再次看一下第一个指令:

    SWI &02
    这是什么意思? 字面的意思是进入 SWI 处理程序并传递值 &02。在 RISC OS 中这意味着执行编号是 &02 的例程。

    它是如何这么作的? 它如何传递 SWI 编号和进入 SWI 处理程序?

    如果你查看内存的开始 32 字节(位于 0-&1C)并反汇编它们(查开实际的 ARM 指令)你将见到如下:

     

    地址 内容 反汇编
    00000000 : 0..å : E5000030 : STR R0,[R0,#-48]
    00000004 : .óŸå : E59FF31C : LDR PC,&00000328
    00000008 : .óŸå : E59FF31C : LDR PC,&0000032C
    0000000C : .óŸå : E59FF31C : LDR PC,&00000330
    00000010 : .óŸå : E59FF31C : LDR PC,&00000334
    00000014 : .óŸå : E59FF31C : LDR PC,&00000338
    00000018 : .óŸå : E59FF31C : LDR PC,&0000033C
    0000001C : 2?ã : E3A0A632 : MOV R10,#&3200000
    让我们仔细看一下。

    除了第一个和最后一个指令之外(它们是特殊情况)你见到的都是把一个新值装载到 PC (程序计数器)的指令,它们告诉计算机到哪里去执行下一个指令。

    还展示了这个值是从内存中的一个地址接受来的。(你可以在 !Zap 主菜单上使用“Read Memory”选项去自己查看一下。)

    这看起来好象与 SWI 没多少关系,下面做进一步的说明。

    一个 SWI 所做的一切就是把模式改变成超级用户并设置 PC 来执行在地址 &08 处的下一个指令!

    把处理器转换到超级用户模式会切换掉两个寄存器 r13 和 r14 并用 r13_svc 和 r14_svc 替换它们。

    在进入超级用户模式的时候,还把 r14_svc 设置为在这个 SWI 指令之后的地址。

    这个实际上就象一个连接到地址 &08 的分支指令(BL &08),但带有用于一些数据(SWI 编号)的空间。

    象我说过的那样,地址 &08 包含跳转到另一个地址的一个指令,就是实际的 SWI 程序的地址!

    此时你可能会想“稍等一会! 还有 SWI 编号呢?”。实际上处理器忽略这个值本身。SWI 处理程序使用传递来的 r14_svc 的值来获取它。

    下面是完成它的步骤(在存储寄存器 r0-r12 之后):

    1. 它从 r14 中减去 4 来获得 SWI 指令的地址。
    2. 把这个指令装载到一个寄存器。
    3. 清除这个指令的高端 8 位,去掉了 OpCode 而只剩下的 SWI 编号。
    4. 使用这个值来找到要被执行的代码的例程的地址(使用查找表等)。
    5. 恢复寄存器 r0-r12。
    6. 使处理器离开超级用户模式。
    7. 跳转到这个例程的地址。
    容易吧! ;)

    下面是一个例子,来自 ARM610 datasheet:

    0x08 B Supervisor
    EntryTable
    DCD ZeroRtn
    DCD ReadCRtn
    DCD WriteIRtn
    ...
    Zero EQU 0
    ReadC EQU 256
    WriteI EQU 512
    ; SWI 包含需要的例程在位 8-23 中和数据(如果有的话)在位 0-7 中。
    ; 假定 R13_svc 指向了一个合适的栈
    STMFD R13, {r0-r2 , R14}
    ; 保存工作寄存器和返回地址。
    LDR R0,[R14,#-4]
    ; 得到 SWI 指令。
    BIC R0,R0, #0xFF000000
    ; 清除高端的 8 位。
    MOV R1, R0, LSR #8
    ; 得到例程偏移量。
    ADR R2, EntryTable
    ; 得到入口表(EntryTable)的开始地址。
    LDR R15,[R2,R1,LSL #2]
    ; 分支到正确的例程
    WriteIRtn
    ; 写 R0 中的位 0 - 7 中的字符。
    .............
    LDMFD R13, {r0-r2 , R15}^
    ; 恢复工作空间,并返回、恢复处理器模式和标志。
    展开全文
  • 汇编中也可以进行算术运算, 比如加减乘除,常用的运算指令用法如表所示: ...使用汇编语言的时候也可以使用逻辑运算指令常用的运算指令用法如表所示: 逻辑运算指令 逻辑运算指令都很好理解,后...

    汇编中也可以进行算术运算, 比如加减乘除,常用的运算指令用法如表所示:

     

    常用运算指令

    在嵌入式开发中最常会用的就是加减指令,乘除基本用不到。

    我们用 C 语言进行CPU 寄存器配置的时候常常需要用到逻辑运算符号,比如“&”、“|”等逻辑运算符。使用汇编语言的时候也可以使用逻辑运算指令,常用的运算指令用法如表所示:

     

    逻辑运算指令

     

    逻辑运算指令都很好理解,后面时候汇编配置 I.MX6UL 的外设寄存器的时候可能会用到,ARM 汇编就讲解到这里,本节主要讲解了一些最常用的指令,还有很多不常用的指令没有讲解,但是够我们后续学习用了。要想详细的学习 ARM 的所有指令请参考《ARM ArchitectureReference Manual ARMv7-A and ARMv7-R edition.pdf》和《ARM Cortex-A(armV7)编程手册 V4.0.pdf》这两份文档。本文转自小平头电子技术社区https://www.xiaopingtou.cn/article-104172.html

    展开全文
  • 基本汇编指令

    2017-03-07 21:55:14
    以下是我在网上找到的汇编常用指令  1. 伪指令org用来规定目标程序存放单元的偏移量。比如,如果在源程序的第一条指令前用了如下指令: org 200h 那么,汇编程序会把指令指针的ip的值设成200h,即目标程序...
  • 微机原理 基本常用操作指令

    万次阅读 多人点赞 2018-10-13 09:39:00
    MOVE 目的操作数或地址 源操作数或地址 常用 PUSH 压字入栈 POP 从栈弹出字ADD 加法 add a,b 将a+b值存到a中 INC 加一 ADC 带进位的加法 add a,b 将a+b+cf存到a SUB 减法 SBB 带错位减法 要考虑是否借位 MUL 无符号...
  • 三菱plc基本指令

    千次阅读 2019-02-22 10:37:20
    三菱 FX 系列plc的基本逻辑指令 取指令与输出指令(LD/LDI/LDP/LDF/OUT) (1)LD(取指令) 一常开触点与左母线连接的指令,每一以常开触点开始的逻辑行都用此指令。 (2)LDI(取反指令) 一常闭触点与左...
  • 8086汇编基本指令

    万次阅读 多人点赞 2018-06-14 20:01:45
    8086汇编的基本指令格式及功能,有助于刚开始学习汇编语言的同学快速上手。
  • 汇编常用指令

    万次阅读 多人点赞 2018-10-06 14:28:08
    IA-32系列有832位通用寄存器,名称分别为:EAX,EBX,ECX,EDX,ESP,EBP,ESI,EDI,如图: 简单传送指令 指令 中文名 格式 解释 备注 location MOV 传送指令 MOV DEST,SRC DEST&amp;lt;=SRC P20 XCHG ...
  • Windows下常用的100CMD指令以及常见的操作

    万次阅读 多人点赞 2016-05-08 18:20:41
    Windows下常用的100CMD指令以及常见的操作常用的100CMD指令 gpedit.msc—–组策略 2. sndrec32——-录音机 3. Nslookup——-IP地址侦测器 ,是一 监测网络中 DNS 服务器是否能正确实现域名解析的命令行工具...
  • 指令格式是指令使用二进制编码表示的结构形式,一般一条指令分为操作码和地 址码两部分: 一、操作码 操作码表示指令的属性功能和执行的指令类型。操作数对应的二进制位数决定了计算机能够实现的最大指令数目。例如...
  • S7-200基本指令

    2013-08-21 22:52:11
     运算指令,包括常用的算术运算和逻辑运算指令。  其他数据处理类,包括数据的传送、移位、填充和交换等指令。  表功能指令,包括对表的存取和查找指令。  转换指令,包括数据类型转换、码转换和字符转换...
  • 汇编语言基本指令记忆要点分析 初学汇编语言难免感觉抽象难懂不好记忆,实际上任何语言都有其特点或规律,学习时只要能发现并掌握其规律就会...本文以8086 微处理器为例,对一些常用基本指令的特点及记忆要点进行了分析。
  • PLC常用指令

    千次阅读 多人点赞 2020-04-28 09:43:50
    PLC指令应用基本指令逻辑取及驱动线圈指令LD、LDI、OUT触电串、并联指令AND、ANI、OR、ORI电路块连接指令ANB、ORB置位与复位指令SET、RST空操作和程序结束指令要素表NOP、END多重输出电路指令MPS、MPD、MPP脉冲输出...
  • 3.1 S7-200系列PLC编程软件简介 3.2 S7-200PLC指令基本格式及编程规约 3.3基本逻辑指令 3.4 定时器 3.5计数器指令 3.6比较指令 3.7程序控制指令
  • 汇编中基本指令格式

    千次阅读 2016-11-18 19:30:19
    指令中符号解释:R代表寄存器 M代表内存单元 I代表立即数 运算指令: ADD R/M , R/M/I    加法指令(减法类似) XCHG R/M ,R    两数交换指令 INC R/M   自增指令(自减类似) CMP R/M, R/M/I    比较指令...
  • 进程运行的基本原理(1)指令的工作原理---操作码+若干参数(可能包含地址参数)(2)逻辑地址(相对地址)vs物理地址(绝对地址)(3)从写程序到程序运行---编译、链接、装入(4)装入模块装入内存(5)装入的三种...
  • 常用指令

    2014-08-22 10:35:11
    指令支持的寻址方式:目的操作数和源操作数不能同时用存储器寻址方式,这限制适用于所有指令指令的执行对标志位的影响:不影响标志位。 指令的特殊要求:目的操作数DST和源操作数SRC不允许同时为段寄存器; ...
  • 三菱 FX 系列plc的基本逻辑指令取指令与输出指令(LD/LDI/LDP/LDF/OUT)(1)LD(取指令) 一常开触点与左母线连接的指令,每一以常开触点开始的逻辑行都用此指令。(2)LDI(取反指令) 一常闭触点与左母线...
  • 汇编常用指令

    千次阅读 2019-06-25 20:02:35
    算术运算类指令 1.加法指令 不带进位 ADD A,Rn ADD A,direct ADD A, @Ri ADD A,#data 带进位 ADDC A,Rn ADDC A,direct ADDC A, @Ri ADDC A,#data 增量指令 INC A INC Rn INC direct INC @Ri INC ...
  • 汇编语言基本指令

    千次阅读 多人点赞 2018-06-16 15:52:38
    常用命令 执行操作 cmp a,b 比较a与b mov a,b 把b的值送给a ret 返回主程序 nop 无作用 call 调用子程序 je 或jz 若相等则跳(机器码74 或0F84) jne或jnz 若不相等则跳(机器码75或0F85...
  • 常用ARM汇编指令

    千次阅读 2014-09-18 11:10:37
    常用ARM汇编指令
  • FX3U基本指令学习

    万次阅读 2017-11-27 15:13:54
    三菱微型可编程控制器 FX3G\FX3U\FX3GC\FX3GU 编程方式:1、指令表编程(LD\AND\OUT);2、梯形图;3、SFC(STL)编程;4、ST(结构文本)(类C语言);5、结构化梯形图;...基本指令 触点指令:  LD:取  LDI:
  • 常用汇编指令

    千次阅读 2012-05-03 11:03:10
    常见的汇编指令 一、通用数据传送指令 1、传送指令 MOV (move) 指令的汇编格式:MOV DST,SRC 指令基本 功能:(DST) 指令支持的寻址方式:目的操作数和源操作数不能同时用存储器寻址 方式,这限制适用...
  • 三菱PLC FX系列的基本逻辑指令:取指令与输出指令(LD/LDI/LDP/LDF/OUT)(1)LD(取指令) 一常开触点与左母线连接的指令,每一以常开触点开始的逻辑行都用此指令;(2)LDI(取反指令) 一常闭触点与左母线...
  • 8086常用指令

    2020-09-23 16:32:06
    三、逻辑运算和移位指令 ①“与”指令: ②“或”运算指令 ③“非”运算指令 ④“异或”运算指令 ⑤“测试”指令 ⑥移位操作指令 1、非循环移位指令 2、循环移位指令 四、串操作指令 ①串传送M

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 127,874
精华内容 51,149
关键字:

五个常用的基本逻辑指令