cat /etc/redhat-release
看到操作系统是CentOS Linux release 7.6.1810
,uname -r
看到内核版本是3.10.0-957.el7.x86_64
,gcc --version
可以看到gcc
版本是12.2.0
,gdb --version
可以看到gdb
版本是12.1
。
twoNumberPlus.s
里边的内容如下:
.type twoNumberPlus, @function
.section .dataintFormatShow:.ascii "%d\n\0".global main.section .textmain:pushq %rbpmovq %rsp,%rbpmovq $2,%rdimovq $3,%rsicall twoNumberPlusmovq %rax,%rsimovq $intFormatShow,%rdimovq $0,%raxcall printfmovq $60,%raxmovq $0,%rdimovq %rbp,%rsppopq %rbpsyscalltwoNumberPlus:pushq %rbpmovq %rsp,%rbpaddq %rdi,%rsimovq %rsi,%raxmovq %rbp,%rsppopq %rbp
gcc twoNumberPlus.s -static -o twoNumberPlus
进行编译。
./twoNumberPlus
执行,发现报错Segmentation fault
。
gcc -g twoNumberPlus.s -static -o twoNumberPlus
带有调试信息编译,然后使用gdb -q twoNumberPlus
进行调试。
在gdb
命令行里边输入run
运行程序,却发现应该显示函数名的地方,却显示?? ()
,看了https://stackoverflow.com/questions/40475306/why-doesnt-gdb-show-line-numbers-or-function-names才发现自己的代码把一些栈给破坏了,这部分破坏的栈正好包括gdb知道程序所在位置的信息。
自己看了《x64汇编语言》这本书105页,才发现,原来是忘记在twoNumberPlus
函数最后写上ret
这条指令了,正确的代码如下:
.type twoNumberPlus, @function
.section .dataintFormatShow:.ascii "%d\n\0".global main.section .textmain:pushq %rbpmovq %rsp,%rbpmovq $2,%rdimovq $3,%rsicall twoNumberPlusmovq %rax,%rsimovq $intFormatShow,%rdimovq $0,%raxcall printfmovq $60,%raxmovq $0,%rdimovq %rbp,%rsppopq %rbpsyscalltwoNumberPlus:pushq %rbpmovq %rsp,%rbpaddq %rdi,%rsimovq %rsi,%raxmovq %rbp,%rsppopq %rbpret
gcc twoNumberPlus.s -static -o twoNumberPlus
进行编译。
./twoNumberPlus
执行,得出正确的结果5
。