[汇编] 第二个汇编程序

求一组数的最大值的汇编程序

#PURPOSE: This program finds the maximum number of a 
#         set of data items. 
# 
#VARIABLES: The registers have the following uses: 
# 
# %edi - Holds the index of the data item being examined 
# %ebx - Largest data item found # %eax - Current data item 
# 
# The following memory locations are used: 
# 
# data_items - contains the item data. A 0 is used 
# to terminate the data 
#
 .section .data 
data_items:             #These are the data items
 .long 13,53,15,74,24,74,24,66,35,21,82,0
 .section .text
 .globl _start
_start:
 movl $0, %edi          # move 0 into the index register 
 movl data_items(,%edi,4), %eax # load the first byte of data
 movl %eax, %ebx        # since this is the first item, %eax is
                        # the biggest
start_loop:             # start loop
 cmpl $0, %eax          # check to see if we've hit the end
 je loop_exit
 incl %edi              # load next value
 movl data_items(,%edi,4), %eax
 cmpl %ebx, %eax        # compare values
 jle start_loop         # jump to loop beginning if the new
                        # one isn't bigger
 movl %eax, %ebx        # move the value as the largest
 jmp start_loop         # jump to loop beginning
loop_exit:
 # %ebx is the status code for the _exit system call
 # and it already has the maximum number
 movl $1, %eax          #1 is the _exit() syscall
 int $0x80

汇编、链接、运行:

[test@localhost Assembler]$ as largest_data.s -o largest_data.o
[test@localhost Assembler]$ ld largest_data.o -o largest_data
[test@localhost Assembler]$ ./largest_data 
[test@localhost Assembler]$ echo $?
82

这个程序在一组数中找到一个最大的数,并把它作为程序的退出状态。这组数在 .data 段给出:

 .section .data 
data_items:             #These are the data items
 .long 13,53,15,74,24,74,24,66,35,21,82,0

.long 指示声明一组数,每个数占 32 位,相当于 C 语言中的数组。这个数组开头定义了一个符号 data_items,汇编器会把数组的首地址作为 data_items 符号所代表的地址,data_items 类似于C语言中的数组名。data_items 这个标号没有用 .globl 声明,因为它只在这个汇编程序内部使用,链接器不需要用到这个名字。除了 .long 之外,常用的数据声明还有:

  • .byte,也是声明一组数,每个数占 8 位
  • .ascii,例如 .ascii “Hello world”,声明 11 个数,取值为相应字符的 ASCII 码。

注意, 和C语言不同,这样声明的字符串末尾是没有 ‘\0’ 字符的,如果需要以 ‘\0’ 结尾可以声明为 .ascii “Hello world\0”data_items 数组的最后一个数是 0,我们在一个循环中依次比较每个数,碰到 0 的时候让循环终止。 在这个循环中:

  • edi 寄存器保存数组中的当前位置,每次比较完一个数就把 edi 的值加 1,指向数组中的下一个数。
  • ebx 寄存器保存到目前为止找到的最大值,如果发现有更大的数就更新 ebx 的值。
  • eax 寄存器保存当前要比较的数,每次更新 edi 之后,就把下一个数读到 eax 中。
_start:
 movl $0, %edi

初始化 edi,指向数组的第 0 个元素。

 movl data_items(,%edi,4), %eax

这条指令把数组的第 0 个元素传送到 eax 寄存器中。data_items 是数组的首地址,edi 的值是数组的下标,4 表示数组的每个元素占 4 字节,那么数组中第 edi 个元素的地址应该是 data_items + edi * 4,写在指令中就是 data_items(,%edi,4),这种地址表示方式之后会详细说明。

 movl %eax, %ebx

ebx 的初始值也是数组的第 0 个元素。下面我们进入一个循环,循环的开头定义一个符号 start_loop,循环的末尾之后定义一个符号 loop_exit

start_loop:
 cmpl $0, %eax
 je loop_exit

比较 eax 的值是不是 0,如果是 0 就说明到达数组末尾了,就要跳出循环。cmpl 指令将两个操作数相减,但计算结果并不保存,只是根据计算结果改变 eflags 寄存器中的标志位。如果两个操作数相等,则计算结果为 0,eflags 中的 ZF 位置 1。je 是一个条件跳转指令,它检查 eflags 中的 ZF 位,ZF 位为 1 则发生跳转,ZF 位为 0 则不跳转,继续执行下一条指令。可见比较指令和条件跳转指令是配合使用的,前者改变标志位,后者根据标志位决定是否跳转。je 可以理解成 “jump if equal”,如果参与比较的两数相等则跳转。

 incl %edi 
 movl data_items(,%edi,4), %eax

edi 的值加 1,把数组中的下一个数传送到 eax 寄存器中。

 cmpl %ebx, %eax 
 jle start_loop

把当前数组元素 eax 和目前为止找到的最大值 ebx 做比较,如果前者小于等于后者,则最大值没有变,跳转到循环开头比较下一个数,否则继续执行下一条指令。jle 表示 “jump if less than or equal”

 movl %eax, %ebx 
 jmp start_loop

更新了最大值 ebx 然后跳转到循环开头比较下一个数。jmp 是一个无条件跳转指令,什么条件也不判断,直接跳转。loop_exit 符号后面的指令调 _exit 系统调用退出程序。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值