【问题标题】:How to pass a data list as an argument in GNU Assembly?如何在 GNU Assembly 中将数据列表作为参数传递?
【发布时间】:2017-03-03 21:37:27
【问题描述】:

我的代码的数据部分中有 3 个不同的列表。我打算编写一个函数来查找这些列表的最大数量,无论用户可能想要使用哪个。如何正确地将所需列表的地址传递给函数?以及如何使用索引从列表中获取值?我不知道作为参数获得的地址上的索引寻址的正确语法。我在 Google 上找不到任何有用的信息。

代码如下:

maxfunc.s

# NAME:     maxfunc.s
# PURPOSE:  A modular approach of finding the maximum of lists

    .section .data
    # The data section has three lists for testing, change the code
    # highlighted in the text section to change the list passed.
data_1:
    .long 1, 2, 3, 4, 5, 6, 7, 8, 9, 0
data_2:
    .long 23, 45, 62, 13, 87, 54, 0
data_3:
    .long 1, 2, 3, 3, 3, 7, 6, 5, 8, 1, 1, 0

# VARIABLES:
# 1. %edi - Will be our index variable, to access the items
# 2. %ebx - The element we're looking at currently
# 3. %eax - The maximum value we've found so far
# 4. %ecx - To store the address of the list


    .section .text
    # Push the address of the list we want to find the maximum of
    pushl   data_1
    #            ^
    #            +---> Change this to select your list

    call    maximum
    addl    $4, %esp    # Reset the stack

    movl    %eax, %ebx
    movl    $1, %eax
    int     $0x80

    .type   maximum, @function
maximum:
    # Setup
    popl    %ebp
    movl    %esp, %ebp

    # The initial setup:
    # Get the address of the list
    # Set the index to 0
    # Get the first item from the list
    # The first item is currently the largest
    movl    $0, %edi
    movl    8(%ebp), %ecx
    movl    (%ecx)(, %edi, 4), %ebx
    movl    %ebx, %eax

max_loop:
    cmpl    $0, %ebx
    je      exit_loop

    incl    %edi
    movl    (%ecx)(, %edi, 4), %ebx

    cmpl    %eax, %ebx
    jle     max_loop

    # %ebx is greater than %eax, therefore, update max
    movl    %ebx, %eax
    jmp     max_loop

exit_loop:
    # Tear down
    movl    %ebp, %esp
    popl    %ebp
    ret

它没有编译并显示以下错误:

maxfunc.s: Assembler messages:
maxfunc.s:47: Error: register value used as expression
maxfunc.s:55: Error: register value used as expression

从寄存器%ecx 获取数据列表的地址以用于索引寻址的正确方法是什么?还是参数?


我的系统是 64 位的,但我将其编译为 32 位二进制文​​件(为了符合 this book

【问题讨论】:

    标签: linux assembly gnu gnu-assembler


    【解决方案1】:

    索引寻址模式类似于movq data_set(,%rbx,8), %rax

    语法类似于INSTRUCTION CONST(BASE_ADDR_REG,INDEX_REG,MULTIPLIER)

    您可以像我在示例中那样省略基址寄存器。我省略它的原因是因为我的数据地址在我的程序中没有改变,所以我使用它的立即值。

    data_set 是基地址(用作常量),%rbx 是索引,8 是乘数……在我的例子中是 8 个字节,因为我正在迭代四字值。

    如果我像您一样迭代 long 值,我会使用 4 作为乘数,因为 x86 上的 long 通常是 4 个字节(32 位)。

    最大函数示例

    .section .data
        data_set: .quad 8, 1, 98, 18, 18, 12, 18, 19, 27, 32, 9, 12, 18, 92, 255, 0
    
    .section .text
    .globl _start
    
    
    # rbx, data index
    # rdi, current max
    # rax, current data
    _start:
        movq $0, %rbx # init index reg
        movq data_set(,%rbx,8), %rax
        movq %rax, %rdi
    
    loop:   
        cmpq $0, %rax # check if end
        je exit
        incq %rbx
        movq data_set(,%rbx,8), %rax
        cmpq %rdi, %rax
        jle loop
    
        movq %rax, %rdi
        jmp loop
    
    exit:
        movq $60, %rax
        syscall
    

    【讨论】:

    • 是的,但我想将其移至以data_set 作为参数的函数。我已经熟悉你发布的代码了。
    • 我试过了......它不起作用......或者我不知道正确的方法。 (查看代码和错误)
    • 试试movl (%ecx, %edi, 4), %ebx
    • 它可以编译,但我遇到了 Seg Fault。我最终会修复它。谢谢你的帮助。 :-) 当我的代码完美运行时,我会接受你的回答。
    • pushl data_1 推送data_1 数组中第一个元素的值。您的评论和代码有冲突。您肯定打算推送直接地址值。更改为pushl $data_1.... 现在popl 可以恢复正确的值了。
    猜你喜欢
    • 2010-11-30
    • 1970-01-01
    • 2013-04-21
    • 2014-12-03
    • 2022-01-02
    • 2017-05-20
    • 2013-11-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多