微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

ASM x64函数指针未返回良好值

如何解决ASM x64函数指针未返回良好值

我在汇编中使用函数指针时遇到问题,即使我的函数返回一个负数,它总是将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,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 举报,一经查实,本站将立刻删除。