将指针传递给汇编函数

rai*_*308 10 assembly

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

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

myfunc ( unsigned char * s1, unsigned char * s2, int someint );
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

movl  8(%esp), %ecx
movl  %ecx, someaddress
Run Code Online (Sandbox Code Playgroud)

如果我把somevar%eax(或%ebx等等),然后printf的它%p,我看到它的地址和无符号的字符指针"的地址,s1"我通过这都是一样的.但我怀疑我实际做的是获取内存地址,将其转换为整数,然后将该整数放入某个地址.

例如,如果我这样做:

movl  pos1, %eax
movl  pos2, %ebx
cmp   (%eax),(%ebx)
Run Code Online (Sandbox Code Playgroud)

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

所以...

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

我想查看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
Run Code Online (Sandbox Code Playgroud)

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;
}
Run Code Online (Sandbox Code Playgroud)

装配计划:

.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
Run Code Online (Sandbox Code Playgroud)

Car*_*rum 8

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

movl  8(%esp), %ecx
Run Code Online (Sandbox Code Playgroud)

在%esp + 8处获取4个字节并将它们放入%ecx.在类似C的伪代码中:

ecx = *(esp + 8);
Run Code Online (Sandbox Code Playgroud)

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

编辑 - 你的问题:

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

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

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

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

    movb (%ecx), %edx
    
    Run Code Online (Sandbox Code Playgroud)

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

    edx = *(unsigned char *)ecx;
    
    Run Code Online (Sandbox Code Playgroud)
  3. 我想查看LEA操作数吗?

    可能不是,根据您提供的问题描述.但总有可能. lea&C中的运算符一样工作.例如,这条指令:

    lea 12(%ecx), %edx
    
    Run Code Online (Sandbox Code Playgroud)

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

    edx = &(*(ecx + 12))
    
    Run Code Online (Sandbox Code Playgroud)

    或更简单地说:

    edx = ecx + 12
    
    Run Code Online (Sandbox Code Playgroud)

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

    lea 1(%edx,%ecx,4), %eax
    
    Run Code Online (Sandbox Code Playgroud)

    意思是:

    eax = &(edx[ecx * 4] + 1)
    
    Run Code Online (Sandbox Code Playgroud)

通常,解决这些问题的最简单方法是在C中编写例程,然后编译它并反汇编结果.

编辑2:

你的榜样方案似乎是对的,但你试图取消引用指针在内存中 - 让这些指针到寄存器第一,你应该确定.