将指针传递给汇编函数

2024-02-23

我对汇编编程相当陌生。我正在使用带有 GCC (Linux) 的 x86 平台。

我有一个我想从 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 into %eax (or %ebx等)然后用 printf 打印它%p,我看到它的地址和unsigned char指针的地址“s1“我传递的结果是相同的。但我怀疑我实际上所做的是获取内存地址,将其转换为整数,然后将该整数放入某个地址中。

例如,如果我这样做:

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

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

So...

  • 如何传入一个指针并将其保留为指针?
  • 如何在汇编中使用所述指针的值? (例如,像*ptr in C)

我想查看 LEA 操作数吗?

我使用 Richard Blum 的“专业汇编编程”作为我的指南,但 Blum 似乎没有涵盖这种情况。

Update

非常感谢您的博学回复!

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

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

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

至少有一个操作数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)
    

通常,解决此类问题的最简单方法是用 C 语言编写例程,然后对其进行编译并反汇编结果。

Edit 2:

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将指针传递给汇编函数 的相关文章

随机推荐