我对汇编编程很新。我正在使用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'的内存引用太多了”。我不完全确定这意味着什么,除了“你搞砸了”; - )
因此...
*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
答案 0 :(得分:8)
cmp
的至少一个操作数必须是寄存器。如果您要尝试比较两个内存位置的内容,则需要将其中一个放入寄存器中。怎么把它放到你问的寄存器里?那么你已经完成了你的示例代码。这一行:
movl 8(%esp), %ecx
占用%esp + 8的4个字节并将它们放入%ecx。在类似C的伪代码中:
ecx = *(esp + 8);
希望这是有道理的。您可以执行类似的操作,使指针离开堆栈并进入寄存器,然后取消引用它们,比较取消引用的值,等等。如果您有更多问题,请与我们联系!
编辑 - 您的问题:
如何传入指针并将其作为指针保存?
你已经这样做了,你的movl 8(%esp), %ecx
指令或类似的指令会做你需要的一切。
如何在程序集中使用所述指针的值? (例如,像C中的* ptr)
您需要再次使用()
- 从上面的指令加载%ecx
中指针的第一个字节,例如:
movb (%ecx), %edx
类似于我上面使用它的C类伪代码,这条指令是:
edx = *(unsigned char *)ecx;
我想查看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中编写例程,然后编译它并反汇编结果。
编辑2:
你的示例程序看起来几乎是正确的,但是你试图在内存中取消引用指针 - 首先将这些指针放到寄存器中,你应该没问题。