Search code examples
linuxassemblygnugnu-assembler

How to pass a data list as an argument in GNU Assembly?


I have 3 different lists in the Data Section of my code. I intend to write a function to find the maximum number of these lists, whichever the user may want to use. How do I correctly pass the address of the required list to the function? And how to I obtain the values from the list using an index? I don't know the proper syntax for indexed addressing on an address I got as an argument. I couldn't find anything helpful on Google.

Here's the code:

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

It doesn't compile and shows the following error:

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

What's the proper way to obtain the address of the data list from the register %ecx to use for indexed addressing? Or the parameter?


My system is 64 bit, but I'm compiling it as a 32 bit binary (for compliance with this book)


Solution

  • Index addressing mode is like movq data_set(,%rbx,8), %rax.

    The syntax is like INSTRUCTION CONST(BASE_ADDR_REG,INDEX_REG,MULTIPLIER)

    You are allowed to omit the base register as I have in my example. The reason I omitted it is because my data address is not changing in my program, so I use it's immediate value instead.

    Where data_set is the base address (used as a constant), %rbx is the index and 8 is the multiplier...in my case 8 bytes because I am iterating quadword values.

    If I was iterating long values, like you are, I would use 4 as my multiplier because longs are generally 4 bytes (32 bits) on x86.

    Example Max Function

    .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