#cpp #ассемблер #clang #clang++
https://wandbox.org/permlink/fNyh3Nj0LroooFFq #include#include using namespace std; char *doSmth(char *s) { volatile register char *p asm("rax") = s; __asm__ ("\ .intel_syntax noprefix \n\ inc rax \n\ inc byte ptr [rax] \n\ "); return (char*)p; } int main() { char s[] = "abcXYZ"; cout << s << ' ' << doSmth(s) << endl; return 0; } Выводится abcXYZ accXYZ т. е. инкремент символа происходит верно, а инкремент указателя тоже как бы происходит (изменён верный символ), но только внутри ассемблерной вставки и не отражается на переменной, используемой в дальнейшем коде. А хотелось бы получить строку с ожидаемо отрезанным первым символом: abcXYZ ccXYZ Как исправить?
Ответы
Ответ 1
Компилятор же не знает, что вы там внутри переменную p поменяли, и берёт значение не из регистра, а из переменной s (её-то вы не меняли, а там записано то же самое). Это один из вариантов, на самом деле их до чёрта. Такая ситуация называется UB (undefined behavior). Чтобы компилятор не занимался самодеятельностью, надо рассказать ему какие переменные изменялись. Например, так: char *doSmth(char *s) { __asm__ volatile ( "inc %0\n" "incb (%0)\n" : "+r"(s) : : "memory"); return s; } Здесь "+r" (s) означает, что переменная s должна быть доступна для чтения и записи как регистр, а volatile и "memory" означают, что в процессе могли измениться посторонние данные (т.е. не являющиеся ни входными параметрами, ни выходными). Подробнее о синтаксисе можно прочитать здесь: https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.htmlОтвет 2
У меня результат зависит от включённой оптимизации. Работает, как предполагалось, при --- testold.cpp 2019-10-30 12:25:49.539828727 +0100 +++ test.cpp 2019-10-30 12:24:11.419439287 +0100 @@ -9,7 +9,6 @@ __asm__ ("\ - .intel_syntax noprefix \n\ inc rax \n\ "); и компиляции с g++ -masm=intel test.cpp. Если не указывать -masm=intel, то не ассемблируется. Если собирать с -O1 или выше, то переменная не изменяется. user@host:~/path$ ./a.out 1234567 234567 user@host:~/path$ Debian, amd64, g++ 6.3.0
Комментариев нет:
Отправить комментарий