Assembly 使用EXT和扩展数字。还有ASR和LSL的工作原理(68000汇编语言)

Assembly 使用EXT和扩展数字。还有ASR和LSL的工作原理(68000汇编语言),assembly,68000,Assembly,68000,我正在学习汇编语言(用于68000微处理器),遇到了以下问题: 编写一个68000汇编语言程序,执行5*X +6*Y+[Y/8]->[D1.L],其中x是存储在 D0和Y是存储在D1的上16位的16位有符号数字。忽略其余的 是的 这就是解决方案: ANDI.W #$OOFF,DO ;CONVERT X TO UNSIGNED 16-BIT MULU.W #5,DO ;COMPUTE UNSIGNED 5*X IN D0.L

我正在学习汇编语言(用于68000微处理器),遇到了以下问题:

编写一个68000汇编语言程序,执行5*X +6*Y+[Y/8]->[D1.L],其中x是存储在 D0和Y是存储在D1的上16位的16位有符号数字。忽略其余的 是的

这就是解决方案:

        ANDI.W      #$OOFF,DO    ;CONVERT X TO UNSIGNED 16-BIT
        MULU.W      #5,DO       ;COMPUTE UNSIGNED 5*X IN D0.L
        SWAP.W      D1          ;MOVE Y TO LOW 16 BITS IN D1
        M0VE.W      D1 ,D2      ;SAVE Y TO LOW 16 BITS OF D2
        MULS.W      #6,D1       ;COMPUTE SIGNED 6*Y IN D1.L
        ADD.L       DO,D1       ;ADD 5*X WITH 6*Y
        EXT.L       D2          ;SIGN EXTEND Y TO 32 BITS
        ASR.L       #3,D2       ;PERFORM Y/8;DISCARD REMAINDER
        ADD.L       D2,Dl       ;PERFORM 5*X+6*Y +Y/8
FINISH  JMP         FINISH
然而,我不明白第一行。我想我们必须把它转换成16位,因为Y是一个16位的有符号数,但我不知道在这种情况下,
ANDI
指令是如何工作的

此外,在示例中,他们使用
ASR.L#3,D2
将D2除以8;所以如果我使用ASR.L#2,D2,那么我将D2除以4?或者它是如何工作的

如果我使用LSL.L#3,D2,那么我将D2乘以8

最后,为什么他们要把Y扩展到32位


谢谢你的帮助

我不知道有68000个asm,但我想ANDI将是立即的,所以
result_16b=0x00FF&X_8b这将确保结果的上8位为零,下8位包含X值

向左/向右移动实际上是乘以/除以2的幂

考虑二进制8b中的值
10

0000 1010
(8+2=10)
0001 0100
左移1档=16+4=20(10*2)
0000 0101
10在向右移动1个位置=4+1=5(10/2)
0000 0010
10向右移动2个位置=2(10/4截断)

因此,在某些CPU上执行X*5可能比使用
MUL
更快:

将放入
D1
16b无符号数,从
D0中的8b无符号扩展而来。作为练习,我将让您自己计算这一点。:)

因此,不要盲目地学习“如何做那件事”,而要始终检查您是否完全了解操作及其目的。这将使您能够更快地构建自己的解决方案。毕竟,事实上,使用CPU可以进行的基本操作很少

一般来说,所有CPU都有(并非所有CPU都有,但从基本CPU开始,就有足够的CPU来模拟其余CPU):

  • 位操作:旋转、移位和或、异或(EOR)、非和复制(移动/加载/存储变体)(x86测试)
  • 很少有算术部件像:NEG、ADD、SUB、MUL、DIV、INC、DEC(还有一些比较)
  • 跳转/呼叫/返回和其他流量控制操作
  • 堆栈实用程序函数:push/pop/。。。(可通过移动/添加/订阅模拟)
  • 其他一切通常要么是CPU/平台的专用控制,要么是基础的专用/复杂变体,或者是更高的数学函数,如sin/cos/

因此,如果您学习了前三组,并习惯于在位级别上思考它们,那么在短时间内学习了“不同”汇编程序的语法之后,您可以在任何其他CPU上取得相当大的进步。这些是相当普遍的。这在用高级语言编程时也有帮助,因此更好地了解什么是CPU的廉价本机操作,什么是更复杂的计算,这样您就可以选择更简单的问题解决方案。

我不知道68000 asm,但我想ANDI将立即使用,所以
result_16b=0x00FF&X_8b这将确保结果的上8位为零,下8位包含X值

向左/向右移动实际上是乘以/除以2的幂

考虑二进制8b中的值
10

0000 1010
(8+2=10)
0001 0100
左移1档=16+4=20(10*2)
0000 0101
10在向右移动1个位置=4+1=5(10/2)
0000 0010
10向右移动2个位置=2(10/4截断)

因此,在某些CPU上执行X*5可能比使用
MUL
更快:

将放入
D1
16b无符号数,从
D0中的8b无符号扩展而来。作为练习,我将让您自己计算这一点。:)

因此,不要盲目地学习“如何做那件事”,而要始终检查您是否完全了解操作及其目的。这将使您能够更快地构建自己的解决方案。毕竟,事实上,使用CPU可以进行的基本操作很少

一般来说,所有CPU都有(并非所有CPU都有,但从基本CPU开始,就有足够的CPU来模拟其余CPU):

  • 位操作:旋转、移位和或、异或(EOR)、非和复制(移动/加载/存储变体)(x86测试)
  • 很少有算术部件像:NEG、ADD、SUB、MUL、DIV、INC、DEC(还有一些比较)
  • 跳转/呼叫/返回和其他流量控制操作
  • 堆栈实用程序函数:push/pop/。。。(可通过移动/添加/订阅模拟)
  • 其他一切通常要么是CPU/平台的专用控制,要么是基础的专用/复杂变体,或者是更高的数学函数,如sin/cos/

因此,如果您学习了前三组,并习惯于在位级别上思考它们,那么在短时间内学习了“不同”汇编程序的语法之后,您可以在任何其他CPU上取得相当大的进步。这些是相当普遍的。这也有助于用高级语言编程,因此更好地了解什么是廉价的CPU本机操作,什么是更复杂的计算,这样您就可以选择更简单的问题解决方案。

原始帖子中的答案效率非常低。应尽可能避免MULU和DIV指令,因为它们分别需要大约70/140个周期,而“正常”指令时间在4到12个周期之间

首先,您可以更改方程式,以便在编码时更好地工作

5 * X + 6 * Y = (X + Y) * 4 + X + 2 * Y
              = (X + Y) << 2 + X + Y + Y
回答您的问题:

EXT执行有符号扩展,因为值的顶部位本质上是一个指示符,指示它是正的还是负的。清除一个
    EOR.W   D1,D1
    MOVE.B  D0,D1
5 * X + 6 * Y = (X + Y) * 4 + X + 2 * Y
              = (X + Y) << 2 + X + Y + Y
         ORG $1000
         ; Compute 5*X + 6*Y + [Y/8] -> [D1.L], 
         ; X = D0.B (unsigned). Y = top 16 bits D1 (signed) 
START
         MOVEQ     #0,D2                   ; MOVEQ faster than CLR
         MOVE.B    D0,D2                   ; D2 now 32 bit X

         SWAP      D1                      ; move Y to bottom 16 bits
         EXT.L     D1                      ; extend to long word.
         MOVE.L    D1,D3                   ;
         ADD.L     D2,D3                   ; add X
         LSL.L     #2,D3                   ; multiply by 4 = 4(X+Y)
         ADD.L     D2,D3                   ; add another X
         ADD.L     D1,D3
         ADD.L     D1,D3                   ; add another 2 Y
         ASR.L     #3,D1                   ; Y/8
         ADD.L     D3,D1                   ; add (5X+6Y)
FINISH
         END      START