我在Linux 64位上学习NASM,并且一直在尝试实现一些代码示例。但是我在下面的示例中遇到了问题。函数donothing在NASM中实现,应该在用C:
实现的程序中调用文件main.c:
#include <stdio.h>
#include <stdlib.h>
int donothing(int, int);
int main() {
printf(" == %d\n", donothing(1, 2));
return 0;
}
档案first.asm
global donothing
section .text
donothing:
push rbp
mov rbp, rsp
mov eax, [rbp-0x4]
pop rbp
ret
所做的只不过是返回第一个参数的值。但是当调用donothing时,将打印值0而不是1.我尝试了rpb + 0x4,但它也不起作用。 我使用以下命令编译文件:
nasm -f elf64 first.asm && gcc first.o main.c
使用gcc -s在C中编译函数'test',生成的汇编代码看起来类似于donothing:
int test(int a, int b) {
return a > b;
}
gcc为上面的函数'test'生成的程序集:
test:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movl %edi, -4(%rbp)
movl %esi, -8(%rbp)
movl -4(%rbp), %eax
cmpl -8(%rbp), %eax
setg %al
movzbl %al, %eax
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
那么,什么是不好的?
答案 0 :(得分:4)
在x86-64 calling conventions中,前几个参数在寄存器中而不是在堆栈中传递。在您的情况下,您应该在1
和2
中找到RDI
和RSI
。
正如您在编译的C代码中看到的那样,来自a
的{{1}}和来自edi
的{{1}}(尽管通过放置它们会经历一个不必要的中间步骤)在记忆中)