【问题标题】:shl won't move bits between 2 byte groups (x86)shl 不会在 2 个字节组之间移动位 (x86)
【发布时间】:2016-10-07 20:55:59
【问题描述】:

我有这个计算阶乘的代码:

jmp start

; variables
num1 DD 0001h

start:  mov cl, al

        factorial_loop: ; cx = ax -> 1
            mov al, cl
            mul num1
            ; combine dx and ax into num1
            mov num1, dx
            shl num1, 16
            add num1, ax
        loop factorial_loop

mov ah, 0
int 16h

ret

在代码的开头,我将 num1 声明为 4 字节变量。 假设 num1 分为 2 个字节组:num1(左)和 num1(右)。 当我移动这些位时,它们不会从 num1(右)移动到 num1(左)。 我该如何解决这个问题?

【问题讨论】:

  • 这是什么汇编程序?
  • 我用的是emu8086 (x86)
  • 即使这确实奏效了,这也不是您积累 32 位产品的方式。 8086 没有 32x32 => 32 乘法,只有 16x16 => 32。而且您在使用前只需设置 AX 的低 8 位。

标签: assembly bit-manipulation emu8086


【解决方案1】:

您正在使用 16 位汇编程序,因此您无法使用 16 位指令移位 32 位值。

shl num1, 16

隐含地相同(不确定你的汇编器是否支持这种语法,但你应该能够理解):

shl word ptr ds:[num1], 16

在 8086/80286 汇编器中。 8086/80286 汇编器中没有等效的 32 位。

由于您似乎在使用 16 位代码,您可以通过以下两种方式之一解决此问题:

1) 声明两个 16 位字而不是一个 32 位字,例如

numlo dw 0     ; these are encoded exactly like num1,
numhi dw 0     ; but are declared separately for easier use

...

mov numlo,dx   ; just write to the appropriate 16-bit word
mov numhi,ax   ; without the need to shift at all

2) 或应用手动偏移,例如

mov [num1+2],dx
mov num1,ax

您必须为手动偏移确定汇编程序的正确语法,尽管根据您的代码,上述示例应该非常接近。

【讨论】:

  • 在真正的 8086 中,唯一的移位指令是移位 1 和移位 CL。因此,对于 1 以外的班次计数,您需要将计数放入 CL。 (请参阅旧版本的 NASM 手册中的此附录,了解有关何时引入 insn 的详细信息:posix.nl/linuxassembly/nasmdochtml/nasmdoca.html)。 (以及x86 tag wiki 中的其他有用链接。
  • @PeterCordes 你说的很对,但是在真正的 8086 中,mul 也不支持内存操作数,所以这个模拟器的指令集显然比真正的 8086 更灵活,而我没有如果指令汇编,认为提及任何一个限制很重要。
  • 您有该声明的来源吗? MUL 使用/r 字段作为额外的操作码位,让模式和/m 位像往常一样用于编码寄存器或内存操作数,就像add r/m16, imm16 和大多数其他只有一个显式操作数的指令一样。 (386 imul r16, r/m16, imm16 是使用 VEX 编码的 BMI/BMI2 整数指令之前的少数例外之一)。我不记得听说过一些指令不支持 8086 中 ModRM 字节的所有常用编码。
猜你喜欢
  • 2020-04-07
  • 1970-01-01
  • 1970-01-01
  • 2022-06-28
  • 1970-01-01
  • 2018-08-25
  • 1970-01-01
  • 2021-06-12
  • 2012-12-27
相关资源
最近更新 更多