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 .data
intFormatShow:
.ascii "%d\n\0"
.global main
.section .text
main:
pushq %rbp
movq %rsp,%rbp
movq $2,%rdi
movq $3,%rsi
call twoNumberPlus
movq %rax,%rsi
movq $intFormatShow,%rdi
movq $0,%rax
call printf
movq $60,%rax
movq $0,%rdi
movq %rbp,%rsp
popq %rbp
syscall
twoNumberPlus:
pushq %rbp
movq %rsp,%rbp
addq %rdi,%rsi
movq %rsi,%rax
movq %rbp,%rsp
popq %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 .data
intFormatShow:
.ascii "%d\n\0"
.global main
.section .text
main:
pushq %rbp
movq %rsp,%rbp
movq $2,%rdi
movq $3,%rsi
call twoNumberPlus
movq %rax,%rsi
movq $intFormatShow,%rdi
movq $0,%rax
call printf
movq $60,%rax
movq $0,%rdi
movq %rbp,%rsp
popq %rbp
syscall
twoNumberPlus:
pushq %rbp
movq %rsp,%rbp
addq %rdi,%rsi
movq %rsi,%rax
movq %rbp,%rsp
popq %rbp
ret
gcc twoNumberPlus.s -static -o twoNumberPlus
进行编译。
./twoNumberPlus
执行,得出正确的结果5
。