assembly - 如何使用乘法的符号扩展?
问题描述
我现在正在学习组装,我完全不知道如何使用符号扩展。我知道,如果您在 AX 中有一个值并且做 MUL 值,它将值乘以 AX,结果在 DX:AX 中,但是我如何访问和使用上部?这对我来说毫无意义。
解决方案
16 位寄存器保存0000h..FFFFh 范围内的无符号数。此类数的加减结果可能会超出该范围一位,该位由CarryFlag 调节。
例如 FFFFh + FFFFh = CF + FFFEh。
乘法的情况有所不同:它可能会溢出 16 位,
例如 FFFFh * FFFFh = FFFE0001h。
这就是为什么使用另一个寄存器(硬连线为 DX)来保存结果的高 16 位的原因。
即使是旧的 16 位处理器 8086 也可以仅使用传统的 16 位寄存器来加|减 32 位数字,但是每个操作需要两条机器指令,并且必须考虑进位标志。32 位数字的下半部分用 计算,ADD|SUB
上半部分用计算ADC|SBB
。
(a*b)+(c*d)
例如,让我们计算一下a,b,c,d
16 位数字 000Ah、000Bh、000Ch、000Dh 分别在哪里。
MOV AX,000Ah ;
MOV CX,000Bh ; Let CX=000Bh
MUL CX ; Let DX:AX= a * b = 0000:006Eh
MOV SI,AX ; Save temporary result DX:AX
MOV DI,DX ; into another pair DI:SI.
MOV AX,000Ch
MOV CX,000Dh
MUL CX ; Let DX:AX = c * d = 0000:009Ch
; Add the temporary result DI:SI to DX:AX.
ADD AX,SI ; Let AX = 009Ch + 006Eh = 010Ah. CF = 0.
ADC DX,DI ; Let DX = 0000h + 0000h + CF = 0. CF = 0.
的结果(a*b)+(c*d)
,即 0000:010Ah,现在位于 DX:AX,CF=0。
我们也可以将 16 位值视为 -32768..+32767 范围内的有符号整数,即 8000h..7FFFh。Intel CPU 8086 不能乘以有符号数,指令IMUL是在 80186 及更高版本中引入的。在没有的情况下,IMUL
我们必须将每个数字转换为其绝对值,执行无符号乘法,如果乘数中恰好一个为负,则将无符号乘积转换为其负值。
负值与其绝对(正)值之间的转换由指令NEG提供。要在两个连接的 16 位寄存器中取反 32 位数字,必须再次考虑进位标志:
; Negate DX:AX
NEG DX
NEG AX
SBB DX,0
或者,或者,效率较低
; Negate DX:AX
NOT AX
NOT DX
ADD AX,1
ADC DX,0
但是,正如 Peter Cordes 在评论中所建议的那样,过去 30 年制造的所有 Intel/AMD 处理器都可以直接计算有符号乘法,IMUL
因此您最好使用它。
推荐阅读
- pandas - Pandas:如何在两个不同的重叠时间序列上合并两个数据帧
- python - 我们可以在列表 pop() 中使用切片吗?答案是肯定的?告诉怎么做?
- php - 如何使用角色授予对脚本的访问权限?
- spring - 尝试 POST 时使用 RestTemplate 在 Spring Project 中抛出 400 Bad Request
- java - 使用 pdfbox 旋转文本
- sql - 使用 Ktor + Exposed (Kotlin) 进行数据库迁移的推荐方法是什么?
- typescript - 如何在打字稿中正确重载具有多个参数的函数?
- c# - 如何将以下 C# lambda 表达式拆分为单独的方法?
- methods - 为什么在另一个方法中无法访问方法的返回值
- python - 如何将其绘制为散点图?