Yes, pointers are just integers, of course you can subtract them, e.g. with sub si, di
.
Assuming they're offsets relative to the same segment base (e.g. a tiny/small or flat memory model), the result is actually meaningful: the distance in bytes between the pointed-to memory locations.
One use-case is what @fuz mentioned: getting an array index from a pointer. e.g. you might implement strlen
by incrementing a pointer, then at the end do sub ax, si
to return a length.
Of course, for labels defined in the current file, the distance is an assemble-time constant so you should just ask the assembler to calculate it for you. I think mov si, OFFSET v5 - v2
is the right MASM syntax. In NASM it would be just mov si, v5 - v2
. And with those definitions, you'd get si=2
whether you do it at assemble time with v5 - v2
or with a runtime sub
instruction, because dw 4
is 2 bytes wide.
Or a function that takes 2 array inputs as 2 pointers + a length can check for overlap by subtracting and taking the absolute value to see if it's smaller than the length. See Should pointer comparisons be signed or unsigned in 64-bit x86?
It's exactly like subtracting pointers in C, except that you control the layout of static data so there are no limitations on what it makes sense to do, or any undefined behaviour. (Except in C, pointer subtraction scales by the type width. So it's actually like casting to uintptr_t
before subtracting.)