x86程序集jl不起作用

时间:2017-12-11 12:37:56

标签: ubuntu assembly x86 32-bit att

我在64位Ubuntu上使用x86汇编语言(AT& T语法)进行编码(所以我使用as --32ld -melf_i386,这对其他人一直很好到目前为止的练习。)

jl指令与我的预期相反。我实际上可以使代码与jg一起正常工作,这基本上可以解决我的问题,但我想在这里找出潜在的问题。

代码段如下:

   # Open file for reading
   movl $SYS_OPEN, %eax         # prepare syscall 5 
   movl $input_file_name, %ebx      # move input file name into %ebx
   movl $0, %ecx                    # open in read-only mode
   movl $0666, %edx     
   int $LINUX_SYSCALL               # execute system call,
                                   # sys_open returns file descriptor in %eax

   movl %eax, ST_INPUT_DESCRIPTOR(%ebp) # store the input file descriptor away

   # This will test and see if %eax is negative. 
   # If it is not negative, it will jump to continue_processing.
   # Otherwise it will handle the error condition that the negative number represents.
   cmpl $0, %eax
   jl continue_processing

   pushl $no_open_file_msg
   pushl $no_open_file_code
   call error_exit

continue_processing:

   # Open file for writing
   movl $SYS_OPEN, %eax         # prepare syscall 5 

......并且该计划仍在继续,但其余部分与此问题无关。

使用gdbgui进行调试,我看到open sys调用返回输入文件描述符(eax = 3)没有问题。 然后你比较0到3.如果我不是白痴,0< 3 jl指令should take you to continue_processingit does not。{/ p>

但是,如果我改为使用jg,它就可以了。打开系统调用returns 3 in eaxjg properly jumpscontinue_processing

我已经读过跳转操作数的顺序可能取决于汇编程序。这可能就是这种情况吗?使用gcc -m32 -nostdlib进行编译具有相同的行为。我也尝试将订单交换到cmpl %eax, $0,但我得到错误:操作数类型不匹配' cmp'。

或者只是这个32位代码在64位Ubuntu上运行这个事实的怪癖?

我正在阅读这本书Programming From the Ground Up。在页125上,书籍示例在.section .data之后插入jl continue_processing,插入一些标签和.ascii命令,然后在{.section .text之前恢复代码pushl $no_open_file_msg 1}}。为了清理代码,我已将.section .data整合到最顶层,因此不需要第二个.section .text。它似乎不会影响jl问题,但我想如果问题确实在那里,我会提及它。

1 个答案:

答案 0 :(得分:1)

在AT& T语法中,与Intel语法相比,操作数的顺序被交换。出于这个原因,

cmpl $0, %eax

实际上计算eax-0并设置标志而不是像你期望的那样计算0-eax。因此,所有标志的设置都与您最初的预期相反,导致您观察到的问题。没有办法解决这个问题,因为它并没有真正错误。我建议你习惯这个怪癖。

作为一般说明,使用testl指令而不是将值与零进行比较通常是个好主意。 testl %eax,%eax在机器代码中比cmp $0,%eax更紧凑,在某些微体系结构上也更快。 testl根据按位及其操作数设置标志,因此如果eax为负,则在testl %eax,%eax之后设置SF,您可以像这样检查:

testl %eax,%eax
jns continue_processing