C 系统的正确内联汇编代码
我已经为系统调用sys_uname编写了内联汇编代码,但它似乎不正确C 系统的正确内联汇编代码,c,x86,freebsd,inline-assembly,i386,C,X86,Freebsd,Inline Assembly,I386,我已经为系统调用sys_uname编写了内联汇编代码,但它似乎不正确 #include <sys/utsname.h> #include <stdio.h> #include <stdlib.h> #include <sys/syscalls.h> #include <string.h> struct utsname stroj; __asm__ volatile("pushl $0;" "pushl %%
#include <sys/utsname.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/syscalls.h>
#include <string.h>
struct utsname stroj;
__asm__ volatile("pushl $0;"
"pushl %%ebx;"
"pushl $0;"
"int $0x80;"
:
: "a" (SYS_uname), "b" (&stroj)
);
//uname(&stroj); -> when I do this it works, but again, I want to use inline assembly
write(1, stroj.nodename, strlen(stroj.nodename)); // 1 = stdout
#包括
#包括
#包括
#包括
#包括
结构utsname stroj;
__asm_uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
“PUSH%%ebx;”
“pushl$0;”
“整型$0x80;”
:
:“a”(SYS_uname),“b”(&stroj)
);
//uname(&stroj);->当我这样做的时候,它是有效的,但同样,我想使用内联汇编
写入(1,stroj.nodename,strlen(stroj.nodename));//1=标准输出
是否有一些我没有解决的突出问题?这个答案假设您希望直接使用系统调用而不是通过C库函数使用系统调用是有原因的 正确的内联程序集版本可能如下所示:
#include <sys/utsname.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/syscall.h>
#include <string.h>
#include <unistd.h>
/* SYS_uname has the value 164 */
/* #define SYS_uname 164 */
#define SYS_uname SYS_freebsd4_uname
int main()
{
u_int syscallnum = SYS_uname;
struct utsname stroj;
asm("push %[stroj]\n\t"
"push %%eax\n\t" /* Required dummy value for int 0x80 */
"int $0x80\n\t"
"add $8, %%esp" /* 2*4 bytes removed from stack */
: "+a"(syscallnum) /* error code also returned in syscallnum */
: [stroj]"r"(&stroj)
: "memory");
write(1, stroj.nodename, strlen(stroj.nodename));
return 0;
}
FreeBSD 2+不支持过时的系统 如果你尝试运行上面的代码,你会发现它没有返回任何东西。如果将该程序与类似
truss./progname
的命令一起使用,您应该会在输出中看到类似的内容:
obs#u uname(0xffffc6f8,0x0,0x0,0x0,0x0)错误#78“未实现函数”
这是因为,现在被认为是过时的。FreeBSD的libcuname
调用以填充utsname
结构的字段。在命令行中,您可以使用以下命令查询节点名
:
sysctl kern.hostname
您可以通过以下方式通过系统调用调用sysctl
:
#include <unistd.h>
#include <sys/syscall.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/sysctl.h>
#define OSNAME_MAX_LEN 256
/* SYS___sysctl has the value 202 */
/* #define SYS___sysctl 202 */
int main(void)
{
char osname[OSNAME_MAX_LEN];
size_t osnamelen = sizeof(osname) - 1;
int name[] = {CTL_KERN, KERN_HOSTNAME};
u_int namelen = sizeof(name) / sizeof(name[0]);
char * old = osname;
size_t * oldlenp = &osnamelen;
u_int syscallnum = SYS___sysctl;
asm("push %[newlen]\n\t"
"push %[new]\n\t"
"push %[oldlenp]\n\t"
"push %[old]\n\t"
"push %[namelen]\n\t"
"push %[name]\n\t"
"push %%eax\n\t" /* Required dummy value */
"int $0x80\n\t"
"add $28, %%esp" /* 7*4=28 bytes to remove from stack */
: "+a"(syscallnum) /* error code also returned in syscallnum */
: [name]"r"(name), [namelen]"r"(namelen),
[old]"r"(old) , [oldlenp]"r"(oldlenp),
[new]"i"(NULL), [newlen]"i"(0)
: "memory");
if (syscallnum) {
return EXIT_FAILURE;
}
osname[osnamelen]='\0'; /* Ensure the OS Name is Null terminated */
printf("This machine's node name is %s\n", osname);
return EXIT_SUCCESS;
}
#include <unistd.h>
#include <sys/syscall.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/sysctl.h>
#define OSNAME_MAX_LEN 256
/* SYS___sysctl has the value 202 */
/* #define SYS___sysctl 202 */
int main(void)
{
char osname[OSNAME_MAX_LEN];
size_t osnamelen = sizeof(osname) - 1;
int name[] = {CTL_KERN, KERN_HOSTNAME};
u_int namelen = sizeof(name) / sizeof(name[0]);
char * old = osname;
size_t * oldlenp = &osnamelen;
if (syscall(SYS___sysctl, name, namelen, old, oldlenp, NULL, 0) == -1) {
perror("sysctl");
return EXIT_FAILURE;
}
osname[osnamelen]='\0'; /* Ensure the OS Name is Null terminated */
printf("This machine's node name is %s\n", osname);
return EXIT_SUCCESS;
}
两次超过0美元可能是错误的。也许其中一个应该是1.5美元,可以编辑,可以编译。我还试着用$1替换$0,输出没有变化。其中一个应该是你问题的答案我希望这是OSX的?你为什么要在堆栈上加零?好的,是的,i386 FreeBSD在用户空间堆栈上传递syscall参数。另外,您忘记了一个
“memory”
clobber或内存输出操作数,因此编译器将假定stroj
仍然没有修改,并且可以在编译时计算strlen
。您是否尝试使用strace
或类似工具跟踪系统调用?我没有使用strace的经验,这是我第一次尝试内联汇编。我将添加内存缓冲。
#include <unistd.h>
#include <sys/syscall.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/sysctl.h>
#define OSNAME_MAX_LEN 256
/* SYS___sysctl has the value 202 */
/* #define SYS___sysctl 202 */
int main(void)
{
char osname[OSNAME_MAX_LEN];
size_t osnamelen = sizeof(osname) - 1;
int name[] = {CTL_KERN, KERN_HOSTNAME};
u_int namelen = sizeof(name) / sizeof(name[0]);
char * old = osname;
size_t * oldlenp = &osnamelen;
if (syscall(SYS___sysctl, name, namelen, old, oldlenp, NULL, 0) == -1) {
perror("sysctl");
return EXIT_FAILURE;
}
osname[osnamelen]='\0'; /* Ensure the OS Name is Null terminated */
printf("This machine's node name is %s\n", osname);
return EXIT_SUCCESS;
}