我正在linux上使用nasm编写汇编语言程序。问题是在使用gdb调试期间它没有进入_start函数并给出消息“单步执行直到退出函数_start”,
另外,当我在第1行之后设置断点时,它说:
(gdb) break 2
Note: breakpoints 1 and 2 also set at pc 0x4000b0.
Breakpoint 3 at 0x4000b0: file new3.asm, line 2.
(gdb) break 3
Note: breakpoints 1, 2 and 3 also set at pc 0x4000b0.
Breakpoint 4 at 0x4000b0: file new3.asm, line 3.
我正在使用命令组装和链接它:
nasm -g -f elf64 new3.asm
ld -g new3.o
然后我使用gdb new3.out
调试它。 gdb版本是7.11.1
该计划如下:
section .text
global _start ;must be declared for linker (ld)
_start: ;tells linker entry point
call sum
mov edx,len ;message length
mov ecx,msg ;message to write
mov ebx,1 ;file descriptor (stdout)
mov eax,4 ;system call number (sys_write)
int 0x80 ;call kernel
mov eax,1 ;system call number (sys_exit)
int 0x80 ;call kernel
sum:
mov eax, ecx
add eax, edx
add eax, '0'
ret
section .data
msg db 'Hello, world!', 0xa ;string to be printed
len equ $ - msg ;length of the string
我如何进入_start进行调试,这是什么意思?
(gdb) break 3
Note: breakpoints 1, 2 and 3 also set at pc 0x4000b0.
Breakpoint 4 at 0x4000b0: file new3.asm, line 3.
答案 0 :(得分:2)
使用nasm -f elf64 -F dwarf -g new3.asm
制作矮人调试信息,而不是默认(stabs)。 (使用nasm -felf64 -y
查看默认值)。 yasm -felf64 -gdwarf2 new3.asm
也有效。 (实际上单步执行即使你遗漏-gdwarf2
为yasm:我猜它默认包含足够的。)
然后gdb将能够通过源代码行单步执行,而不仅仅通过指令(stepi
)。您不需要ld -g
,它不会做任何事情。
您可能还应该直接与gcc -nostdlib -g new3.o
链接,而不是ld。如果您向ld命令行添加了任何动态库,那么您将有一个损坏的二进制文件(因为ld的默认ELF解释器路径在现代x86-64多系统系统上没有用)。请参阅Building an executable from asm source that defines _start
vs. main
, static or dynamic。
另外,请勿使用64位代码中的int 0x80
32位ABI。
使用stepi
(或si
)逐步说明而不是按来源行。
使用b *0x4000b0
根据数字地址设置断点。或者使用标签名称,例如b _start
在入口点设置断点。
有关使用gdb调试asm的更多提示,请参阅x86标记wiki的底部。
您文件中的第一条指令位于第4行,因此b 1
和b 4
都在CALL指令上设置了断点,这就不足为奇了。
b 5
确实在CALL之后的指令上设置断点。即使gdb只有STABS调试信息(不是DWARF或DWARF2),这部分也能正常工作,但单步执行则不行。 IDK为什么。
(gdb) b _start
Breakpoint 1 at 0x4000b0
(gdb) b 5
Breakpoint 2 at 0x4000b5: file new3.asm, line 5.
(gdb) r
Starting program: /home/peter/src/SO/a.out
Breakpoint 1, 0x00000000004000b0 in _start ()