首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >很难计算出对程序集函数的调用返回什么

很难计算出对程序集函数的调用返回什么
EN

Stack Overflow用户
提问于 2018-10-05 23:28:43
回答 1查看 856关注 0票数 0

我对汇编语言很陌生。我有以下汇编代码:

代码语言:javascript
复制
.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。我在这里读到了汇编代码的语法:syntax.htm,但我仍然无法理解这一点。我已经用C++编写了三年代码,但这仍然让我感到困惑。有更多经验的人能帮我解决这个问题吗?

编辑:上面的代码是推送和移动,所以它看起来有点像堆栈数据结构?然后它会在最后返回。但是,这个函数没有参数。这怎么做呢?

运行gcc -m32 -g main.c汇编.s时出现的错误消息

代码语言:javascript
复制
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'
EN

回答 1

Stack Overflow用户

发布于 2018-10-06 02:12:40

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

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

push操作于调用堆栈,而不是堆栈数据结构。https://felixcloutier.com/x86/PUSH.html。它只是减少电除尘器,并存储到[esp]。它这样做是为了保存/恢复调用者的EBP,作为创建传统堆栈框架的一部分。这是非常基本的东西,如果你还没看过,请阅读更多的教程或指南。

您可以很容易地尝试代码并通过从C程序调用它来找到它所做的事情。

但你不能因为你的asm不能组装。.bits 32不是一个有效的GAS指令,但这显然是GNU (GAS)的语法。我不知道除了GAS本身和clang的内置汇编程序之外,没有任何汇编程序有.intel_syntax noprefix指令,而且它们都不支持.bits 32。因此,我猜想这个函数来自于一个教程或者什么的,并且是手工移植到NASM语法(bits 32)或者其他什么东西上,而没有进行实际的测试。但是你不需要,也不应该使用那个指令,或者气体等效的.code32。在将32位代码组装为32位对象文件时,32位代码已经是默认的,因此,如果您只使用没有.code32gcc foo.s,则可以将32位代码组装成64位的对象文件,然后就会遇到运行时难以调试的问题,而不是在组装时出现明显的错误。

因此,删除.bits 32 ,以解决问题中的错误消息。

为了消除警告消息,通过提供适当的标题和原型,扩展我在评论中写的一行代码。

代码语言:javascript
复制
#include <stdio.h>
int asm0(int,int);

int main(){
    printf("%d\n", asm0(123,456));
}

这个函数也有问题:它破坏了ebx,这是i386 System调用约定中的一个呼叫保存寄存器。(就像所有正常的x86调用约定一样。)

gcc在Linux发行版上启用默认饼,生成依赖于EBX的代码被调用保护,并且实际上崩溃了。(不过,您仍然可以使用调试器单步执行,因为崩溃发生在asm0返回之后。)

但是,您可以创建一个碰巧工作的可执行文件,并允许您运行它来查看它返回的是哪个arg:

代码语言:javascript
复制
peter@volta:/tmp$ gcc -g -Og -no-pie -fno-pie -m32 main.c asm0.s 
peter@volta:/tmp$ ./a.out 
456

asm0 返回它的第二个arg (通过将它复制到EAX,返回值寄存器)。它将其加载到EBX,然后将EBX复制到EAX,覆盖加载第一个arg.的结果。

您可以在gdb ./a.out中看到这种情况。

代码语言:javascript
复制
(gdb)  layout reg
       b main
       r
       si
       (press return to single-step one instruction at a time through the code, including into your function)

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

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

进一步读:

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52674400

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档