我正在 Oracle Enterprise Linux 7.3 VM 上学习 x86-64 程序集。我有一个简单的程序,它在 gdb 之外运行良好,但如果我设置断点并运行程序,则会出现分段错误。我已经将它缩减为一个非常小的程序,但想知道我是否做错了什么,或者它是否只是一个 gdb 错误。这是文件 ex1.asm 的源代码:
segment .data
a dd 1
segment .text
global _start
_start:
mov eax,4
ltop:
mov ebx,[a]
; exit with return code 0
mov eax,60
mov edi,0
syscall
end
我像这样组装、链接它并在 gdb 中运行它:
yasm -f elf64 -g dwarf2 -l ex1.lst ex1.asm; ld -o ex1.exe ex1.o; gdb ex1.exe
以下是 gdb 会话的运行方式:
(gdb) l
1 segment .data
2 a dd 1
3 segment .text
4 global _start
5 _start:
6 mov eax,4
7 ltop:
8 mov ebx,[a]
9 ; exit with return code 0
10 mov eax,60
(gdb) b 8
Breakpoint 1 at 0x4000ba: file ex1.asm, line 8.
(gdb) r
Starting program: /home/bobby/gdbbug/ex1.exe
Program received signal SIGSEGV, Segmentation fault.
ltop () at ex1.asm:6
6 mov eax,4
我有一个简单的解决方法。我只是在 _start 标签之后添加了一个不需要的异或。
(gdb) l
1 segment .data
2 a dd 1
3 segment .text
4 global _start
5 _start:
6 xor eax,eax
7 mov eax,4
8 ltop:
9 mov ebx,[a]
10 ; exit with return code 0
(gdb) b 9
Breakpoint 1 at 0x4000b7: file ex1.asm, line 9.
(gdb) r
Starting program: /home/bobby/gdbbug/ex1.exe
Breakpoint 1, ltop () at ex1.asm:9
9 mov ebx,[a]
删除 ltop 标签也可以,但是我为这个示例缩减的较大的原始程序需要该标签,所以这不是一个很好的解决方法。
(gdb) l
1 segment .data
2 a dd 1
3 segment .text
4 global _start
5 _start:
6 mov eax,4
7 ;ltop:
8 mov ebx,[a]
9 ; exit with return code 0
10 mov eax,60
(gdb) b 8
Breakpoint 1 at 0x4000b5: file ex1.asm, line 8.
(gdb) r
Starting program: /home/bobby/gdbbug/ex1.exe
Breakpoint 1, _start () at ex1.asm:8
8 mov ebx,[a]
有点奇怪。也许有一些明显的我做错了,但它看起来更像是一个 gdb 错误。
谢谢,鲍比
基于评论的附加信息:
(gdb) l
1 segment .data
2 a dd 1
3 segment .text
4 global _start
5 _start:
6 mov eax,4
7 ltop:
8 mov ebx,[a]
9 ; exit with return code 0
10 mov eax,60
(gdb) b 8
Breakpoint 1 at 0x4000ba: file ex1.asm, line 8.
(gdb) r
Starting program: /home/bobby/gdbbug/ex1.exe
Program received signal SIGSEGV, Segmentation fault.
ltop () at ex1.asm:6
6 mov eax,4
(gdb) q
A debugging session is active.
Inferior 1 [process 4184] will be killed.
Quit anyway? (y or n) y
[bobby@assembly gdbbug]$ objdump -D ex1.exe
ex1.exe: file format elf64-x86-64
Disassembly of section .text:
00000000004000b0 <_start>:
4000b0: b8 04 00 00 00 mov $0x4,%eax
00000000004000b5 <ltop>:
4000b5: 8b 1c 25 c8 00 60 00 mov 0x6000c8,%ebx
4000bc: b8 3c 00 00 00 mov $0x3c,%eax
4000c1: bf 00 00 00 00 mov $0x0,%edi
4000c6: 0f 05 syscall
看来评论可能是正确的。如果我正确读取转储,则 move to ebx 语句从 4000b5 开始,但断点设置在 mov 指令字节内的 4000ba 处。
这就是我注释掉 ltop 标签时发生的情况:
(gdb) b 8
Breakpoint 1 at 0x4000b5: file ex1.asm, line 8.
(gdb) r
Starting program: /home/bobby/gdbbug/ex1.exe
Breakpoint 1, _start () at ex1.asm:8
8 mov ebx,[a]
断点位于转储中的 0x4000b5 处:
00000000004000b0 <_start>:
4000b0: b8 04 00 00 00 mov $0x4,%eax
4000b5: 8b 1c 25 c8 00 60 00 mov 0x6000c8,%ebx
谢谢回复。
我使用 nasm 使用此命令行重新进行了此操作:
nasm -f elf64 ex1.asm -o ex1.o -l ex1.lst -g -F dwarf; ld -o ex1.exe ex1.o; gdb ex1.exe
它工作得很好。因此,正如评论所建议的,这似乎是 yasm 和调试的问题。