X86汇编 - 处理数组类型参数

时间:2012-05-17 14:45:35

标签: c assembly compiler-construction x86

我目前正在编写一个简单的C编译器,它将.c文件作为输入并生成汇编代码(X86,AT& T语法)。我很难传递数组类型的参数并为它生成正确的汇编代码。这是我的意见:

int getIndexOne(int tab[]){
  return tab[1];
}

int main_test(void){
  int t[3];
  t[0] = 0;
  t[1] = 1;
  t[2] = 2;
  return getIndexOne(t);
}

一个相当简单的测试。这是我的输出:

getIndexOne:
.LFB0:
    .cfi_startproc
    pushl   %ebp
    .cfi_def_cfa_offset 16
    movl    %esp, %ebp
    .cfi_offset 6, -16
    .cfi_def_cfa_register 6
    movl    %edi, -24(%ebp)
    movl    $1, %eax
    movl    -24(%ebp, %eax, 8), %eax    #trouble over here
    leave
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc
.LFE0:
    .size getIndexOne, .-getIndexOne


falsemain:
.LFB1:
    .cfi_startproc
    pushl   %ebp
    .cfi_def_cfa_offset 16
    movl    %esp, %ebp
    .cfi_offset 6, -16
    .cfi_def_cfa_register 6
    pushl   %ebx
    subl    $120, %esp
    movl    $2, -32(%ebp)
    movl    $0, %eax
    movl    $0, -24(%ebp, %eax, 8)
    movl    $1, %eax
    movl    $1, -24(%ebp, %eax, 8)
    movl    $2, %eax
    movl    $2, -24(%ebp, %eax, 8)
    leal    -24(%ebp, %eax, 8), %eax
    movl    %eax, %edi
    call    getIndexOne
    addl    $120, %esp
    popl    %ebx
    leave
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc
.LFE1:
    .size main_test, .-main_test

我无法访问传递的地址(leal指令)的内容。任何帮助将非常感激。 PS:不要担心我的整数大小,由于其他原因,它们被设置为8而不是4个字节。

1 个答案:

答案 0 :(得分:2)

有两个问题,第一个问题是当您为getIndexOne的呼叫设置堆栈时:

movl    $2, %eax
movl    $2, -24(%ebp, %eax, 8)
leal    -24(%ebp, %eax, 8), %eax   ##<== EAX still holds value of 2!
movl    %eax, %edi                 ##<== wrong address for start of array

您没有在EAX命令之后清除MOV寄存器的内容,因此您放入函数调用的EDI寄存器的地址未指向到数组的开头,但是数组的最后一个元素(即第二个索引的元素值为2)。

第二个问题出现在getIndexOne函数中:

movl    %edi, -24(%ebp)
movl    $1, %eax
movl    -24(%ebp, %eax, 8), %eax

您已将地址存储在堆栈中。这很好,但这也意味着当你从堆栈中检索到值时,你会得到一个指针,然后必须再次取消引用第二次。你现在正在做的是你只是从堆栈上的帧指针读回一个值偏移...这不是数组中的值,因为你没有取消引用存储在堆栈中的指针。换句话说,如果必须将指针存储在堆栈上,则应将其更改为以下内容(我认为这不是最有效的方法,因为该值已经在EDI中,但无论如何):

movl    %edi, -24(%ebp)           ##<== store pointer to the array on the stack
movl    $1, %eax
movl    -24(%ebp), %ecx           ##<== get the pointer back from the stack
movl    (%ecx, %eax, 8), %eax     ##<== dereference the pointer

作为旁注,虽然我不确定你的编译器是如何工作的,但我确实认为你使用加载到数组元素中的值来索引数组有点可怕......如果正在加载的值与数组索引不匹配,这会产生相当多的havok ......我猜这是两种值匹配时你试图做的某种类型的优化?