一个最“小”程序的疑惑


在看<<程序员自我修养>>第4.6小结时,看到这样一个最“小”程序:

   
  char* str = "Hello World\n";
  

void print()
{
asm("movl $13, %%edx\n\t"
"movl %0, %%ecx\n\t"
"movl $0, %%ebx\n\t"
"movl $4, %%eax\n\t"
"int $0x80"
::"r"(str):"edx","ecx","ebx");
}

void exit()
{
asm("movl $17, %ebx\n\t"
"movl $1, %eax\n\t"
"int $0x80\n\t");
}

void nomain()
{
print();
exit();
}

这是一个不需要任何C标准库即可在终端输出“Hello World”字样的程序,有助于了解程序链接过程的奥秘。
编译过程:

   
  $gcc -c -fno-builtin TinyHelloWorld.c
  
$ld -static -e nomain -o TinyHelloWorld TinyHelloWorld.o

exit()函数中的汇编代码是看懂了,但print()中的汇编代码是我没有见过的形式,还请懂汇编的朋友帮忙解释下,谢谢!

c 汇编

hd0210 12 years, 3 months ago

C内嵌汇编的格式为

__asm__ __volatile__("Instruction List" : Output : Input : Clobber/Modify);
"r"(str) 为Input,对应Instruction List中的%0

可参考 http://www.embedu.org/Column/Column28.htm

系统调用通过0x80中断实现。其中eax为调用号,ebx,ecx,edx等通用寄存器来传递参数。
比如WRITE调用是往一个文件句柄写入数据,如果用C语言来描述它的原型就是:
int write(int filedesc, char *buffer, int size);

print函数中倒着看就是:
·WRITE调用的调用号为4, 则eax = 4

·filedesc表示被写入的文件句柄,使用ebx寄存器传递,我们这里是要往标准输出,它的文件句柄为0,即ebx = 0

·buffer表示要写入的缓冲区地址,使用ecx寄存器传递,我们这要输出字符串str,所以ecx = str.

·size表示要写入的字节数,使用edx寄存器传递,字符串“Hello world!\n”长度为13字节,所以edx = 13

来自 http://www.cnblogs.com/zhuyp1015/archive/2012/05/02/2479546.html

r4ez8 answered 12 years, 3 months ago

Your Answer