【发布时间】:2020-11-07 00:32:50
【问题描述】:
我在汇编中遇到函数指针问题,即使我的函数返回负数,它总是将rax 设置为正数,我用一个比较两个整数的函数做了一个最小的可复制示例,它的作用相同事情:
ASM 功能代码[编辑]:
global foo
section .data
msg: db `superior\n`
msg_len: equ $-msg
section .text
foo:
push rbx
mov rbx, rdi
mov rdi, 2
mov rsi, 1
sub rsp, 8 ; align the stack frame
call rbx
add rsp, 8
test rax, rax ;[EDIT] correct: test eax, eax
js bar
mov rax, 1
mov rdi, 1
mov rsi, msg
mov rdx, msg_len
syscall
bar:
mov rdi, 1
mov rsi, 2
sub rsp, 8 ; same here
call rbx
add rsp, 8
test rax, rax ;[EDIT] correct: test eax, eax
js exit
mov rax, 1
mov rdi, 1
mov rsi, msg
mov rdx, msg_len
syscall
exit:
pop rbx ;restoring initial data of rbx
ret
main.c 代码:
#include <stdio.h>
int foo(int (*f)()); //my asm function prototype
int cmp(int i, int j)
{
printf("%d - %d\n", i, j);
return(i - j);
}
int main(void)
{
foo(&cmp);
return (0);
}
输出是:
2 - 1
superior
1 - 2
superior
但应该只是:
2 - 1
superior
编译:
nasm -f elf64 foo.s
gcc -c main.c -o main.o
gcc main.o foo.o
感谢您的帮助
[编辑] 它不起作用,因为我检查了 rax 而不是 eax,现在它起作用了。感谢您的帮助
【问题讨论】:
-
你的跳转指令不应该是标签foo中的JG吗? JA 不检查标志标志。
-
@The_aLiEn 也许吧,但 ja 不是代表“跳到上面”吗?
-
@The_aLiEn 我检查了 jg 也做了同样的事情
-
您的代码有多个 ABI 违规。它正在破坏属于调用者的
rbx,没有恢复它,并使用rsp未对齐mod 16 进行函数调用。我不确定这些是否是你所看到的来源,但真的有如果没有固定它们,它就没有希望可靠地工作。 -
@Fayeure:阅读wiki.osdev.org/System_V_ABI,“x86-64”部分,了解调用约定。这些是必须了解和遵循的。
rbx是一个被调用者保存的寄存器,你必须保存它;也就是说,您必须确保当您的函数返回时,rbx包含与输入函数时相同的值。您可以在函数开始时将其推入堆栈并在结束时将其弹出(这将代替您的堆栈调整)。但更简单的是使用调用者保存的“临时”寄存器代替;rax, rcx, rdx, r8, r9, r10, r11中的任何一个都可以。
标签: c assembly x86-64 nasm function-pointers