I have an array and I'm loading the base address of this array into the %esi register. I can access the first element in the array for instance like this: pushl 0(%esi)
, the second like this: pushl 4(%esi)
, and so on. But I get an segmentation fault if I'm replacing the number before (%esi)
with a variable from the .data section:
.data
array: .long 1,2,3,4,5
k: .long 4
out: .string "out: %d\n"
.globl main
main:
#load array-baseaddress into %esi
leal array, %esi
# Will print 1
pushl 0(%esi)
pushl $out
call printf
# Will print 2
pushl 4(%esi)
pushl $out
call printf
# Will result in segmentation fault
pushl k(%esi)
pushl $out
call printf
call exit
Can somebody explain to me why this is not working and if it's possible to access an element of an array in such a manner?
First of all you have this at the top of your function main:
main:
# Will print 1
pushl 0(%esi)
pushl $out
call printf
The first issue is that you use indexed addressing (with displacement) with the value in ESI as the address. So you have the equivalent of the value at memory address ESI+0 . The problem is that you don't initialize ESI . You should be initializing it with the address of array . So change the code to:
main:
mov $array, %esi /* initialize ESI with address of array. */
# Will print 1
pushl 0(%esi)
pushl $out
call printf
In the last section of code you do:
# Will result in segmentation fault
pushl k(%esi)
pushl $out
call printf
You are looking to use the value in variable k as a displacement when you do k(%esi)
. Unfortunately indexed addressing (with displacement) only supports a displacement as a constant. In your case k(%esi)
is taking the address of k and adding it to ESI and pushing the value at that address on the stack. That isn't what you want. You can't do this in one operation. You'll have to retrieve the value in variable k and put it in a free register and then use that register to compute the address using based indexed addressing mode. You can do that with code like this:
movl k, %eax /* move 32-bit value in k to temporary register */
pushl (%esi, %eax) /* Push 32-bit value @ memory location %esi+%eax to stack */
pushl $out
call printf
The output would look like:
out: 1
out: 2
out: 2
From your code it is uncertain if k was holding an element number within the array or if it was just a byte offset in the array. If you were looking to access the kth element in the array (0 based) then you need to use a scaling factor on the based indexed addressing mode like this:
movl k, %eax /* move 32-bit value in k to temporary register */
pushl (%esi, %eax, 4) /* Push 32-bit value @ memory location %esi+(%eax*4) to stack */
pushl $out
call printf
This would print out the 4th element (0 based) in array or the value 5
in your case. The output would look like:
out: 1
out: 2
out: 5