Syscall из встроенной сборки GCC
Можно ли написать один символ, используя syscall из встроенного блока сборки? если да, то как? он должен выглядеть "что-то" следующим образом:
__asm__ __volatile__
(
" movl $1, %%edx \n\t"
" movl $80, %%ecx \n\t"
" movl $0, %%ebx \n\t"
" movl $4, %%eax \n\t"
" int $0x80 \n\t"
::: "%eax", "%ebx", "%ecx", "%edx"
);
$80 является "P" в ascii, но ничего не возвращает.
любые предложения, которые были высоко оценены!
Ответы
Ответ 1
Что-то вроде
char p = 'P';
int main()
{
__asm__ __volatile__
(
" movl $1, %%edx \n\t"
" leal p , %%ecx \n\t"
" movl $0, %%ebx \n\t"
" movl $4, %%eax \n\t"
" int $0x80 \n\t"
::: "%eax", "%ebx", "%ecx", "%edx"
);
}
Добавить: обратите внимание, что я использовал lea
для загрузки эффективного адреса регистра char в ecx
; для значения ebx
я пробовал $0 и $1 и, похоже, все равно работает...
Избегайте использования внешнего char
int main()
{
__asm__ __volatile__
(
" movl $1, %%edx \n\t"
" subl $4, %%esp \n\t"
" movl $80, (%%esp)\n\t"
" movl %%esp, %%ecx \n\t"
" movl $1, %%ebx \n\t"
" movl $4, %%eax \n\t"
" int $0x80 \n\t"
" addl $4, %%esp\n\t"
::: "%eax", "%ebx", "%ecx", "%edx"
);
}
N.B.: это работает из-за эндемичности процессоров Intel!: D
Ответ 2
Вы можете использовать ограничения, специфичные для архитектуры, для непосредственного размещения аргументов в определенных регистрах, без инструкций movl
в вашей встроенной сборке. Кроме того, затем вы можете использовать оператор &
для получения адреса символа:
#include <sys/syscall.h>
void sys_putc(char c) {
// write(int fd, const void *buf, size_t count);
int ret;
asm volatile("int $0x80" : "=a"(ret): "a"(SYS_write), "b"(1), "c"(&c), "d"(1));
}
int main(void) {
sys_putc('P');
sys_putc('\n');
}
(В этом случае требуется =a(ret)
, чтобы указать, что сбрасываемые сейсмоприемники EAX.)
$ cc -m32 sys_putc.c && ./a.out
P
Вы также можете вернуть количество байтов, записанных в Syscall, и использовать "0"
как ограничение, чтобы снова указать EAX:
int sys_putc(char c) {
int ret;
asm volatile("int $0x80" : "=a"(ret) : "0"(SYS_write), "b"(1), "c"(&c), "d"(1));
return ret;
}
Ответ 3
IIRC, в вашем примере две вещи неверны.
Во-первых, вы пишете stdin с mov $0,% ebx
Во-вторых, запись берет указатель как второй аргумент, поэтому для записи одного символа вам нужен этот символ, хранящийся где-то в памяти, вы не можете записать значение непосредственно в% ecx
Пример:
.data
char: .byte 80
.text
mov $char, %ecx
Я только делал чистый asm в Linux, никогда не использовал inline с помощью gcc, вы не можете удалить данные в середине сборки, поэтому я не уверен, как вы получите указатель, используя встроенную сборку.
EDIT: Думаю, я просто вспомнил, как это сделать. вы можете нажать "p" на стек и использовать% esp
pushw $80
movl %%esp, %%ecx
... int $0x80 ...
addl $2, %%esp