如何在 x86 中比较地址

How to compare addresses in x86

下面是一个 x86 程序,用于从数字列表中查找最大数字。当到达结束地址时,我试图退出循环。 (在源码中用data_ends:标签标注)

# Program to find maximum number
# Program should end when an ending address is reached
.section .data
.globl data_items                   
data_items:
#These are the data items
.long 3,67,34,222,45,75,54,34,44,33,22,11,66
data_ends:
.section .text
.globl _start                        
_start:
movl [=10=], %edi                        
movl data_items(,%edi,4), %eax       
movl %eax, %ebx                      
start_loop:
incl %edi
# Problem in below line
cmpl data_items(,%edi,4), data_ends
je loop_exit
movl data_items(,%edi,4), %eax
cmpl %ebx, %eax
jle start_loop
movl %eax, %ebx
jmp start_loop
loop_exit:
movl , %eax
int [=10=]x80

然而,从下面的 as 输出可以看出,cmpl data_items(,%edi,4), data_ends 行有一些问题。

user $ as maxNum.s -o maxNum.o
maxNum.s: Assembler messages:
maxNum.s:28: Error: too many memory references for `cmp'
user $

cmpl 指令的语法似乎有误。我该如何解决这个问题?

cmpl data_items(,%edi,4), data_ends有两个内存操作数。 cmp 不像 lea。如果你给它一个内存操作数,它就会从中加载。

cmp $(data_ends - data_items) / 4, %edi 应该可以解决问题。使用您的源代码,汇编为 cmp [=14=]xd,%edi。请注意,您 不是 比较地址,而是将循环计数器(用作索引)与循环计数进行比较。

如果您从寄存器中的指针开始,每次迭代将其递增 4,那么比较地址就有意义了。为此,您可以比较两个寄存器,或一个寄存器和一个立即数。 (符号地址是一个编译时常量,可用作立即操作数。请记住,您需要的是地址本身,而不是存储在那里的内容。)

有关两种循环结构的示例(带偏移的索引与递增指针和比较结束),请参阅 my answer to another beginner question.

中的两个代码块

此外,您应该将只读数据放在 .rodata 部分,而不是 .data。你应该缩进你的说明而不是你的标签。这有助于 lot 的可读性。