首页 > 解决方案 > 你能用汇编语言减去两个指针吗?

问题描述

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

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

v5v2参考以下数据:

v2 dw 4
v5 dw 3

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

标签: pointersassemblyx86inteladdressing

解决方案


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

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

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

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


或者一个将 2 个数组输入作为 2 个指针 + 一个长度的函数可以通过减去并取绝对值来检查它是否小于长度来检查重叠。请参阅在 64 位 x86 中指针比较应该是有符号还是无符号?


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


推荐阅读