【问题标题】:Get the address at the end of a set of data?获取一组数据末尾的地址?
【发布时间】:2012-10-13 15:37:25
【问题描述】:

我一直在阅读“从头开始编程”一书来学习 Linux 中的汇编编程。我无法解决第 3 章末尾的一个练习。 练习说修改以下程序以使用数据集末尾的地址来终止循环。这只是一个简单的程序,用于查找一组数据中的最大数,目前它只是使用数字零来标记数据的结束。

#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:
    .long 3, 67, 34, 14, 45, 75, 54, 187, 44, 87, 22, 11, 66, 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                      # The biggest

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 the beginning if new value
                                        # Isn't larger
movl    %eax, %ebx                      # Move the value as the largest
jmp     start_loop                      # Jump to the beginning of loop

loop_exit:

# %ebx is the status code for the exit system call
# and it contains the maximum number
movl    $1, %eax                         # 1 is the exit() system call
int     $0x80

我知道我可以硬编码数据列表的长度,或者我可以将它存储在数据的第一个字节中,但是练习要求使用最后一个元素的地址来终止循环。书中提到使用符号来标记结束。我认为我的问题是我只是不明白如何获取地址。如果我知道如何获得它,我可以将它存储在寄存器中。任何帮助表示赞赏。

【问题讨论】:

    标签: linux assembly gnu-assembler


    【解决方案1】:

    带有一些适用于 Mac OSX 的小模组...

    .data
    
    data_items:
        .long 3, 67, 34, 14, 45, 75, 54, 187, 44, 87, 22, 11, 66, 0
    data_end:
    
    .text
    
    .globl    start
    start:
            movl    $0, %edi                       # Move 0 into the index register
            movl    data_items (, %edi, 4), %eax   # Load the first data value
            movl    %eax, %ebx                     # The biggest
            leal    data_end, %ecx                 # Load and save ending address
    
    start_loop:
            leal    data_items(, %edi, 4), %eax    # Get address of next value
            cmpl    %eax, %ecx                     # Check to see if we've hit the end
            je      loop_exit
            incl    %edi                           # Increment index
            movl    (%eax), %eax                   # Load value
            cmpl    %ebx, %eax                     # Compare values
            jle     start_loop                     # Jump to the beginning if new value
                                                   # Isn't larger
            movl    %eax, %ebx                     # Move the value as the largest
            jmp     start_loop                     # Jump to the beginning of loop
    
    loop_exit:
            movl    $1, %eax                       # 1 is the exit() system call
            pushl   %ebx
            pushl   $0
    
            int     $0x80
    

    【讨论】:

    • 这是一个非常优雅的解决方案,但是如果您只阅读本书的三章,您将无法立即理解,更不用说想出它了。首先,从不介绍真正的指令,仅在附录中提及。其次,我不确定它是否解释了前三章中这样定义的 data_end 将具有 data_items+1 的最后一个元素的地址。我想知道这是否真的是预期的解决方案。话虽如此,您可以不使用 data_end,但我不知道如何在没有 leal 的情况下访问 data_items 地址。
    • 这很棒。但是,我们可以去掉pushl %ebxpushl $0,进一步优化
    【解决方案2】:

    问问自己:我知道数据的起始地址吗?我怎么知道?我知道数据的大小吗?我怎么知道这个?我可以从这些信息中得知结束地址吗?

    【讨论】:

    • 这是我遇到的最后一个问题。
    • 如果您知道起始地址、数据中的项目数和每个元素的大小,您就可以计算出结束地址。如果您知道如何声明标签,则可以更轻松,也许您可​​以在最后一个元素附近声明一个?
    猜你喜欢
    • 2023-03-13
    • 2011-06-13
    • 1970-01-01
    • 2015-01-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-08
    • 1970-01-01
    相关资源
    最近更新 更多