这篇文章讲解的是使用汇编语言找出一组数字的最大值,主要涉及的知识点有data段、循环等。
# 目的:在程序中找出最大的数字 # # 变量:寄存器的用途定义 # %edi - 保存正在检查的数据项索引 # %ebx - 当前已找到的最大项 # %eax - 当前数据 # # 使用以下内存位置: # data_items - 包含数据项 # 0表示结束 # .section .data data_items: .long 3, 68, 12, 37, 198, 10, 1, 4, 26, 255, 11, 22, 33, 44, 0 .section .text .globl _start _start: movl $0, %edi #将0移入索引寄存器 movl data_items(,%edi,4), %eax #加载数据项的第一个字节 movl %eax, %ebx #由于是第一项,%eax就是最大值 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
代码详解:
1. 代码的执行结果为:
echo $?输出的结果为255是因为在基数数组为:
3, 68, 12, 37, 198, 10, 1, 4, 26, 255, 11, 22, 33, 44
在这个数组中,最大的数字为255,如果将255去掉或者换成别的数字,则会输出别值,例如我们将值换成168,则”echo $?“应该输出198:
程序输出的结果为:
2.下面从头开始分析代码的结构:
(1)以#开头的为注释,这里不再解释
(2)
.section .data data_items: .long 3, 68, 12, 37, 198, 10, 1, 4, 26, 255, 11, 22, 33, 44, 0
该段代码定义了程序所要使用的数据,其中date_items是一个标签,到时候其会被实际的内存地址所替代。
.long 定了了数据的类型,在32位系统中long类型的数据占4字节(byte)。long后面跟的是实际要使用的数字。
汇编语言中主要的数据类型:
.byte 每个字节类型的数字占用一个存储位置,数字范围0~255
.int 每个整型数字(这种类型与int指令不同)占用两个存储位置,数字范围为0~65535.
.ascii 该指令用于将字符串输入内存。每个字符占用一个存储位置。
(3)
_start: movl $0, %edi #将0移入索引寄存器 movl data_items(,%edi,4), %eax #加载数据项的第一个字节 movl %eax, %ebx #由于是第一项,%eax就是最大值movl data_items(,%edi,4), %eax这句是加载数据项的第一个,因为%edi寄存器中的值为0,则实际地址是data_items + %edi * 4--> data_items + 0;
(4)
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该段代码为循环控制结构。其中start_loop只是一个标签,标记循环指令开始的位置。语句“cmpl $0, %eax”判断寄存器%eax中的值是否为0,如果为0则直接跳转到loop_exit指令处。如果不为0,则继续往下执行。这是因为我们使用0作为所有数字的结束标志,当然也可以换成别的。语句“incl %edi”表示将%edi寄存器中的值加1,这样在下一指令(“movl data_items(,%edi,4), %eax”)中可以得到下一个数字的地址,语句“cmpl %ebx,
%eax”用来比较两个数字的大小,下一条语句“jle start_loop”则表示如果上一个比较结果是%eax中的值小于或等于%ebx中的值,则程序跳转到start_loop处,即程序循环的开始,如果不是小于或等于的情况,则表示%eax中的数字大于%ebx中的数字,需要将%eax中的值放到%ebx寄存器中,因为最大值会作为程序退出时的状态码返回。