我在C:
中有这个功能int write(int fd, char *buffer, int size)
{
int ret;
__asm__("mov $4, %%eax;"
"mov %0, %%ebx;"
"mov %1, %%ecx;"
"mov %2, %%edx;"
"int $0x80"
: "=r"(ret)
: "g"(fd), "g"(buffer), "g"(size)
: "eax", "ebx", "ecx", "edx");
if (ret < 0) {
return -1;
} else {
return 0;
}
}
在ASM中转换为此代码:
push %ebp
mov %esp,%ebp
push %esi
push %ebx
mov $0x4,%eax
mov %esi,%ebx
mov 0x8(%ebp),%ecx
mov 0xc(%ebp),%edx
int $0x80
mov %esi,%eax
sar $0x1f,%eax
pop %ebx
pop %esi
pop %ebp
ret
作为fd,*缓冲区和大小是函数参数,它们分别是0x8(%ebp),0xc(%ebp)和0x10(%ebp)。为什么GCC在%esi中识别fd的位置,而另外两个变量在堆栈中移位?如何运行此函数(正确获取寄存器中的变量)?
答案 0 :(得分:1)
这可能是您架构上的调用约定。如果要将其他参数约束到寄存器,则应直接使用寄存器约束:例如。 "a"
代表eax
注册。
开头的$4
对我来说也是错误的。
沿线的东西
__asm__(
"int $0x80"
: "=b"(ret)
: "c"(fd), "d"(buffer), "a"(size)
);
应该这样做,如果它们真的是你的系统调用使用的寄存器。
但是,总的来说,我认为你不应该自己这样做。您的操作系统肯定有类似syscall
的功能,可以为您提供该功能。
答案 1 :(得分:0)
内联汇编程序的参数从输出开始从零开始编号,因此%0为ret,%1为fd,%2为缓冲区,%3为大小。