x86 程序集 jl 不起作用

x86 assembly jl doesn't work

我在 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 [=10=], %ecx                    # open in read-only mode
   movl 66, %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 [=10=], %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 调试,我看到打开的系统调用 returns 输入文件描述符 (eax = 3) 没有问题。 然后你比较 0 和 3。如果我不是白痴,0 < 3 所以 jl 指令 should take you to continue_processing, but it does not.

但是,如果我改为使用 jg,它会起作用。打开系统调用 returns 3 in eax and jg properly jumpscontinue_processing.

我了解到跳转操作数的顺序可能取决于汇编程序。会不会是这里的情况?使用 gcc -m32 -nostdlib 编译具有相同的行为。我也尝试将顺序交换为 cmpl %eax, [=21=] 但我收到错误:'cmp'.

的操作数类型不匹配

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

我正在看书Programming From the Ground Up。在第 125 页,书本示例在 jl continue_processing 之后插入了一个 .section .data,插入了一些标签和 .ascii 命令,然后在 [=] 之前使用 .section .text 恢复了代码26=]。为了清理代码,我在顶部合并了 .section .data,因此不需要第二个 .section .text。它似乎不会影响 jl 问题,但我想我会提到它以防问题确实存在。

在 AT&T 语法中,与 Intel 语法相比,操作数的顺序是互换的。为此,

cmpl [=10=], %eax

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

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

testl %eax,%eax
jns continue_processing