我对汇编编程很新.我正在使用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)
至少有一个操作数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)
希望这是有道理的.您可以执行类似的操作,使指针离开堆栈并进入寄存器,然后取消引用它们,比较取消引用的值,等等.如果您有更多问题,请告诉我们!
编辑 - 你的问题:
如何传入指针并将其作为指针保存?
你已经这样做了,你的movl 8(%esp), %ecx指导或类似的东西会做你需要的一切.
如何在程序集中使用所述指针的值?(例如,像C中的*ptr)
您需要()再次使用- %ecx从上面的指令中加载指针的第一个字节,例如:
movb (%ecx), %edx
Run Code Online (Sandbox Code Playgroud)
在类似C的伪代码中,类似于我上面的使用方式,这条指令是:
edx = *(unsigned char *)ecx;
Run Code Online (Sandbox Code Playgroud)我想查看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:
你的榜样方案似乎是对的,但你试图取消引用指针在内存中 - 让这些指针到寄存器第一,你应该确定.