2

Hello I'm new in assembly language. I read a book to improve my knowledge (Programming from the ground up).

I understand the following example, there is a question which demand to modify the program and make it stop when reaches an ending address. I don't know how to print the current address in assembly or to compare it with a number. And is it correct to use cmpl $13, %edi to detect when end of data_items has been reached ?

.section .data
data_items:             #These are the data items
.long 3,67,34,222,45,75,54,34,44,33,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                 # since this is the first item, %eax is
                                # the biggest
start_loop:                     # start loop
#cmpl $22, %eax                 # check to see if we’ve hit the end using Value
#cmpl $13, %edi                 # Using Length to break loop

#I have to add a condition here  to use an ending address 
#rather than the number 0 to know when to stop.

je loop_exit
incl %edi                       # load next value
movl data_items(,%edi,4), %eax
cmpl %ebx, %eax                 # compare values
jle start_loop                  # jump to loop beginning if the new
                                # one isn’t bigger
movl %eax, %ebx                 # move the value as the largest
jmp start_loop                  # jump to loop beginning
loop_exit:
    # %ebx is the status code for the exit system call
    # and it already has the maximum number
            movl $1, %eax   #1 is the exit() syscall
            int $0x80
Michael
  • 57,169
  • 9
  • 80
  • 125
  • 1
    _"And please It is true to use : cmpl $13, %edi to stop using the Length?"_ What happened when you tried it? – Michael Apr 29 '20 at 16:43
  • @Michael It worked I just want to make sure if it's the right instruction to do. – Youssef Dehane Apr 29 '20 at 17:27
  • 1
    Use a debugger to print registers and symbol addresses. If you don't know how to do that yet, that's the first thing you need to learn. – Peter Cordes Apr 29 '20 at 17:31
  • 1
    Well, 13 is the index of that final 0 in the array. So if that's where you want to stop, then I guess that `cmpl` is correct. Note that you're not really comparing addresses; you're comparing indexes. – Michael Apr 29 '20 at 17:32
  • @PeterCordes Is there any solution to set a limite for our loop using adress? I tried something like cmpl data_items(,13,4),data_items(,%edi,4) but it not working – Youssef Dehane Apr 29 '20 at 19:13
  • 1
    Try it in C. How would you use pointers to determine the end? Compute the end location in advance of the loop and later the loop is done when your incrementing pointer reaches that precomputed value. – Erik Eidt Apr 29 '20 at 20:13

1 Answers1

-1

It seems like you're trying to determine whether you've reached the end of data_items by comparing it to a number. What you can do is use a loop to help with that. Here's what I came up with:

.section .data
data_items:
        .long 4,73,121,133,236,251,252
data_items_size:
        .byte 7

.section .text
.globl _start
_start:
        movl $0, %edi
        movl data_items(,%edi,4), %eax
        movl %eax, %ebx
        movl $1, %ecx

        loop:
                cmpl data_items_size, %ecx
                je   exit
                incl %ecx

                incl %edi
                movl data_items(,%edi,4), %eax
                cmpl %eax, %ebx
                jge  loop
                movl %eax, %ebx
                jmp  loop

        loop_exit:
                movl $1, %eax
                int  $0x80

The data_items_size label contains the size of data_items. In this example, I used the %ecx register as a counter for the loop. I tried it and I got 252 as the exit status code, and when I added 253 at the end, I still got 252. So it seems to be working. Hope I helped you out :).

0xPictor
  • 63
  • 6
  • `data_items_size: .byte 7` only emits a single byte into the data section. But `cmpl data_items_size, %ecx` loads 4 from that address. Don't do that. Much better would be to do `data_items_size = (. - data_items) / 4` to get the assembler to calculate the size for you as an assemble-time constant, instead of loading a hard-coded value from memory. Then `cmp $data_items_size, %ecx`. – Peter Cordes May 06 '20 at 07:29
  • It's also inefficent to have EDI and ECX as nearly equivalent loop counters that both get incremented in lockstep; just adjust your end condition so you can CMP EDI. Or even better, just increment a pointer and compare it against an actual end *address*. In your current version, the `data_items_size` label is right after the array, i.e. at one-past-the-end of the array like a C++ `std::end` iterator that you can use to make a `do {} while(++ptr < endptr)` loop. ([Why are loops always compiled into "do...while" style (tail jump)?](https://stackoverflow.com/q/47783926)) – Peter Cordes May 06 '20 at 07:31
  • Take a look at how a compiler would do it. [How to remove "noise" from GCC/clang assembly output?](https://stackoverflow.com/q/38552116). e.g. https://godbolt.org/z/5fT_3P with `gcc -Og` to actually branch instead of optimizing to cmov, and `clang -O2` which cleverly indexed relative to the end of the array so it can count up toward `0` and branch on flags set by incrementing a byte-offset. If you want to play around with higher optimization levels, make the array much bigger so compilers don't fully unroll the loop, like `int data_items[10240] = {1,2,3};` – Peter Cordes May 06 '20 at 07:40