ald> disassemble -s .textDisassembling section .text (0x08048074 - 0x08048096)08048074 BA0F000000 mov edx, 0xf08048079 B998900408 mov ecx, 0x80490980804807E BB01000000 mov ebx, 0x108048083 B804000000 mov eax, 0x408048088 CD80 int 0x800804808A BB00000000 mov ebx, 0x00804808F B801000000 mov eax, 0x108048094 CD80 int 0x80 上述输出信息的第一列是指令对应的地址码,利用它可以设置在程序执行时的断点: ald> break 0x08048088Breakpoint 1 set for 0x08048088 断点设置好后,使用 run 命令开始执行程序。ALD 在遇到断点时将自动暂停程序的运行,同时会显示所有寄存器的当前值: ald> runStarting program: helloBreakpoint 1 encountered at 0x08048088eax = 0x00000004 ebx = 0x00000001 ecx = 0x08049098 edx = 0x0000000Fesp = 0xBFFFF6C0 ebp = 0x00000000 esi = 0x00000000 edi = 0x00000000ds = 0x0000002B es = 0x0000002B fs = 0x00000000 gs = 0x00000000ss = 0x0000002B cs = 0x00000023 eip = 0x08048088 eflags = 0x00000246Flags: PF ZF IF08048088 CD80 int 0x80 如果需要对汇编代码进行单步调试,可以使用 next 命令: ald> nextHello, world!eax = 0x0000000F ebx = 0x00000000 ecx = 0x08049098 edx = 0x0000000Fesp = 0xBFFFF6C0 ebp = 0x00000000 esi = 0x00000000 edi = 0x00000000ds = 0x0000002B es = 0x0000002B fs = 0x00000000 gs = 0x00000000ss = 0x0000002B cs = 0x00000023 eip = 0x0804808F eflags = 0x00000346Flags: PF ZF TF IF0804808F B801000000 mov eax, 0x1 若想获得 ALD 支持的所有调试命令的详细列表,可以使用 help 命令: ald> helpCommands may be abbreviated.If a blank command is entered, the last command is repeated.Type `help <command>' for more specific information on <command>.General commandsattach clear continue detach disassembleenter examine file help loadnext quit register run setstep unload window writeBreakpoint related commandsbreak delete disable enable ignorelbreak tbreak 五、系统调用 即便是最简单的汇编程序,也难免要用到诸如输入、输出以及退出等操作,而要进行这些操作则需要调用操作系统所提供的服务,也就是系统调用。除非你的程序只完成加减乘除等数学运算,否则将很难避免使用系统调用,事实上除了系统调用不同之外,各种操作系统的汇编编程往往都是很类似的。 在 Linux 平台下有两种方式来使用系统调用:利用封装后的 C 库(libc)或者通过汇编直接调用。其中通过汇编语言来直接调用系统调用,是最高效地使用 Linux 内核服务的方法,因为最终生成的程序不需要与任何库进行链接,而是直接和内核通信。 和 DOS 一样,Linux 下的系统调用也是通过中断(int 0x80)来实现的。在执行 int 80 指令时,寄存器 eax 中存放的是系统调用的功能号,而传给系统调用的参数则必须按顺序放到寄存器 ebx,ecx,edx,esi,edi 中,当系统调用完成之后,返回值可以在寄存器 eax 中获得。 所有的系统调用功能号都可以在文件 /usr/include/bits/syscall.h 中找到,为了便于使用,它们是用 SYS_<name> 这样的宏来定义的,如 SYS_write、SYS_exit 等。例如,经常用到的 write 函数是如下定义的: ssize_t write(int fd, const void *buf, size_t count); 该函数的功能最终是通过 SYS_write 这一系统调用来实现的。根据上面的约定,参数 fb、buf 和 count 分别存在寄存器 ebx、ecx 和 edx 中,而系统调用号 SYS_write 则放在寄存器 eax 中,当 in | | | | | |