如何解决ASM x64函数指针未返回良好值
我在汇编中使用函数指针时遇到问题,即使我的函数返回一个负数,它总是将rax
设置为一个正数,我还是做了一个最小的可复制示例,该函数比较了两个整数,并且同一件事:
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,2
sub rsp,8 ; same here
call rbx
add rsp,rax ;[EDIT] correct: test eax,eax
js exit
mov rax,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
感谢您的帮助
[EDIT]它不起作用,因为我检查了rax而不是eax,现在可以了。谢谢您的帮助
解决方法
int
是32位,而rax
是64位寄存器。返回int
的函数会将其返回值放在eax
中,这通常会将rax
的上半部分归零。因此,如果cmp
返回-1
,即32位数字0xffffffff
,则rax
将包含0x00000000ffffffff
。这不是一个负的64位数字,因此test rax,rax
不会设置符号标志。
尝试使用test eax,eax
作为测试。
您的代码似乎太复杂了。
首先,让我们用C之类的语言编写要做的事情:
int foo(int (*f)()) {
if (cmp(2,1) > 0) {
PRINT;
}
if (cmp(1,2) > 0) {
PRINT;
}
}
然后,让我们根据以下代码编写汇编代码:
global foo
section .data
msg: db `superior\n`
msg_len: equ $-msg
section .text
; int foo(int (*f)()) {
foo:
mov rbx,rdi ; function pointer stored in rbx
; if (cmp(2,1) > 0) {
mov rdi,2 ; first integer
mov rsi,1 ; second integer
call rbx ; call function pointer
cmp rax,0
jle bar ; jump if rdi <= rsi (signed)
; PRINT;
mov rax,1
mov rdi,1
mov rsi,msg
mov rdx,msg_len
syscall ; write "superior\n"
; }
bar:
; if (cmp(1,2) > 0) {
mov rdi,2
call rbx
cmp rax,0
jle bar2
; PRINT;
mov rax,msg_len
syscall ; write "superior\n"
; }
bar2:
; }
ret
要保留您的代码,要解决的问题是:
-
ja
用于无符号比较。应该使用jg
来进行比较。 - 在
bar2
之后有一些代码要打印,但是在未执行跳转ja bar2
之后也有一些代码要打印。您应在ret
之前添加bar:
,以防止执行此操作。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。