为什么出现错误24:也可能在asm中打开文件描述符

问题描述 投票:0回答:1

问题number1:

有这种鼻音:

section .data
dat db "write out this:%x", 0xa, 0x0

section .text
global main
extern printf
main:
    push rbp
    mov rbp, rsp
    mov rdi, dat
    mov esi, 0xdeedbeef
    call printf
    leave 
    ret

给出错误号24-打开太多文件描述符。

但如果更改为int 80h,而不是

    leave 
    ret

将终止错误,那是怎么回事?

另外,问题数字2]如果我没有通过:

进行呼叫约定
push rbp
mov rbp, rsp

并且仅是mov rbp, rsp,之前没有push调用rbp,然后是command terminated,尽管之前没有调用任何函数,所以不需要推送基址指针。那么,为什么需要它(在编译器看来)并且将终止?

linux x86-64 nasm calling-convention
1个回答
0
投票

问题1

您误认为这与文件描述符有关。这不是正在报告的内容。

正如您在注释中所解释的,24是运行程序后echo $?时显示的数字。这是程序的退出代码;通常,从main函数返回或传递给exit()的值。它可以是您想要的任何内容,通常not对应于errno值。

那么为什么您的程序给出的退出代码为24?如果返回main,则退出代码为其返回值。函数返回时,它的返回值应保留在rax寄存器中(假定它是整数或指针类型)。但是您永远不要触摸rax寄存器,因此它仍然包含printf返回时保留在其中的值。现在printf返回成功打印的字符数,对于您选择的字符串,该字符数是... 24(计数'em)。

这只是一个巧合,errno代码的“打开的文件描述符太多”也发生了24个-这是完全不相关的。

如果要以成功的退出代码0退出以表示成功,则应在xor rax, rax之前添加ret。>>

您未显示将其更改为int 0x80来自己调用_exit syscall时使用的确切代码。但是在那种情况下,退出代码将是您进行系统调用时ebx寄存器中的代码。也许您的代码在ebx中放置了零,或者也许您很幸运,它恰好已经包含零。

[位系统调用接口使用int 0x80指令,并在ABI的A.2.1中进行了说明。)

问题2

您必须对齐纸叠。[从汇编中调用C函数时(在这种情况下为syscall),printf要求将堆栈对齐到16字节边界。堆栈在对the x86-64 ABI Section 3.2.2的调用之前[[before

适当对齐,并且main推送的返回地址减去8个字节。

因此,如果您根本不触摸代码中的堆栈,则在调用call时将无法正确对齐堆栈,这可能导致崩溃。 (汇编程序不会帮助您执行此操作;这不是它的工作。)但是,当您按printf时,它将再减去8个字节,并使堆栈正确对齐。因此,要么保留该代码,要么自己对齐堆栈。

并且无论哪种情况,请记住,如果更改代码以将更多内容压入堆栈,则在进行任何函数调用之前,必须进行相应的调整。
© www.soinside.com 2019 - 2024. All rights reserved.