我在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 $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_processing
,it does not。{/ p>
但是,如果我改为使用jg
,它就可以了。打开系统调用returns 3 in eax和jg
properly jumps到continue_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
问题,但我想如果问题确实在那里,我会提及它。
答案 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