c/c++语言开发共享从Assembly调用C函数(printf)时的Segfault

我在linux上使用NASM编写一个基本的汇编程序,它从C库(printf)调用一个函数。 不幸的是,我这样做会导致分段错误。 注释掉对printf的调用允许程序无错误地运行。

; Build using these commands: ; nasm -f elf64 -g -F stabs .asm ; gcc .o -o  ; SECTION .bss ; Section containing uninitialized data SECTION .data ; Section containing initialized data text db "hello world",10 ; SECTION .text ; Section containing code global main extern printf ;------------- ;MAIN PROGRAM BEGINS HERE ;------------- main: push rbp mov rbp,rsp push rbx push rsi push rdi ;preserve registers **************** ;code i wish to execute push text ;pushing address of text on to the stack ;x86-64 uses registers for first 6 args, thus should have been: ;mov rdi,text (place address of text in rdi) ;mov rax,0 (place a terminating byte at end of rdi) call printf ;calling printf from c-libraries add rsp,8 ;reseting the stack to pre "push text" ************** pop rdi ;preserve registers pop rsi pop rbx mov rsp,rbp pop rbp ret 

    x86_64不使用堆栈作为前6个args。 您需要将它们加载到适当的寄存器中。 那些是:

     rdi, rsi, rdx, rcx, r8, r9 

    我用来记住前两个的技巧是想象这个函数是作为rep movsb实现的memcpy

    您需要熟悉正在使用的调用约定。 AMD64上的Linux使用System V AMD64 ABI 。 从该文件中我们了解到:

    所以对于电话

     printf ("Hello Worldn"); 

    你有

     .section .rodata format db "Hello World", 10, 0 .section .text my_function: ; with RSP 16-byte aligned mov edi, format ; or in PIC code: lea rdi, [rel format] ; mov rsi, 2nd arg if any xor eax, eax ; no FP args call printf 

    注意字符串上的0终止符:C字符串是隐式长度,以0字节结尾。

    你正在调用一个varargs函数 – printf需要一个可变数量的参数,你必须在参数堆栈中考虑它。 见这里: http : //www.csee.umbc.edu/portal/help/nasm/sample.shtml#printf1

      以上就是c/c++开发分享从Assembly调用C函数(printf)时的Segfault相关内容,想了解更多C/C++开发(异常处理)及C/C++游戏开发关注计算机技术网(www.ctvol.com)!)。

      本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。

      ctvol管理联系方式QQ:251552304

      本文章地址:https://www.ctvol.com/c-cdevelopment/519245.html

      (0)
      上一篇 2020年12月5日
      下一篇 2020年12月5日

      精彩推荐