Можете ли вы вычесть два указателя на ассемблере? - PullRequest
0 голосов
/ 20 марта 2019

Я столкнулся со следующим фрагментом кода и пытаюсь понять его концептуально:

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

v5 и v2 относятся к следующим данным:

v2 dw 4
v5 dw 3

Так что, насколько я понимаю, это касается концепции косвенной адресации на языке ассемблера x86. Я знаю, что регистры si и di не равны значениям, а просто указывают местоположение. Итак, каков будет ответ от вычитания двух указателей, как в коде выше? Это возможно?

1 Ответ

3 голосов
/ 20 марта 2019

Да, указатели - это просто целые числа, конечно, вы можете вычесть их, например. с 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 перед вычитанием.)

...