将指针传递给汇编函数

时间:2011-03-04 00:12:45

标签: assembly

我对汇编编程很新。我正在使用x86平台和GCC(Linux)。

我有一个我想从C调用的函数:

myfunc ( unsigned char * s1, unsigned char * s2, int someint );

该函数将获取s1和s2存储器位置并进行比较,然后递增和比较等,进行一些处理。这有点像memcmp,但我做得更多。

我的问题:如果我将指针传递给汇编函数? 然后我怎么说“给我存储在这个内存地址的值”?

这是我到目前为止所拥有的:

要从堆栈中获取第一个函数arg(“s1”),我这样做(someaddress是一个32位整数,我正在使用32位处理器):

movl  8(%esp), %ecx
movl  %ecx, someaddress

如果我将somevar放入%eax(或%ebx等),然后使用%p打印,我会看到它的地址和无符号的地址char指针“s1”我通过它是一样的。但我怀疑我实际做的是获取内存地址,将其转换为整数,然后将该整数放入某个地址。

例如,如果我这样做:

movl  pos1, %eax
movl  pos2, %ebx
cmp   (%eax),(%ebx)

我得到“错误:'cmp'的内存引用太多了”。我不完全确定这意味着什么,除了“你搞砸了”; - )

因此...

  • 如何传入指针并将其作为指针保存?
  • 如何在程序集中使用所述指针的值? (例如,像C中的*ptr

我想查看LEA操作数吗?

我正在使用Richard Blum的“专业装配编程”作为我的向导,但Blum似乎没有涵盖这种情况。

更新

非常感谢您的学习回应!

不幸的是,我仍然无法取消引用。

这是一个简化的例子。汇编函数接受指针并应该回显它。相反,我得到:

first_ptr points to 81 (should be 81) <-- from C program
the value is -1543299247 <-- printf called from within assembler
the value is -6028513 <-- printf called from within assembler
my function returned -6028513 <-- return value printed from C program

C计划:

#include <stdio.h>
#include <string.h>

int main (void) {
        unsigned char first;
        unsigned char * first_ptr;

        first = 'Q';
        first_ptr = &first;

        printf ("first_ptr points to %i (should be 81)\n",*first_ptr);

        printf ("my function returned %i\n", myfunc(first_ptr));
        return 0;
}

装配程序:

.section .data

msg:
  .asciz "the value is %i\n"

.section .bss
.lcomm str, 8

.section .text
.type myfunc, @function
.globl myfunc
myfunc:

  # save stack
  pushl %ebp
  movl  %esp, %ebp

  # save string arg from stack to "str"
  movl  8(%esp), %ecx
  movl  %ecx, str

  # let's try printing the ecx dereference

  pushl (%ecx)
  pushl $msg
  call printf

  # put the value of str on the stack 
  # and call printf

  pushl (str)
  pushl $msg
  call printf

  # now return the character at pos1
  movl  (str), %eax

  # restore the stack
  movl  %ebp, %esp
  popl  %ebp

  ret

1 个答案:

答案 0 :(得分:8)

cmp的至少一个操作数必须是寄存器。如果您要尝试比较两个内存位置的内容,则需要将其中一个放入寄存器中。怎么把它放到你问的寄存器里?那么你已经完成了你的示例代码。这一行:

movl  8(%esp), %ecx

占用%esp + 8的4个字节并将它们放入%ecx。在类似C的伪代码中:

ecx = *(esp + 8);

希望这是有道理的。您可以执行类似的操作,使指针离开堆栈并进入寄存器,然后取消引用它们,比较取消引用的值,等等。如果您有更多问题,请与我们联系!

编辑 - 您的问题:

  1.   

    如何传入指针并将其作为指针保存?

    你已经这样做了,你的movl 8(%esp), %ecx指令或类似的指令会做你需要的一切。

  2.   

    如何在程序集中使用所述指针的值? (例如,像C中的* ptr)

    您需要再次使用() - 从上面的指令加载%ecx中指针的第一个字节,例如:

    movb (%ecx), %edx
    

    类似于我上面使用它的C类伪代码,这条指令是:

    edx = *(unsigned char *)ecx;
    
  3.   

    我想查看LEA操作数吗?

    可能不是,根据您提供的问题描述。但总有可能。 lea的工作方式类似于C中的&运算符。例如,此指令:

    lea 12(%ecx), %edx
    

    可以翻译成我们的伪代码:

    edx = &(*(ecx + 12))
    

    或更简单:

    edx = ecx + 12
    

    这个例子有点傻,因为我们使用的是相对简单的寻址模式,但是这样的事情怎么样:

    lea 1(%edx,%ecx,4), %eax
    

    表示:

    eax = &(edx[ecx * 4] + 1)
    
  4. 通常,解决这些问题的最简单方法是在C中编写例程,然后编译它并反汇编结果。

    编辑2:

    你的示例程序看起来几乎是正确的,但是你试图在内存中取消引用指针 - 首先将这些指针放到寄存器中,你应该没问题。