该程序(来自Jonathan Bartlett的Programming From the Ground Up)以.long
循环存储在内存中的所有数字,并将最大数字放在EBX寄存器中,以便在程序完成时查看。 / p>
.section .data
data_items:
.long 3, 67, 34, 222, 45, 75, 54, 34, 44, 33, 22, 11, 66, 0
.section .text
.globl _start
_start:
movl $0, %edi
movl data_items (,%edi,4), %eax
movl %eax, %ebx
start_loop:
cmpl $0, %eax
je loop_exit
incl %edi
movl data_items (,%edi,4), %eax
cmpl %ebx, %eax
jle start_loop
movl %eax, %ebx
jmp start_loop
loop_exit:
movl $1, %eax
int $0x80
我不确定(,%edi,4)
在此计划中的用途。我已经读过逗号用于分隔,而4用于提醒我们的计算机数据项中的每个数字都是4个字节长。既然我们已经声明每个数字是.long的4个字节,为什么我们需要在这里再做一次呢?此外,有人可以更详细地解释这两个逗号在这种情况下的用途是什么吗?
答案 0 :(得分:2)
在AT& T语法中,内存操作数有the following syntax 1 :
displacement(base_register, index_register, scale_factor)
基础,索引和位移组件可以任意组合使用,每个组件都可以省略
但很明显,如果省略基址寄存器,则必须保留逗号,否则汇编程序无法理解您遗漏哪些组件。
所有这些数据结合起来计算您指定的地址,使用以下公式:
effective_address = displacement + base_register + index_register*scale_factor
(顺便提一下,你几乎就是在英特尔语法中指定它的方式)。
因此,凭借这些知识,我们可以解读您的指示:
movl data_items (,%edi,4), %eax
匹配上面的语法,你会看到:
data_items
是排量; base_register
被省略,因此不会被放入上面的公式中; %edi
是index_register
; 4
是scale_factor
。所以,你要告诉CPU mov 一个 l ong从data_items+%edi*4
到注册%eax
。
*4
是必要的,因为数组的每个元素都是4字节宽,所以要将索引(在%edi
中)转换为数组开头的偏移量(以字节为单位)必须乘以4。
由于我们已经声明每个数字是.long的4个字节,为什么我们需要在这里再做一次呢?
汇编程序是低级别的工具,对类型一无所知。
.long
不是数组声明,只是汇编器发出与其参数的32位表示相对应的字节的指令; data_items
不是一个数组,只是一个符号被解析到某个内存位置,就像其他标签一样;事实上,在它之后放置了.long
指令对汇编程序没有特别的意义。<强> 备注 强>