指针传递到汇编函数 [英] Passing a pointer to an assembly function

查看:157
本文介绍了指针传递到汇编函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是相当新的汇编编程。我使用的是x86平台与海湾合作委员会(Linux)的。

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

  MYFUNC(无符号字符* S1,无符号字符* S2,INT someint);

该功能将S1和S2的内存位置并加以比较,然后增加和比较等方面,做了一些处理,因为它去。这有点像memcmp但我做得更多。

我的问题:如果我通过一个指针到一个汇编函数?
然后,我怎么说给我存储在这个内存地址值?

下面是我到目前为止有:

要得到第一个功能ARG(S1)从堆栈中,我这样做(someaddress是一个32位的整数,我的工作在32位处理器):

  MOVL 8(%ESP),ECX%
MOVL%ECX,someaddress

如果我把 somevar %EAX (或%EBX 等),然后用%p 的printf它,我看到它的地址和无符号的字符指针的地址 S1 我通过这都是一样的。但我怀疑,我实际上已经做的是采取的内存地址,它转换成整数,然后放入someaddress该整数。

例如,如果我再这样做:

  MOVL POS1,EAX%
MOVL POS2,EBX%
CMP(%EAX)(%EBX)

我收到错误:'CMP'太多的内存引用。我不能完全肯定这意味着什么,除了你搞砸了; - )

所以...


  • 如何传递一个指针,并把它作为一个指针?

  • 如何使用所述指针的值在装配? (例如,如 * PTR 在C)

我想看看机关操作?

我使用的是理查德·布鲁姆的专业汇编编程为我的指导,但是百隆似乎并不包括这种情况。

更新

非常感谢你为你的回应得知!

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

下面是一个简化的例子。汇编函数需要一个指针,应该呼应回来。相反,我得到:

  first_ptr点81(应为81)<  - 从C程序
该值为-1543299247< - 从printf的汇编中调用
该值为-6028513< - 从汇编中所谓的printf
我的函数返回-6028513< - 从C程序印刷返回值

C程序:

 的#include<&stdio.h中GT;
#包括LT&;&string.h中GT;诠释主要(无效){
        unsigned char型第一;
        无符号字符* first_ptr;        第一=Q;
        first_ptr =放大器;第一;        的printf(first_ptr指向%I(应为81)\\ n,* first_ptr);        的printf(我的函数返回%I \\ N,MYFUNC(first_ptr));
        返回0;
}

汇编程序:

  .section伪。数据味精:
  .asciz值%I \\ N.section伪的.bss
.lcomm海峡,8.section伪的.text
.TYPE MYFUNC,@function
.globl MYFUNC
MYFUNC:  #保存堆栈
  pushl%EBP
  MOVL%ESP,EBP%  #保存字符串ARG从堆栈STR
  MOVL 8(%ESP),ECX%
  MOVL%ECX,STR  #让我们尝试打印ECX提领  pushl(ECX%)
  pushl $味精
  调用printf  #放str的值在堆栈上
  #和调用printf  pushl(STR)
  pushl $味精
  调用printf  #现在POS1返回字符
  MOVL(STR),EAX%  #恢复栈
  MOVL%EBP,ESP%
  popl%EBP  RET


解决方案

至少有一个操作数为 CMP 必须是一个寄存器。如果你想比较两个存储单元的内容,你需要把其中的一个在寄存器中。如何得到它变成你问一个寄存器?那么您已经在你的榜样code刚刚做了已经。该行:

  MOVL 8(%ESP),ECX%

注意到4个字节%ESP + 8,并将它们放入%ecx中。在C类伪code:

  ECX = *(ESP + 8);

希望这是有道理的。你可以做类似的操作,让您的指针从栈中和到寄存器,然后解引用它们,比较提领值,依此类推。让我知道如果您有更多问题!

编辑 - 你爆发的问题:



  1.   

    如何传递一个指针,并把它作为一个指针?


    你已经这样做,你的 MOVL 8(%ESP),ECX%指令,或类似的东西会做你需要的一切。



  2.   

    如何使用所述指针的值在装配? (例如,像C * PTR)


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

      MOVB(ECX%),EDX%

    在C-仿伪$ C $相似,我是如何使用它上面C,该指令是:

      EDX = *(无符号字符*)ECX;



  3.   

    我想看看机关操作?


    大概不会,根据您提供您的问题的描述。它始终是可能的,虽然。 LEA 工作方式类似,如&安培; 在C.运营商作为一个例子,该指令:

      12 LEA(ECX%),EDX%

    可以转化为我们的伪code为:

      EDX =及(*(ECX + 12))

    或者更简单地说:

      EDX = ECX + 12

    这个例子是一个有点傻,因为我们使用的是相对简单的寻址模式,但如何对这样的:

      LEA 1(%EDX,ECX%,4),EAX%

    这意味着:

      EAX =及(EDX [ECX * 4 + 1)


通常,这些各种各样的问题,最简单的方法是用C来写你的常规,然后编译和拆解结果。

编辑2:

您的示例程序似乎是对的,但你要在内存中解引用指针 - 让那些指针到寄存器第一,你应该确定

I'm rather new to assembly programming. I'm using the x86 platform with GCC (Linux).

I have a function that I want to call from C as:

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

The function will take the s1 and s2 memory locations and compare them, then increment and compare, etc., doing some processing as it goes. This is sort of like memcmp but I'm doing more.

My question: if I pass a pointer into an assembly function? And then how do I say "give me the value stored at this memory address"?

Here's what I have so far:

To get the first function arg ("s1") off the stack, I do this (someaddress is a 32-bit integer, and I'm working on a 32-bit processor):

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

If I put somevar into %eax (or %ebx, etc.) and then printf it with %p, I see that its address and the address of the unsigned char pointer "s1" I passed it are the same. But I suspect that what I've actually done is taken the memory address, converted it to an integer, and then put that integer in someaddress.

For example, if I then do this:

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

I get "Error: too many memory references for `cmp'". I'm not entirely certain what that means, except "you screwed up" ;-)

So...

  • how to pass a pointer in and keep it as a pointer?
  • how to use the value of said pointer in assembly? (e.g., like *ptr in C)

Do I want to look at the LEA operand?

I'm using Richard Blum's "Professional Assembly Programming" as my guide, but Blum doesn't seem to cover this case.

Update

Thank you very much for your learned response!

Unfortunately, I'm still not able to dereference.

Here is a simplified example. The assembly function takes a pointer and should echo it back. Instead I get:

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 Program:

#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;
}

Assembly program:

.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

解决方案

At least one of the operands to cmp has to be a register. If you're trying to compare the contents of two memory locations, you'll need to put one of them in a register. How to get it into a register you ask? Well you've done just that already with your example code. This line:

movl  8(%esp), %ecx

Takes the 4 bytes at %esp+8 and puts them into %ecx. In a C-like psuedocode:

ecx = *(esp + 8);

Hopefully that makes sense. You can do similar operations to get your pointers off of the stack and into registers, and then dereference them, compare the dereferenced values, and so on. Let me know if you have more questions!

Edit - your broken out questions:

  1. how to pass a pointer in and keep it as a pointer?

    You're already doing that, and your movl 8(%esp), %ecx instruction, or something like it will do everything you need.

  2. how to use the value of said pointer in assembly? (e.g., like *ptr in C)

    You need to use the () again - to load the first byte out of the pointer in %ecx from your instruction above, for example:

    movb (%ecx), %edx
    

    In the C-like pseudocode similar to how I used it above, this instruction is:

    edx = *(unsigned char *)ecx;
    

  3. Do I want to look at the LEA operand?

    Probably not, based on the description of your problem you've provided. It is always possible, though. lea works something like like the & operator in C. As an example, this instruction:

    lea 12(%ecx), %edx
    

    can be translated into our pseudocode as:

    edx = &(*(ecx + 12))
    

    or more simply:

    edx = ecx + 12
    

    This example is a bit silly, since we're using a relatively uncomplicated addressing mode, but how about something like this:

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

    which means:

    eax = &(edx[ecx * 4] + 1)
    

Often the easiest solution to these sorts of problems is to write your routine in C, then compile it and disassemble the results.

Edit 2:

Your example program seems almost right, but you're trying to dereference pointers in memory - get those pointers into registers first and you should be ok.

这篇关于指针传递到汇编函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆