我一直在尝试找出一部分DOS游戏的程序集,并且有一个使用所有4个寄存器的调用都在不断被调用的操作。我可以看到每一行的内容,但是我一生都无法弄清楚所有代码在一起意味着什么。

任何人都可以给我一些想法吗?

代码为:

seg000:3825 some_math_op_on_regs proc far; CODE XREF: sub_72C6+19FP
seg000:3825                              ; sub_72C6+1DDP ...
seg000:3825       cmp     cl, 10h
seg000:3828       jnb     short loc_383A ; Jump if CF=0
seg000:382A       mov     bx, dx         ; c register is < 16; move d to b
seg000:382C       shr     ax, cl         ; Shift a right by value in c (logical)
seg000:382E       sar     dx, cl         ; Shift d right by value in c (arithmetic)
seg000:3830       neg     cl             ; Negate c (2's complement)
seg000:3832       add     cl, 10h        ; Add 16 to c
seg000:3835       shl     bx, cl         ; Shift b left by value in c (logical)
seg000:3837       or      ax, bx         ; OR a and b, store result in a
seg000:3839       retf
seg000:383A ; --------------------------------------------------------------------
seg000:383A
seg000:383A loc_383A:                    ; CODE XREF: some_math_op_on_regs+3j
seg000:383A       sub     cl, 10h        ; c register is >= 16; subtract 16 from c
seg000:383D       xchg    ax, dx         ; Switch values in a and d
seg000:383E       cwd                    ; Convert word to doubleword
seg000:383F       sar     ax, cl         ; Shift a right by value in c (arithmetic)
seg000:3841       retf
seg000:3841 some_math_op_on_regs endp


#1 楼

这看起来像一个32位右移编译器助手。在16位时代,32位数字由一对寄存器表示,在这种情况下为ax:dx。对16的检查是一种优化:如果移位超过16,则低位寄存器的值会完全丢失,因此可以将其丢弃并替换为dx>>(shift-16),而高位寄存器将由于cwd指令的结果而填充符号位。这是Borland C运行时库中的(略加注解)的源代码,似乎与您的源代码相匹配:

#2 楼

它似乎是32位右移,其中dx:ax提供了32位数字,而cl是要移位的位数。 16位只需要关心存储在cl中的高16位,因为低16位无论如何都被移出。如果dx大于16,则将cl(高16位)移至dx并将其转换为32位数字,请从ax中减去16,因为这是通过忽略低16位来隐式完成的,然后将高位部分(即现在的cl多亏了dx:ax)的数字。 />基本上,这是在16位架构中完成的32位右移。