x86 程序集 jl 不起作用
x86 assembly jl doesn't work
我在 64 位 Ubuntu 上使用 x86 汇编(AT&T 语法)进行编码(所以我使用 as --32
和 ld -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 jumps 到 continue_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
我在 64 位 Ubuntu 上使用 x86 汇编(AT&T 语法)进行编码(所以我使用 as --32
和 ld -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 jumps 到 continue_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