1

I ran into to the following bit of code and am trying to conceptually understand it:

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

v5 and v2 refer to the following data:

v2 dw 4
v5 dw 3

So from my understanding, this seems to touch on the concept of the indirect addressing in x86 assembly language. I know the si and di registers aren't equal to the values, but are just pointing the location. So, therefore, would what be the answer from subtracting two pointers like in the code above? Is it feasible?

user10335564
  • 133
  • 3
  • 16
  • 1
    The difference between pointers is the distance between the objects they point to. This is occasionally useful, for example to find out the index of an array element from a pointer to it. – fuz Mar 20 '19 at 02:41
  • bits is bits. to the processor they are just bits, not floating point not pointers, not integers. just bits. only when operated on for that brief moment they might be something else then go back to being bits. – old_timer Mar 20 '19 at 04:02

1 Answers1

4

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.)

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847