Страницы

Поиск по вопросам

суббота, 13 октября 2018 г.

Вывести символ через ассемблерную вставку

Под linux x86_64 не получается вывести символ через ассемблерную вставку. Делаю так:
void putc(char symbol) { __asm__ ( "mov $4, %%eax
\t" "mov $1, %%ebx
\t" "mov %0, %%ecx
\t" "mov $1, %%edx
\t" "int $0x80
\t" : /* no output registers */ : "c" ((unsigned int)symbol) ); }
GCC генерирует следующий ассемблер:
mov $4, %eax mov $1, %ebx mov %ecx, %ecx mov $1, %edx int $0x80
Видимо проблема в регистре %ecx, что в него не вставляется адрес символа symbol
Компилирую gcc:
$ gcc -ffreestanding -Wall -pedantic -ansi -std=c89 main.c -o main $ ./main
Почему не выводит символ на stdout?


Ответ

Видимо проблема в регистре %ecx, что в него не вставляется адрес символа symbol
Совершенно верно. Но вы можете передать в ассемблерную вставку адрес symbol, просто поставив оператор взятия адреса (&) перед именем переменной.
Убедитесь, что компилируете для x86, и тогда заработает. (За это отвечает флаг компилятора -m32; вероятно, придётся допоставить 32-ух битные библиотеки).
Вот, на мой взгляд, несколько улучшенный вариант:
int putc(char symbol) { int result; __asm__ ( "int $0x80" : "=a" (result) /* возвращаемое значение */ : "a" ((unsigned int) 4) /* номер системного вызова */ , "b" ((unsigned int) 1) /* номер файла для вывода */ , "c" ((unsigned int) &symbol) /* адрес буфера */ , "d" ((unsigned int) 1) /* сколько байт вывести */ : "memory" /* будет читаться основная память */ ); return result; }
int main(int argc, char* argv[]) { return putc(argv[argc > 1][0]); }
Использованные материалы:
Находим код системного вызова mkdir (Habrahabr) Ассемблерные вставки в GCC (GameDev)
Дополнительно и более подробно:
https://gcc.gnu.org/onlinedocs/gcc/Using-Assembly-Language-with-C.html

P.S.: спасибо за интересный вопрос

Комментариев нет:

Отправить комментарий