主要参考了《程序员的自我修养》,对作者表示感谢。
部分内容可能有误,请注意了!
本来就不太懂的朋友请不要看,懂的朋友帮忙找找错误啦!
//-------------------------------------------------------------------------------------------------------------------------------------------
/*
print "hello,world\n" on stdou without the main()
with GCC builtin assembly && i386
gcc -c -fno-builtin filename.c // -c : don't link
ld -static -e minor filename.o -o jj // -e : assign enter_adress
*/
char* str="hello,world\n";
void jxprint(void)
{
asm(
"movl $0,%%ebx \n\t" //这里用到了C语言变量str,所以是扩展的汇编格式,所以寄存器前面要用2个%%
"movl %0,%%ecx \n\t" //%0意味着这里要用到某个C语言变量,具体看下面的代码
"movl $12,%%edx \n\t" //这里直接使用汇编调用Linux的系统调用write()来向标准输出,下面“详解”
"movl $4,%%eax \n\t"
"int $0x80 \n\t" //0x80中断即为“系统调用”
:
:"r"(str) //"r"表示把str的值存入str对应的那个寄存器;此时表示把str的值存入ecx。详见说明3
:"eax",“ebx","edx" //对这个的解释涉及更多的GCC内嵌汇编格式,在此不做更多说明,感兴趣的自己见参考资料2
);
}
void jxexit(void)
{
asm(
"movl $42,%ebx \n\t" //这里没有使用扩展汇编格式,所以寄存器前只用1个%
"movl $1,%eax \n\t"
"int $0x80 \n\t"
);
}
int minor(void)
{
jxprint();
jxexit();
}
//-------------------------------------------------------------------------------------------------------------------------------------------
说明1:
"int $0x80"表示调用中断号为0x80的中断,此时即为进行“系统调用”,接着,根据寄存器eax的值来选择系统调用的函数;
eax=4时,表示调用write();eax=1时,表示调用exit();
说明2:
系统调用时的传参问题,系统调用函数参数不超过5个时,依次使用ebx,ecx,edx,esi,edi;超过5个参数时。。。(见参考资料1)这里的依次指寄存器使用的次序对应系统调用函数参数从左至右的排列顺序。//《程序员的自我修养》里面说传参寄存器可以为6个。。。因为之前对这个也不懂,看了之后这篇算是一点笔记吧。贴在这里求高手请教吧。
说明3:
"r"(str)一句。第二个冒号后面第一次出现的C语言变量,对应%0; 第二次出现的对应%1;依次类推。
因为%0对应了str这个C语言变量,所以"movl %0,%%ecx \n\t"相当于"movl str,%%ecx",即为把str的值存入ecx寄存器;由GCC负责把C变量的值和汇编寄存器的值联系起来。更多信息见参考资料2
(非官方资料)
阅读(1000) | 评论(0) | 转发(0) |