assembly 即使转换成功,scanf后的JL也会跳转?函数是否根据其返回值设置FLAGS?

fjnneemd  于 2022-12-13  发布在  其他
关注(0)|答案(1)|浏览(98)

我想用scanf来获取输入,我的想法是循环scanf直到它返回负数(错误)。由于某种原因scanf将第一个输入存储在指定的变量中并返回负数,它不应该正确地完成它?下面是我的代码的一部分

.global main
main:
    movl $var, %edx
in:
    push %edx
    push $inp
    call scanf
    jl done
    add $8, %esp
    add $4, %edx
    jmp in
done:
    ...
.data
inp: .asciz "%d"
var: .space 4*100

我用的是AT&T汇编

dffbzjpn

dffbzjpn1#

函数在EAX中返回(对于整数/指针),而不是FLAGS。

**您需要test %eax,%eax**根据返回瓦尔设置FLAGS,然后才能对其进行分支。

函数不会为您做这些。
在i386 System V的调用约定中(像所有标准的调用约定一样),FLAGS是call-crobbered的,所以对条件代码中保留什么函数没有要求。(该约定确实要求在call和ret时DF=0)。它并不长,也不容易阅读。
或者,您可以看看编译器是怎么做的,因为编译器创建的全局(非static)函数将遵守ABI是一个很好的假设。int foo(){return 1;}编译为mov $1, %eax; ret,这会使FLAGS不受影响。(https://godbolt.org/z/3a1jjaeM1
在手工编写的asm中,使用自定义的调用约定是完全可以的,其中FLAGS保存返回值,或者是返回值之一。(Asm没有C中只有一个按值返回值对象的恼人限制。)参见 * Is it considered bad practice to use the flags register as a boolean return value? *(不,MacOS / FreeBSD对系统调用也是这样做的。)
还要注意,EDX是被调用的;为指针选择一个不同的寄存器,如EDI、ESI或EBX,这样scanf就不会破坏它。

相关问题