asm.s程序第39行中(以下片段第21行处),有个call函数调用代码,如下:
_divide_error:
pushl $_do_divide_error
no_error_code:
xchgl %eax,(%esp)
pushl %ebx
pushl %ecx
pushl %edx
pushl %edi
pushl %esi
pushl %ebp
push %ds
push %es
push %fs
pushl $0 # "error code"
lea 44(%esp),%edx
pushl %edx
movl $0x10,%edx
mov %dx,%ds
mov %dx,%es
mov %dx,%fs
call *%eax
addl $8,%esp
pop %fs
pop %es
pop %ds
popl %ebp
popl %esi
popl %edi
popl %edx
popl %ecx
popl %ebx
popl %eax
iret
对于这条函数调用指令,很奇怪为啥会有个'*'前缀。在GNU《using as-The GNU Assembler》文档8.10.6节中,找到一句话,如下:
这段话是说,绝对地址的call和jump操作,需要加上'*'前缀,如果没有'*'前缀,as始终选择PC相对寻址。也就是说,如果没有这个'*'前缀,最终调用地址会加上PC寄存器里面的值。这当然就不是我们想要的了。