Linux汇编实例讲解(二)——求最大值

     这篇文章讲解的是使用汇编语言找出一组数字的最大值,主要涉及的知识点有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寄存器中,因为最大值会作为程序退出时的状态码返回。

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。