系统调用从GCC内联汇编

是否有可能使用内联汇编块内的系统调用编写单个字符? 如果是的话,怎么样? 它应该看起来像这样的东西:

__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是ascii中的“P”,但是不会返回任何结果。

任何build议非常感谢!

就像是

 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,它似乎无论如何工作…

避免使用外部字符

 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" ); } 

注意:这是因为英特尔处理器的端到端的工作原理! :d

您可以使用体系结构特定的约束将参数直接放置在特定寄存器中,而无需movl联汇编中使用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 

您还可以返回系统调用返回的写入字节数,并使用"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; } 

IIRC,在你的例子中有两件事是错误的。 首先,你正在给stdin写mov $ 0,%ebx其次,写指针的时候是第二个参数,所以要写一个字符就需要那个字符存储在内存中的某个地方,你不能直接把值写到% ECX

例如:

 .data char: .byte 80 .text mov $char, %ecx 

我只在Linux中完成纯粹的asm,从不使用gcc内联,不能将数据放入程序集的中间,所以我不知道如何使用内联汇编来获取指针。

编辑:我想我只记得如何做到这一点。 你可以将“p”推入堆栈并使用%esp

 pushw $80 movl %%esp, %%ecx ... int $0x80 ... addl $2, %%esp