当前位置: 首页 > news >正文

linux nasm汇编中调用printf不报错,但调用scanf报错。抛出了分段错误(核心转储)

当我写了如下汇编时

; nasm -f elf64 -g -F dwarf charsin.asm
; gcc charsin.o -no-pie -o charsin
; ld -o eatclib eatclib.o
; gdb eatclib[SECTION .data]SPrompt db 'Enter string data, followed by Enter: ',0IPrompt db 'Enter an integer value, followed by Enter: ',10,0IFormat db "%d",0SShow db 'The string you entered was: %s',0IShow db 'The Integer value you entered was: %5d',10,0[SECTION .bss]IntVal resd 1InString resb 128 [SECTION .text]extern stdinextern fgetsextern printfextern scanfglobal mainmain:push rbpmov rbp,rsppush rbxpush rsipush rdi;push SPromptmov rdi,SPrompt ; 传递参数mov rax,0call printf;add rsp,8; rdi,rsi,rdx,rcx分别保存第1,2,3,4个参数;push qword [stdin];push 72;push InStringmov rdi,InStringmov rsi,72mov rdx,[stdin]mov rax,0call fgets;add rsp,24;push InString;push SShowmov rdi,SShowmov rsi,InString;在汇编代码中,若是调用变长参数的函数,需要使用al这个寄存器记录使用到的向量寄存器数量。;这段代码中eax中存放的不是系统调用号,存放的是向量寄存器使用到的数量0,因为printf使用的是变长参数。mov rax,0call printf;add rsp,16mov rax,0push IPromptmov rdi,IPrompt ; 传递参数call printfadd rsp,8;push IntVal;push IFormatmov rdi,IFormat mov rsi,IntVal ; 保留数字的内存地址xor rax,raxcall scanf;add rsp,16;mov rax, 0  ;sys_read 系统调用号;mov rdi, 0  ; 文件描述符 标准输入;mov rsi,IntVal ; 保留数字的内存地址;mov rdx, 4;syscallxor rsi,rsimov rax,0mov rdi,IShow ; 传递格式参数mov esi,[IntVal]call printf;add rsp,16pop rdipop rsipop rbxmov rsp,rbppop rbpret

编译后,系统会如下段错误(Segmentation fault (core dumped)).
在这里插入图片描述

在函数的开始/结束处使用 sub rsp, 8/add rsp, 8 将堆栈重新对齐到 16函数执行调用之前的字节。

; nasm -f elf64 -g -F dwarf charsin.asm
; gcc charsin.o -no-pie -o charsin
; ld -o eatclib eatclib.o
; gdb eatclib[SECTION .data]SPrompt db 'Enter string data, followed by Enter: ',0IPrompt db 'Enter an integer value, followed by Enter: ',10,0IFormat db "%d",0SShow db 'The string you entered was: %s',0IShow db 'The Integer value you entered was: %5d',10,0[SECTION .bss]IntVal resd 1InString resb 128 [SECTION .text]extern stdinextern fgetsextern printfextern scanfglobal mainmain:push rbpmov rbp,rsppush rbxpush rsipush rdi;在函数的开始/结束处使用 sub rsp, 8/add rsp, 8 将堆栈重新对齐到 16函数执行调用之前的字节。sub rsp, 8;push SPromptmov rdi,SPrompt ; 传递参数mov rax,0call printf;add rsp,8; rdi,rsi,rdx,rcx分别保存第1,2,3,4个参数;push qword [stdin];push 72;push InStringmov rdi,InStringmov rsi,72mov rdx,[stdin]mov rax,0call fgets;add rsp,24;push InString;push SShowmov rdi,SShowmov rsi,InString;在汇编代码中,若是调用变长参数的函数,需要使用al这个寄存器记录使用到的向量寄存器数量。;这段代码中eax中存放的不是系统调用号,存放的是向量寄存器使用到的数量0,因为printf使用的是变长参数。mov rax,0call printf;add rsp,16mov rax,0push IPromptmov rdi,IPrompt ; 传递参数call printfadd rsp,8;push IntVal;push IFormatmov rdi,IFormat mov rsi,IntVal ; 保留数字的内存地址xor rax,raxcall scanf;add rsp,16;mov rax, 0  ;sys_read 系统调用号;mov rdi, 0  ; 文件描述符 标准输入;mov rsi,IntVal ; 保留数字的内存地址;mov rdx, 4;syscallxor rsi,rsimov rax,0mov rdi,IShow ; 传递格式参数mov esi,[IntVal]call printf;add rsp,16;在函数的开始/结束处使用 sub rsp, 8/add rsp, 8 将堆栈重新对齐到 16函数执行调用之前的字节。add rsp, 8pop rdipop rsipop rbxmov rsp,rbppop rbpret

编译后,程序运行正常。
在这里插入图片描述

参考段错误
StackOverflow

http://www.lryc.cn/news/308375.html

相关文章:

  • Linux系统——Nginx负载均衡模式
  • 【自然语言处理之语言模型】讲解
  • 输入一个整数n,输出这个整数的二进制的0和1的个数
  • 初阶数据结构:链表相关题目练习(补充)
  • java: 错误: 不支持发行版本 5
  • springSecruity--->和springboot结合的跨域问题
  • 网关kong记录接口处理请求和响应插件 tcp-log-with-body的安装
  • ElasticSearch之Completion Suggester
  • ant 布局组件 组件等高设置
  • 不可多得的干货,网易的朋友给我这份339页的Android面经
  • Qt项目:网络1
  • 软件测试有哪些常用的测试方法?
  • 【C语言基础】:深入理解指针(一)
  • 单点故障解决方案之Smart Link与Monitor Link
  • QT之QSharedMemory共享内存
  • string 类 经典习题之数字字符相加
  • 通讯录——C语言实现
  • 优思学院|3步骤计算出Cpk|学习Minitab
  • 【Java编程进阶之路 06】深入探索:JDK、JRE与JVM的关系与差异
  • Linux中的touch命令
  • 智能驾驶规划控制理论学习-基于采样的规划方法
  • 二叉树——二叉树所有路径
  • 算法训练营day38(补),动态规划6
  • 【java、微服务、nacos】nacos服务分级存储模型
  • 共享旅游卡:打开0费用旅游新纪元,探索40+精彩线路
  • MQTT协议解析:揭秘固定报头、可变报头与有效载荷的奥秘
  • 备战蓝桥杯---树形DP基础3
  • IEEE Transactions on Industrial Electronics工业电子TIE修改稿注意事项及提交须知
  • c#委托的三种实现方式
  • c/c++|红黑树|分析应用|锚点