LINUX.ORG.RU

Вопрос по ассемблерным вставкам в Си

 ,


0

5

Код:

#include <stdio.h>

int main(int argc, char *argv[]){
  int i = 58;
  int b = 52;
  int sum;
  asm("add %1, %2;" : "=r"(sum) : "r"(i), "r"(b));
  printf("Hello, %d+%d=%d \n", i, b, sum);
  return 0;
}

Получившийся ассемблерный код выглядит так:

...
	mov	edx, 52
	mov	eax, 58
	mov	ecx, 52
	mov	esi, 58
	mov	edi, OFFSET FLAT:.LC0
#APP
# 7 "test1.c" 1
	add eax, ecx;
# 0 "" 2
#NO_APP
	xor	eax, eax
	call	printf
...

После выполнения моей вставки регистр eax обнуляется. Тем не менее результат сложения сохраняется и нормально отображается. Если выполнить xor eax, eax внутри моей вставки, то sum обнуляется. Что за магия?

причём тут eax, параметры в System V AMD64 ABI передаются в RDI, RSI, RDX, RCX, R8, R9, XMM0–7

смотрим objdump

00000000004004a0 <main>:
  4004a0:       sub    rsp,0x8
  4004a4:       mov    eax,0x3a
  4004a9:       mov    ecx,0x34
  4004ae:       mov    edx,0x34
  4004b3:       mov    esi,0x3a
  4004b8:       mov    edi,0x400698
  4004bd:       add    ecx,eax
  4004bf:       xor    eax,eax
  4004c1:       call   400480 <printf@plt>

anonymous ()

Если меняешь регистр внутри вставки, то должен его указывать в clobbered registers, т.е.

asm("add %1, %2;" : "=r"(sum) : "r"(i), "r"(b): "%eax");

Сам листинг какой-то неполный, в нём нет кода формирования аргументов для printf(), лучше смотреть objdump'ом.

mashina ★★★★★ ()
Последнее исправление: mashina (всего исправлений: 1)
Ответ на: комментарий от anonymous

Спасибо большое, разобрался. Я генерил бинарник без оптимизации, а ассемблерный код с оптимизацией -O2. С оптимизацией эта вставка действительно не работает.

Archer73 ()

Есть какой-то профит от таких вот вставок?

Context switch в шедулерах как пример не рассматриваем.

anonymous ()
Ответ на: комментарий от anonymous

есть, всякий раз, когда тебе надо выполнить конкретную последовательность инструкций с использованием конкретных регистров.

в современных компиляторах частично вместо этого можно пользоваться интринсиками, но сплошь и рядом они делают не то, не так или их просто нет в твоей версии компилятора для нужной инструкции.

anonymous ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.