最近我在玩 freebsd 系统调用,我对 i386 部分没有问题,因为它在这里有很好的记录。但是我找不到 x86_64 的相同文档。
我看到人们在 linux 上使用相同的方式,但他们只使用程序集而不是 c。我想在我的例子中,系统调用实际上改变了一些被高优化级别使用的寄存器,所以它给出了不同的行为。
/* for SYS_* constants */
#include <sys/syscall.h>
/* for types like size_t */
#include <unistd.h>
ssize_t sys_write(int fd, const void *data, size_t size){
register long res __asm__("rax");
register long arg0 __asm__("rdi") = fd;
register long arg1 __asm__("rsi") = (long)data;
register long arg2 __asm__("rdx") = size;
__asm__ __volatile__(
"syscall"
: "=r" (res)
: "0" (SYS_write), "r" (arg0), "r" (arg1), "r" (arg2)
: "rcx", "r11", "memory"
); …Run Code Online (Sandbox Code Playgroud) const int howmany = 5046;
char buffer[howmany];
asm("lea buffer,%esi"); //Get the address of buffer
asm("mov howmany,%ebx"); //Set the loop number
asm("buf_loop:"); //Lable for beginning of loop
asm("movb (%esi),%al"); //Copy buffer[x] to al
asm("inc %esi"); //Increment buffer address
asm("dec %ebx"); //Decrement loop count
asm("jnz buf_loop"); //jump to buf_loop if(ebx>0)
Run Code Online (Sandbox Code Playgroud)
我正在使用gcc编译器.出于某种原因,我的缓冲区/ howmany变量在我的asm眼中是不确定的.我不知道为什么.我只想将缓冲区数组的起始地址移动到esi寄存器中,在将每个元素复制到al寄存器时循环"howmany"次.
我正在使用此处bsf找到的英特尔开发人员手册第 210 页上的x86-64 指令。本质上,如果找到最低有效位 1,则将其位索引存储在目标操作数中。
此外,如果所有源操作数为 0,则 ZF 标志设置为 1;否则,ZF 标志被清除。
我正在使用内联 x86-64 汇编指令编译我的 C 代码。我已经定义了一个调用bsf指令的 C 函数:
uint64_t bitScanForward(T_bitboard b) {
__asm__(
"bsf %rcx,%rax\n"
"leave\n"
"ret\n"
);
}
Run Code Online (Sandbox Code Playgroud)
还有另一个 C 函数,它检查标志寄存器中 ZF 位的状态:
uint64_t isZFSet() {
printf("\n"); <- This is another problem I am having (see below)...
__asm__(
"jz true\n"
"movq $0,%rax\n"//return false
"jmp end\n"
"true:\n"
"movq $1,%rax\n"//return true
"end:\n"
"leave\n"
"ret\n"
);
}
Run Code Online (Sandbox Code Playgroud)
我已经对这些进行了测试,发现即使将 bsf 命令应用于数字零,ZF 标志也始终被清除,这似乎违反了规范。
//Calling function...
//Do stuff...
bitScanForward(0ULL);//ULL is …Run Code Online (Sandbox Code Playgroud)