Под 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.: спасибо за интересный вопрос
Комментариев нет:
Отправить комментарий