【问题标题】:Can you subtract two pointers in assembly language?你能用汇编语言减去两个指针吗?
【发布时间】:2019-03-20 02:39:46
【问题描述】:

我遇到了以下代码,并试图从概念上理解它:

mov si,offset v5
mov di,offset v2
sub si,di

v5v2参考以下数据:

v2 dw 4
v5 dw 3

所以据我了解,这似乎触及了 x86 汇编语言中间接寻址的概念。我知道 si 和 di 寄存器不等于值,而只是指向位置。因此,像上面的代码那样减去两个指针会得到什么答案?可行吗?

【问题讨论】:

  • 指针之间的区别在于它们所指向的对象之间的距离。这有时很有用,例如从指向它的指针中找出数组元素的索引。
  • 位就是位。对于处理器来说,它们只是位,不是浮点,不是指针,不是整数。只是位。只有在那个短暂的时刻被操作时,它们可能会变成别的东西,然后回到比特。

标签: pointers assembly x86 intel addressing


【解决方案1】:

是的,指针只是整数,当然你可以减去它们,例如sub si, di

假设它们是相对于同一段基础的偏移量(例如,微小/小型或扁平内存模型),结果实际上是有意义的:指向的内存位置之间的字节距离。

@fuz 提到的一个用例是:从指针获取数组索引。例如您可以通过增加一个指针来实现strlen,然后在最后执行sub ax, si 以返回一个长度。

当然,对于当前文件中定义的标签,距离是一个汇编时间常数,因此您应该让汇编程序为您计算它。我认为mov si, OFFSET v5 - v2 是正确的 MASM 语法。在 NASM 中,它只是 mov si, v5 - v2。有了这些定义,无论你是在汇编时使用 v5 - v2 还是使用运行时 sub 指令,你都会得到 si=2,因为 dw 4 是 2 个字节宽。


或者将 2 个数组输入作为 2 个指针 + 一个长度的函数可以通过减去并取绝对值来检查重叠是否小于长度。见Should pointer comparisons be signed or unsigned in 64-bit x86?


这与 C 中的指针减法完全相同,只是您可以控制静态数据的布局,因此对有意义的操作或任何未定义的行为没有任何限制。 (除了在 C 语言中,指针减法按类型宽度缩放。所以它实际上就像在减去之前强制转换为 uintptr_t。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-20
    • 1970-01-01
    相关资源
    最近更新 更多