很难弄清楚对汇编函数的调用返回了什么

时间:2018-10-05 23:28:44

标签: assembly x86

我是汇编语言的新手。我有以下汇编代码:

.intel_syntax noprefix
.bits 32

.global asm0

asm0:
    push    ebp
    mov ebp,esp
    mov eax,DWORD PTR [ebp+0x8]
    mov ebx,DWORD PTR [ebp+0xc]
    mov eax,ebx
    mov esp,ebp
    pop ebp 
    ret

我想弄清楚以下命令返回什么: asm0(0x2a,0x4f)。

我正在运行Ubuntu,并且已经下载了NASM。我一直在这里阅读汇编代码的语法:https://www.tutorialspoint.com/assembly_programming/assembly_basic_syntax.htm,但仍无法弄清楚。我已经用C ++编写了三年代码,但这仍然让我感到困惑。任何有更多经验的人都可以帮助我解决这个问题吗?

编辑:上面的代码说了推入和移动,因此它看起来像堆栈数据结构吗?然后它在最后返回。但是,此函数没有参数。怎么办?

运行gcc -m32 -g main.c程序集时出现错误消息。

myName@myName:~/Downloads$ gcc -m32 -g main.c file.S

main.c: In function ‘main’:

main.c:5:17: warning: implicit declaration of function ‘asm0’ [-Wimplicit-
function-declaration]

    printf("%d", asm0(123,456));
                 ^~~~

file.S: Assembler messages:

file.S:2: Error: unknown pseudo-op: `.bits'

1 个答案:

答案 0 :(得分:1)

您的函数在堆栈中返回地址上方查找其2个args。在设置了传统的堆栈框架之后,请注意对[ebp+8][ebp+12]的访问。

您不会在asm中声明args;这是一个高级概念,您可以自己在asm的代码中实现

push在调用堆栈上运行,而不是完全在堆栈数据结构上运行。  https://felixcloutier.com/x86/PUSH.html。它只是减少了ESP并存储到[esp]。这样做是为了保存/恢复调用者的EBP,这是制作传统堆栈框架的一部分。这是非常基础的内容,如果您还没看过,请阅读更多教程或指南。


您可以轻松地尝试代码,并通过C程序调用它来查找代码。

除非您不能,因为您的asm无法组装。 .bits 32不是有效的GAS指令,但是显然,这显然是GNU汇编程序(GAS)语法。除了GAS本身和clang的内置汇编程序外,我没有其他具有.intel_syntax noprefix指令的汇编程序,而且它们都不支持.bits 32。因此,我猜想此功能来自教程或其他内容,并且是通过NASM语法(bits 32)或其他内容手动移植到GAS的,未经实际测试。  但是您不需要也不应使用该指令或与GAS等效的.code32。汇编成32位目标文件时,默认值是32位代码,因此,如果您只使用.code32而不使用{,则gcc foo.s将允许您将32位代码汇编成64位目标文件。 {1}},然后您将遇到难以调试的问题,那就是运行时,而不是汇编时出现的明显错误。

因此,请删除-m32,以解决问题中的错误消息。

要摆脱警告消息,请提供适当的标题和原型,以扩展我在评论中写的单行代码。

.bits 32

该函数也是有问题的:它掩盖#include <stdio.h> int asm0(int,int); int main(){ printf("%d\n", asm0(123,456)); } ,这是i386 System V调用约定中的一个保留调用的寄存器。 (就像所有普通的x86调用约定一样。)

启用默认PIE的Linux发行版上的

gcc使得依赖于EBX的代码被保留并实际上崩溃了。 (不过,您仍然可以使用调试器进行单步调试,因为崩溃发生在ebx返回之后。)

但是您可以制作一个可执行的可执行文件,让您只运行它即可查看返回的arg:

asm0

peter@volta:/tmp$ gcc -g -Og -no-pie -fno-pie -m32 main.c asm0.s peter@volta:/tmp$ ./a.out 456 返回其第二个arg(通过将其复制到返回值寄存器EAX)。它将其加载到EBX,然后将EBX复制到EAX,覆盖第一个arg的加载结果。

您可以通过asm0

观看这种情况
gdb ./a.out

GDB突出显示了在每个步骤中更改了哪些寄存器。

有关更多调试提示,请参见https://stackoverflow.com/tags/x86/info的底部。


进一步阅读: